1#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
2pub struct RemoteLashlangProcessRef {
3 pub component: String,
4 pub pos: u32,
5}
6
7impl RemoteLashlangProcessRef {
8 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
9 require_non_empty(type_name, "process_ref.component", &self.component)
10 }
11}
12
13#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
14pub struct RemoteSessionScope {
15 pub session_id: String,
16 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub agent_frame_id: Option<String>,
18}
19
20impl RemoteSessionScope {
21 pub fn new(session_id: impl Into<String>) -> Self {
22 Self {
23 session_id: session_id.into(),
24 agent_frame_id: None,
25 }
26 }
27
28 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
29 require_non_empty(type_name, "session_id", &self.session_id)?;
30 if let Some(agent_frame_id) = &self.agent_frame_id {
31 require_non_empty(type_name, "agent_frame_id", agent_frame_id)?;
32 }
33 Ok(())
34 }
35}
36
37#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
38#[serde(tag = "type", rename_all = "snake_case")]
39pub enum RemoteProcessOriginator {
40 Host,
41 Session { scope: RemoteSessionScope },
42}
43
44impl RemoteProcessOriginator {
45 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
46 match self {
47 Self::Host => Ok(()),
48 Self::Session { scope } => scope.validate(type_name),
49 }
50 }
51}
52
53#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
54pub struct RemoteProcessProvenance {
55 pub originator: RemoteProcessOriginator,
56 pub host_profile_id: String,
57 #[serde(default, skip_serializing_if = "Option::is_none")]
58 pub caused_by: Option<RemoteCausalRef>,
59}
60
61impl RemoteProcessProvenance {
62 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
63 self.originator.validate(type_name)?;
64 require_non_empty(type_name, "host_profile_id", &self.host_profile_id)
65 }
66}
67
68#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
69pub struct RemoteProcessDefinitionIdentity {
70 pub module_ref: String,
71 pub host_requirements_ref: String,
72 pub process_ref: RemoteLashlangProcessRef,
73 pub process_name: String,
74}
75
76impl RemoteProcessDefinitionIdentity {
77 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
78 require_non_empty(type_name, "module_ref", &self.module_ref)?;
79 require_non_empty(type_name, "host_requirements_ref", &self.host_requirements_ref)?;
80 self.process_ref.validate(type_name)?;
81 require_non_empty(type_name, "process_name", &self.process_name)
82 }
83}
84
85#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
86pub struct RemoteProcessDefinitionSummary {
87 pub name: String,
88}
89
90impl RemoteProcessDefinitionSummary {
91 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
92 require_non_empty(type_name, "definition.name", &self.name)
93 }
94}
95
96#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
97pub struct RemoteProcessHandleDescriptor {
98 #[serde(default, skip_serializing_if = "Option::is_none")]
99 pub kind: Option<String>,
100 #[serde(default, skip_serializing_if = "Option::is_none")]
101 pub label: Option<String>,
102}
103
104impl RemoteProcessHandleDescriptor {
105 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
106 if let Some(kind) = &self.kind {
107 require_non_empty(type_name, "descriptor.kind", kind)?;
108 }
109 if let Some(label) = &self.label {
110 require_non_empty(type_name, "descriptor.label", label)?;
111 }
112 Ok(())
113 }
114}
115
116#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
117pub struct RemoteProcessStartGrant {
118 pub session_scope: RemoteSessionScope,
119 pub descriptor: RemoteProcessHandleDescriptor,
120}
121
122impl RemoteProcessStartGrant {
123 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
124 self.session_scope.validate(type_name)?;
125 self.descriptor.validate(type_name)
126 }
127}
128
129#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
130#[serde(tag = "type", rename_all = "snake_case")]
131pub enum RemoteProcessInput {
132 ToolCall {
133 #[serde(default)]
134 prepared_tool_call: serde_json::Value,
135 },
136 LashlangProcess {
137 module_ref: String,
138 process_ref: RemoteLashlangProcessRef,
139 host_requirements_ref: String,
140 process_name: String,
141 #[serde(default, skip_serializing_if = "serde_json::Map::is_empty")]
142 args: serde_json::Map<String, serde_json::Value>,
143 },
144 SessionTurn {
145 #[serde(default)]
146 create_request: serde_json::Value,
147 turn_input: RemoteTurnInput,
148 #[serde(default, skip_serializing_if = "RemoteToolOutputContract::is_static")]
149 output_contract: RemoteToolOutputContract,
150 },
151 External {
152 #[serde(default)]
153 metadata: serde_json::Value,
154 },
155}
156
157impl RemoteProcessInput {
158 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
159 match self {
160 Self::ToolCall {
161 prepared_tool_call: _,
162 } => Ok(()),
163 Self::LashlangProcess {
164 module_ref,
165 process_ref,
166 host_requirements_ref,
167 process_name,
168 args: _,
169 } => {
170 require_non_empty(type_name, "module_ref", module_ref)?;
171 process_ref.validate(type_name)?;
172 require_non_empty(type_name, "host_requirements_ref", host_requirements_ref)?;
173 require_non_empty(type_name, "process_name", process_name)
174 }
175 Self::SessionTurn {
176 create_request: _,
177 turn_input,
178 output_contract,
179 } => {
180 turn_input.validate()?;
181 match output_contract {
182 RemoteToolOutputContract::Static => Ok(()),
183 RemoteToolOutputContract::FromInputSchema {
184 input_field,
185 default_schema: _,
186 } => require_non_empty(type_name, "output_contract.input_field", input_field),
187 }
188 }
189 Self::External { metadata: _ } => Ok(()),
190 }
191 }
192}
193
194#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
195#[serde(rename_all = "snake_case")]
196pub enum RemoteProcessLifecycleStatus {
197 #[default]
198 Running,
199 Completed,
200 Failed,
201 Cancelled,
202}
203
204impl RemoteProcessLifecycleStatus {
205 pub fn is_terminal(self) -> bool {
206 !matches!(self, Self::Running)
207 }
208}
209
210#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
211#[serde(tag = "state", rename_all = "snake_case")]
212pub enum RemoteProcessStatus {
213 Running,
214 Completed { await_output: RemoteProcessAwaitOutput },
215 Failed { await_output: RemoteProcessAwaitOutput },
216 Cancelled { await_output: RemoteProcessAwaitOutput },
217}
218
219impl Default for RemoteProcessStatus {
220 fn default() -> Self {
221 Self::Running
222 }
223}
224
225#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
226#[serde(tag = "type", rename_all = "snake_case")]
227pub enum RemoteProcessAwaitOutput {
228 Success {
229 value: serde_json::Value,
230 #[serde(default, skip_serializing_if = "Option::is_none")]
231 control: Option<serde_json::Value>,
232 },
233 Failure {
234 class: RemoteToolFailureClass,
235 code: String,
236 message: String,
237 #[serde(default, skip_serializing_if = "Option::is_none")]
238 raw: Option<serde_json::Value>,
239 #[serde(default, skip_serializing_if = "Option::is_none")]
240 control: Option<serde_json::Value>,
241 },
242 Cancelled {
243 message: String,
244 #[serde(default, skip_serializing_if = "Option::is_none")]
245 raw: Option<serde_json::Value>,
246 #[serde(default, skip_serializing_if = "Option::is_none")]
247 control: Option<serde_json::Value>,
248 },
249}
250
251impl RemoteProcessAwaitOutput {
252 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
253 match self {
254 Self::Success { .. } => Ok(()),
255 Self::Failure { code, message, .. } => {
256 require_non_empty(type_name, "await_output.code", code)?;
257 require_non_empty(type_name, "await_output.message", message)
258 }
259 Self::Cancelled { message, .. } => {
260 require_non_empty(type_name, "await_output.message", message)
261 }
262 }
263 }
264}
265
266#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
267#[serde(rename_all = "snake_case")]
268pub enum RemoteToolFailureClass {
269 InvalidRequest,
270 Unavailable,
271 PermissionDenied,
272 Timeout,
273 Execution,
274 External,
275 ResourceLimit,
276 Internal,
277}
278
279#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
280pub struct RemoteProcessExternalRef {
281 pub backend: String,
282 pub id: String,
283 #[serde(default, skip_serializing_if = "Option::is_none")]
284 pub metadata: Option<serde_json::Value>,
285}
286
287impl RemoteProcessExternalRef {
288 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
289 require_non_empty(type_name, "external_ref.backend", &self.backend)?;
290 require_non_empty(type_name, "external_ref.id", &self.id)
291 }
292}
293
294#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
295pub struct RemoteProcessWaitState {
296 pub kind: RemoteProcessWaitKind,
297 pub since_ms: u64,
298}
299
300#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
301#[serde(tag = "kind", rename_all = "snake_case")]
302pub enum RemoteProcessWaitKind {
303 Signal {
304 name: String,
305 event_type: String,
306 key: String,
307 ordinal: u64,
308 },
309}
310
311impl RemoteProcessWaitState {
312 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
313 match &self.kind {
314 RemoteProcessWaitKind::Signal {
315 name,
316 event_type,
317 key,
318 ordinal,
319 } => {
320 require_non_empty(type_name, "wait.name", name)?;
321 require_non_empty(type_name, "wait.event_type", event_type)?;
322 require_non_empty(type_name, "wait.key", key)?;
323 if *ordinal == 0 {
324 return Err(RemoteProtocolError::InvalidEnvelope {
325 type_name,
326 message: "wait ordinal must be non-zero".to_string(),
327 });
328 }
329 Ok(())
330 }
331 }
332 }
333}
334
335#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
336pub struct RemoteProcessSummary {
337 #[serde(rename = "__handle__")]
338 pub handle_type: String,
339 pub id: String,
340 pub process_id: String,
341 pub descriptor: RemoteProcessHandleDescriptor,
342 #[serde(default, skip_serializing_if = "Option::is_none")]
343 pub definition: Option<RemoteProcessDefinitionSummary>,
344 pub status: RemoteProcessLifecycleStatus,
345}
346
347impl RemoteProcessSummary {
348 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
349 require_non_empty(type_name, "handle_type", &self.handle_type)?;
350 require_non_empty(type_name, "id", &self.id)?;
351 require_non_empty(type_name, "process_id", &self.process_id)?;
352 self.descriptor.validate(type_name)?;
353 if let Some(definition) = &self.definition {
354 definition.validate(type_name)?;
355 }
356 Ok(())
357 }
358}
359
360#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
361pub struct RemoteProcessRecord {
362 pub process_id: String,
363 pub input: RemoteProcessInput,
364 #[serde(default, skip_serializing_if = "Vec::is_empty")]
365 pub event_types: Vec<RemoteProcessEventType>,
366 pub provenance: RemoteProcessProvenance,
367 #[serde(default, skip_serializing_if = "Option::is_none")]
368 pub env_ref: Option<String>,
369 #[serde(default, skip_serializing_if = "Option::is_none")]
370 pub wake_target: Option<RemoteSessionScope>,
371 pub created_at_ms: u64,
372 pub updated_at_ms: u64,
373 #[serde(default, skip_serializing_if = "Option::is_none")]
374 pub external_ref: Option<RemoteProcessExternalRef>,
375 #[serde(default, skip_serializing_if = "Option::is_none")]
376 pub wait: Option<RemoteProcessWaitState>,
377 #[serde(default)]
378 pub status: RemoteProcessStatus,
379}
380
381impl RemoteProcessRecord {
382 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
383 require_non_empty(type_name, "process_id", &self.process_id)?;
384 self.input.validate(type_name)?;
385 for event_type in &self.event_types {
386 event_type.validate(type_name)?;
387 }
388 self.provenance.validate(type_name)?;
389 if let Some(env_ref) = &self.env_ref {
390 require_non_empty(type_name, "env_ref", env_ref)?;
391 }
392 if let Some(wake_target) = &self.wake_target {
393 wake_target.validate(type_name)?;
394 }
395 if let Some(external_ref) = &self.external_ref {
396 external_ref.validate(type_name)?;
397 }
398 if let Some(wait) = &self.wait {
399 wait.validate(type_name)?;
400 }
401 match &self.status {
402 RemoteProcessStatus::Running => Ok(()),
403 RemoteProcessStatus::Completed { await_output }
404 | RemoteProcessStatus::Failed { await_output }
405 | RemoteProcessStatus::Cancelled { await_output } => await_output.validate(type_name),
406 }
407 }
408}
409
410#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
411pub struct RemoteProcessWorkSnapshot {
412 pub protocol_version: u32,
413 pub session_id: String,
414 #[serde(default)]
415 pub visible_process_ids: Vec<String>,
416 #[serde(default)]
417 pub items: Vec<RemoteProcessWorkItem>,
418}
419
420impl RemoteProcessWorkSnapshot {
421 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
422 ensure_protocol_version(self.protocol_version)?;
423 require_non_empty("RemoteProcessWorkSnapshot", "session_id", &self.session_id)?;
424 for process_id in &self.visible_process_ids {
425 require_non_empty("RemoteProcessWorkSnapshot", "visible_process_ids", process_id)?;
426 }
427 for item in &self.items {
428 item.validate("RemoteProcessWorkSnapshot")?;
429 }
430 Ok(())
431 }
432}
433
434#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
435pub struct RemoteProcessWorkItem {
436 pub process: RemoteObservedProcess,
437 pub descriptor: RemoteProcessHandleDescriptor,
438 #[serde(default)]
439 pub events: Vec<RemoteObservedProcessEvent>,
440 pub kind: String,
441 pub label: String,
442}
443
444impl RemoteProcessWorkItem {
445 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
446 self.process.validate(type_name)?;
447 self.descriptor.validate(type_name)?;
448 for event in &self.events {
449 event.validate(type_name)?;
450 }
451 require_non_empty(type_name, "kind", &self.kind)?;
452 require_non_empty(type_name, "label", &self.label)
453 }
454}
455
456#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
457pub struct RemoteObservedProcess {
458 pub process_id: String,
459 pub graph_key: String,
460 pub kind: String,
461 pub lifecycle: RemoteProcessLifecycleStatus,
462 pub status_label: String,
463 pub terminal: bool,
464 #[serde(default, skip_serializing_if = "Option::is_none")]
465 pub error: Option<String>,
466 pub created_at_ms: u64,
467 pub updated_at_ms: u64,
468 pub input: RemoteProcessInput,
469 pub originator: RemoteProcessOriginator,
470 #[serde(default, skip_serializing_if = "Option::is_none")]
471 pub env_ref: Option<String>,
472 #[serde(default, skip_serializing_if = "Option::is_none")]
473 pub wake_target: Option<RemoteSessionScope>,
474 #[serde(default, skip_serializing_if = "Option::is_none")]
475 pub caused_by: Option<RemoteCausalRef>,
476 #[serde(default, skip_serializing_if = "Option::is_none")]
477 pub external_ref: Option<RemoteProcessExternalRef>,
478 #[serde(default, skip_serializing_if = "Option::is_none")]
479 pub wait: Option<RemoteProcessWaitState>,
480 #[serde(default, skip_serializing_if = "Option::is_none")]
481 pub child_session_id: Option<String>,
482 pub label: String,
483}
484
485impl RemoteObservedProcess {
486 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
487 require_non_empty(type_name, "process_id", &self.process_id)?;
488 require_non_empty(type_name, "graph_key", &self.graph_key)?;
489 require_non_empty(type_name, "kind", &self.kind)?;
490 require_non_empty(type_name, "status_label", &self.status_label)?;
491 self.input.validate(type_name)?;
492 self.originator.validate(type_name)?;
493 if let Some(env_ref) = &self.env_ref {
494 require_non_empty(type_name, "env_ref", env_ref)?;
495 }
496 if let Some(wake_target) = &self.wake_target {
497 wake_target.validate(type_name)?;
498 }
499 if let Some(external_ref) = &self.external_ref {
500 external_ref.validate(type_name)?;
501 }
502 if let Some(wait) = &self.wait {
503 wait.validate(type_name)?;
504 }
505 if let Some(child_session_id) = &self.child_session_id {
506 require_non_empty(type_name, "child_session_id", child_session_id)?;
507 }
508 require_non_empty(type_name, "label", &self.label)
509 }
510}
511
512#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
513pub struct RemoteObservedProcessEvent {
514 pub sequence: u64,
515 pub event_type: String,
516 pub occurred_at_ms: u64,
517 #[serde(default)]
518 pub payload: serde_json::Value,
519}
520
521impl RemoteObservedProcessEvent {
522 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
523 require_non_empty(type_name, "event_type", &self.event_type)
524 }
525}
526
527#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
528pub struct RemoteProcessEvent {
529 pub process_id: String,
530 pub sequence: u64,
531 pub event_type: String,
532 #[serde(default)]
533 pub payload: serde_json::Value,
534 #[serde(default, skip_serializing_if = "Option::is_none")]
535 pub invocation: Option<RemoteRuntimeInvocation>,
536 #[serde(default)]
537 pub semantics: RemoteProcessEventSemantics,
538 pub occurred_at_ms: u64,
539}
540
541impl RemoteProcessEvent {
542 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
543 require_non_empty(type_name, "process_id", &self.process_id)?;
544 require_non_empty(type_name, "event_type", &self.event_type)?;
545 if let Some(invocation) = &self.invocation {
546 invocation.validate(type_name)?;
547 }
548 self.semantics.validate(type_name)
549 }
550}
551
552#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
553pub struct RemoteProcessEventType {
554 pub name: String,
555 #[serde(default)]
556 pub payload_schema: serde_json::Value,
557 #[serde(default)]
558 pub semantics: RemoteProcessEventSemanticsSpec,
559}
560
561impl RemoteProcessEventType {
562 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
563 require_non_empty(type_name, "event_type.name", &self.name)?;
564 self.semantics.validate(type_name)
565 }
566}
567
568#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
569pub struct RemoteProcessEventSemanticsSpec {
570 #[serde(default, skip_serializing_if = "Option::is_none")]
571 pub terminal: Option<RemoteProcessTerminalSpec>,
572 #[serde(default, skip_serializing_if = "Option::is_none")]
573 pub wake: Option<RemoteProcessWakeSpec>,
574}
575
576impl RemoteProcessEventSemanticsSpec {
577 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
578 if let Some(terminal) = &self.terminal {
579 terminal.validate(type_name)?;
580 }
581 if let Some(wake) = &self.wake {
582 wake.validate(type_name)?;
583 }
584 Ok(())
585 }
586}
587
588#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
589pub struct RemoteProcessTerminalSpec {
590 pub state: RemoteProcessTerminalState,
591 #[serde(default, skip_serializing_if = "Option::is_none")]
592 pub await_output: Option<RemoteProcessValueSelector>,
593}
594
595impl RemoteProcessTerminalSpec {
596 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
597 if let Some(await_output) = &self.await_output {
598 await_output.validate(type_name)?;
599 }
600 Ok(())
601 }
602}
603
604#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
605pub struct RemoteProcessWakeSpec {
606 #[serde(default, skip_serializing_if = "Option::is_none")]
607 pub when: Option<RemoteProcessValueSelector>,
608 pub input: RemoteProcessValueSelector,
609 #[serde(default)]
610 pub dedupe_key: RemoteProcessWakeDedupeKey,
611}
612
613impl RemoteProcessWakeSpec {
614 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
615 if let Some(when) = &self.when {
616 when.validate(type_name)?;
617 }
618 self.input.validate(type_name)?;
619 self.dedupe_key.validate(type_name)
620 }
621}
622
623#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
624pub struct RemoteProcessEventSemantics {
625 #[serde(default, skip_serializing_if = "Option::is_none")]
626 pub terminal: Option<RemoteProcessTerminalSemantics>,
627 #[serde(default, skip_serializing_if = "Option::is_none")]
628 pub wake: Option<RemoteProcessWake>,
629}
630
631impl RemoteProcessEventSemantics {
632 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
633 if let Some(terminal) = &self.terminal {
634 terminal.await_output.validate(type_name)?;
635 }
636 if let Some(wake) = &self.wake {
637 wake.validate(type_name)?;
638 }
639 Ok(())
640 }
641}
642
643#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
644#[serde(rename_all = "snake_case")]
645pub enum RemoteProcessTerminalState {
646 Completed,
647 Failed,
648 Cancelled,
649}
650
651#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
652pub struct RemoteProcessTerminalSemantics {
653 pub state: RemoteProcessTerminalState,
654 pub await_output: RemoteProcessAwaitOutput,
655}
656
657#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
658pub struct RemoteProcessWake {
659 pub input: String,
660 pub dedupe_key: String,
661}
662
663impl RemoteProcessWake {
664 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
665 require_non_empty(type_name, "wake.input", &self.input)?;
666 require_non_empty(type_name, "wake.dedupe_key", &self.dedupe_key)
667 }
668}
669
670#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
671#[serde(rename_all = "snake_case")]
672pub enum RemoteProcessWakeDedupeKey {
673 #[default]
674 EventIdentity,
675 Selector(RemoteProcessValueSelector),
676 Const(String),
677}
678
679impl RemoteProcessWakeDedupeKey {
680 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
681 match self {
682 Self::EventIdentity => Ok(()),
683 Self::Selector(selector) => selector.validate(type_name),
684 Self::Const(value) => require_non_empty(type_name, "wake.dedupe_key.const", value),
685 }
686 }
687}
688
689#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
690#[serde(rename_all = "snake_case")]
691pub enum RemoteProcessValueSelector {
692 Payload,
693 Pointer(String),
694 Const(serde_json::Value),
695 Template {
696 template: String,
697 #[serde(default)]
698 fields: BTreeMap<String, RemoteProcessValueSelector>,
699 },
700 Present(String),
701}
702
703impl RemoteProcessValueSelector {
704 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
705 match self {
706 Self::Payload | Self::Const(_) => Ok(()),
707 Self::Pointer(pointer) => require_non_empty(type_name, "selector.pointer", pointer),
708 Self::Template { template, fields } => {
709 require_non_empty(type_name, "selector.template", template)?;
710 for (name, selector) in fields {
711 require_non_empty(type_name, "selector.field", name)?;
712 selector.validate(type_name)?;
713 }
714 Ok(())
715 }
716 Self::Present(pointer) => require_non_empty(type_name, "selector.present", pointer),
717 }
718 }
719}
720
721#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
722pub struct RemoteRuntimeInvocation {
723 pub scope: RemoteRuntimeScope,
724 pub subject: RemoteRuntimeSubject,
725 #[serde(default, skip_serializing_if = "Option::is_none")]
726 pub caused_by: Option<RemoteCausalRef>,
727 #[serde(default, skip_serializing_if = "Option::is_none")]
728 pub replay: Option<RemoteRuntimeReplay>,
729}
730
731impl RemoteRuntimeInvocation {
732 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
733 self.scope.validate(type_name)?;
734 self.subject.validate(type_name)?;
735 if let Some(replay) = &self.replay {
736 require_non_empty(type_name, "replay.key", &replay.key)?;
737 }
738 Ok(())
739 }
740}
741
742#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
743pub struct RemoteRuntimeScope {
744 pub session_id: String,
745 #[serde(default, skip_serializing_if = "Option::is_none")]
746 pub turn_id: Option<String>,
747 #[serde(default, skip_serializing_if = "Option::is_none")]
748 pub turn_index: Option<usize>,
749 #[serde(default, skip_serializing_if = "Option::is_none")]
750 pub protocol_iteration: Option<usize>,
751}
752
753impl RemoteRuntimeScope {
754 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
755 require_non_empty(type_name, "runtime_scope.session_id", &self.session_id)?;
756 if let Some(turn_id) = &self.turn_id {
757 require_non_empty(type_name, "runtime_scope.turn_id", turn_id)?;
758 }
759 Ok(())
760 }
761}
762
763#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
764pub struct RemoteRuntimeReplay {
765 pub key: String,
766}
767
768#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
769#[serde(tag = "type", rename_all = "snake_case")]
770pub enum RemoteRuntimeSubject {
771 Effect {
772 effect_id: String,
773 kind: RemoteRuntimeEffectKind,
774 },
775 Process {
776 process_id: String,
777 },
778 ProcessEvent {
779 process_id: String,
780 sequence: u64,
781 event_type: String,
782 },
783 TriggerOccurrence {
784 occurrence_id: String,
785 },
786 SessionNode {
787 node_id: String,
788 },
789}
790
791impl RemoteRuntimeSubject {
792 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
793 match self {
794 Self::Effect { effect_id, .. } => {
795 require_non_empty(type_name, "runtime_subject.effect_id", effect_id)
796 }
797 Self::Process { process_id } => {
798 require_non_empty(type_name, "runtime_subject.process_id", process_id)
799 }
800 Self::ProcessEvent {
801 process_id,
802 event_type,
803 ..
804 } => {
805 require_non_empty(type_name, "runtime_subject.process_id", process_id)?;
806 require_non_empty(type_name, "runtime_subject.event_type", event_type)
807 }
808 Self::TriggerOccurrence { occurrence_id } => {
809 require_non_empty(type_name, "runtime_subject.occurrence_id", occurrence_id)
810 }
811 Self::SessionNode { node_id } => {
812 require_non_empty(type_name, "runtime_subject.node_id", node_id)
813 }
814 }
815 }
816}
817
818#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
819#[serde(rename_all = "snake_case")]
820pub enum RemoteRuntimeEffectKind {
821 LlmCall,
822 Direct,
823 ToolCall,
824 Process,
825 ExecCode,
826 Checkpoint,
827 SyncExecutionEnvironment,
828 Sleep,
829 AwaitEvent,
830 DurableStep,
831}
832
833#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
834pub struct RemoteProcessStartRequest {
835 pub protocol_version: u32,
836 pub id: String,
837 pub input: RemoteProcessInput,
838 #[serde(default, skip_serializing_if = "Option::is_none")]
839 pub env_spec: Option<serde_json::Value>,
840 pub originator: RemoteProcessOriginator,
841 #[serde(default, skip_serializing_if = "Option::is_none")]
842 pub wake_target: Option<RemoteSessionScope>,
843 #[serde(default, skip_serializing_if = "Option::is_none")]
844 pub grant: Option<RemoteProcessStartGrant>,
845 #[serde(default, skip_serializing_if = "Vec::is_empty")]
846 pub event_types: Vec<RemoteProcessEventType>,
847}
848
849impl RemoteProcessStartRequest {
850 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
851 ensure_protocol_version(self.protocol_version)?;
852 require_non_empty("RemoteProcessStartRequest", "id", &self.id)?;
853 self.input.validate("RemoteProcessStartRequest")?;
854 if let RemoteProcessInput::SessionTurn { turn_input, .. } = &self.input
855 && turn_input.protocol_version != self.protocol_version
856 {
857 return Err(RemoteProtocolError::MismatchedNestedProtocolVersion {
858 parent: "RemoteProcessStartRequest",
859 child: "input.turn_input",
860 parent_version: self.protocol_version,
861 child_version: turn_input.protocol_version,
862 });
863 }
864 self.originator.validate("RemoteProcessStartRequest")?;
865 if let Some(wake_target) = &self.wake_target {
866 wake_target.validate("RemoteProcessStartRequest")?;
867 }
868 if let Some(grant) = &self.grant {
869 grant.validate("RemoteProcessStartRequest")?;
870 }
871 for event_type in &self.event_types {
872 event_type.validate("RemoteProcessStartRequest")?;
873 }
874 Ok(())
875 }
876}
877
878#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
879pub struct RemoteProcessStartResult {
880 pub protocol_version: u32,
881 pub record: RemoteProcessRecord,
882 #[serde(default, skip_serializing_if = "Option::is_none")]
883 pub summary: Option<RemoteProcessSummary>,
884}
885
886impl RemoteProcessStartResult {
887 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
888 ensure_protocol_version(self.protocol_version)?;
889 self.record.validate("RemoteProcessStartResult")?;
890 if let Some(summary) = &self.summary {
891 summary.validate("RemoteProcessStartResult")?;
892 }
893 Ok(())
894 }
895}
896
897#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
898#[serde(rename_all = "snake_case")]
899pub enum RemoteProcessStatusFilter {
900 #[default]
901 Running,
902 Completed,
903 Failed,
904 Cancelled,
905 Any,
906}
907
908#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
909pub struct RemoteProcessListFilter {
910 pub protocol_version: u32,
911 #[serde(default, skip_serializing_if = "Option::is_none")]
912 pub definition: Option<RemoteProcessDefinitionIdentity>,
913 #[serde(default)]
914 pub status: RemoteProcessStatusFilter,
915 #[serde(default, skip_serializing_if = "Option::is_none")]
916 pub waiting: Option<bool>,
917}
918
919impl Default for RemoteProcessListFilter {
920 fn default() -> Self {
921 Self {
922 protocol_version: REMOTE_PROTOCOL_VERSION,
923 definition: None,
924 status: RemoteProcessStatusFilter::Running,
925 waiting: None,
926 }
927 }
928}
929
930impl RemoteProcessListFilter {
931 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
932 ensure_protocol_version(self.protocol_version)?;
933 if let Some(definition) = &self.definition {
934 definition.validate("RemoteProcessListFilter")?;
935 }
936 Ok(())
937 }
938}
939
940#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
941pub struct RemoteProcessListResponse {
942 pub protocol_version: u32,
943 #[serde(default)]
944 pub records: Vec<RemoteObservedProcess>,
945}
946
947impl RemoteProcessListResponse {
948 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
949 ensure_protocol_version(self.protocol_version)?;
950 for record in &self.records {
951 record.validate("RemoteProcessListResponse")?;
952 }
953 Ok(())
954 }
955}
956
957#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
958pub struct RemoteProcessCancelRequest {
959 pub protocol_version: u32,
960 pub process_id: String,
961 #[serde(default, skip_serializing_if = "Option::is_none")]
962 pub reason: Option<String>,
963}
964
965impl RemoteProcessCancelRequest {
966 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
967 ensure_protocol_version(self.protocol_version)?;
968 require_non_empty(
969 "RemoteProcessCancelRequest",
970 "process_id",
971 &self.process_id,
972 )?;
973 if let Some(reason) = &self.reason {
974 require_non_empty("RemoteProcessCancelRequest", "reason", reason)?;
975 }
976 Ok(())
977 }
978}
979
980#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
981pub struct RemoteProcessCancelResult {
982 pub protocol_version: u32,
983 pub process_id: String,
984 pub status: RemoteProcessLifecycleStatus,
985 #[serde(default, skip_serializing_if = "Option::is_none")]
986 pub record: Option<RemoteProcessRecord>,
987}
988
989impl RemoteProcessCancelResult {
990 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
991 ensure_protocol_version(self.protocol_version)?;
992 require_non_empty(
993 "RemoteProcessCancelResult",
994 "process_id",
995 &self.process_id,
996 )?;
997 if let Some(record) = &self.record {
998 record.validate("RemoteProcessCancelResult")?;
999 }
1000 Ok(())
1001 }
1002}
1003
1004#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1005pub struct RemoteProcessSignalRequest {
1006 pub protocol_version: u32,
1007 pub process_id: String,
1008 pub signal_name: String,
1009 pub signal_id: String,
1010 #[serde(default)]
1011 pub payload: serde_json::Value,
1012 #[serde(default, skip_serializing_if = "Option::is_none")]
1013 pub replay_key: Option<String>,
1014 #[serde(default, skip_serializing_if = "Option::is_none")]
1015 pub wake_target_scope: Option<RemoteSessionScope>,
1016}
1017
1018impl RemoteProcessSignalRequest {
1019 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1020 ensure_protocol_version(self.protocol_version)?;
1021 require_non_empty(
1022 "RemoteProcessSignalRequest",
1023 "process_id",
1024 &self.process_id,
1025 )?;
1026 require_non_empty(
1027 "RemoteProcessSignalRequest",
1028 "signal_name",
1029 &self.signal_name,
1030 )?;
1031 require_non_empty(
1032 "RemoteProcessSignalRequest",
1033 "signal_id",
1034 &self.signal_id,
1035 )?;
1036 if let Some(replay_key) = &self.replay_key {
1037 require_non_empty("RemoteProcessSignalRequest", "replay_key", replay_key)?;
1038 }
1039 if let Some(scope) = &self.wake_target_scope {
1040 scope.validate("RemoteProcessSignalRequest")?;
1041 }
1042 Ok(())
1043 }
1044}
1045
1046#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1047pub struct RemoteProcessSignalResult {
1048 pub protocol_version: u32,
1049 pub event: RemoteProcessEvent,
1050}
1051
1052impl RemoteProcessSignalResult {
1053 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1054 ensure_protocol_version(self.protocol_version)?;
1055 self.event.validate("RemoteProcessSignalResult")
1056 }
1057}
1058
1059#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1060pub struct RemoteProcessAwaitRequest {
1061 pub protocol_version: u32,
1062 pub process_id: String,
1063}
1064
1065impl RemoteProcessAwaitRequest {
1066 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1067 ensure_protocol_version(self.protocol_version)?;
1068 require_non_empty(
1069 "RemoteProcessAwaitRequest",
1070 "process_id",
1071 &self.process_id,
1072 )
1073 }
1074}
1075
1076#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1077pub struct RemoteProcessAwaitResult {
1078 pub protocol_version: u32,
1079 pub process_id: String,
1080 pub output: RemoteProcessAwaitOutput,
1081}
1082
1083impl RemoteProcessAwaitResult {
1084 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1085 ensure_protocol_version(self.protocol_version)?;
1086 require_non_empty(
1087 "RemoteProcessAwaitResult",
1088 "process_id",
1089 &self.process_id,
1090 )?;
1091 self.output.validate("RemoteProcessAwaitResult")
1092 }
1093}
1094
1095#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1096pub struct RemoteProcessEventsRequest {
1097 pub protocol_version: u32,
1098 pub process_id: String,
1099 #[serde(default)]
1100 pub after_sequence: u64,
1101}
1102
1103impl RemoteProcessEventsRequest {
1104 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1105 ensure_protocol_version(self.protocol_version)?;
1106 require_non_empty(
1107 "RemoteProcessEventsRequest",
1108 "process_id",
1109 &self.process_id,
1110 )
1111 }
1112}
1113
1114#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1115pub struct RemoteProcessEventsResponse {
1116 pub protocol_version: u32,
1117 pub process_id: String,
1118 #[serde(default)]
1119 pub events: Vec<RemoteProcessEvent>,
1120}
1121
1122impl RemoteProcessEventsResponse {
1123 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1124 ensure_protocol_version(self.protocol_version)?;
1125 require_non_empty(
1126 "RemoteProcessEventsResponse",
1127 "process_id",
1128 &self.process_id,
1129 )?;
1130 for event in &self.events {
1131 event.validate("RemoteProcessEventsResponse")?;
1132 }
1133 Ok(())
1134 }
1135}