1use std::collections::BTreeMap;
6
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9
10use crate::prompt::RemotePromptLayer;
11use crate::registry_errors::{RemoteProtocolError, require_non_empty};
12use crate::tools::RemoteToolOutputContract;
13use crate::turn_input::RemoteTurnInput;
14use crate::turn_result::RemoteCausalRef;
15use crate::{REMOTE_PROTOCOL_VERSION, ensure_protocol_version};
16
17#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
18pub struct RemoteSessionScope {
19 pub session_id: String,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub agent_frame_id: Option<String>,
22}
23
24impl RemoteSessionScope {
25 pub fn new(session_id: impl Into<String>) -> Self {
26 Self {
27 session_id: session_id.into(),
28 agent_frame_id: None,
29 }
30 }
31
32 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
33 require_non_empty(type_name, "session_id", &self.session_id)?;
34 if let Some(agent_frame_id) = &self.agent_frame_id {
35 require_non_empty(type_name, "agent_frame_id", agent_frame_id)?;
36 }
37 Ok(())
38 }
39}
40
41#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, JsonSchema)]
42#[serde(transparent)]
43pub struct RemoteProcessExecutionEnvRef(String);
44
45impl RemoteProcessExecutionEnvRef {
46 pub const PREFIX: &'static str = "process-env:sha256:";
47
48 pub fn parse(value: impl Into<String>) -> Result<Self, RemoteProtocolError> {
49 let value = value.into();
50 if is_canonical_process_execution_env_ref(&value) {
51 Ok(Self(value))
52 } else {
53 Err(RemoteProtocolError::InvalidEnvelope {
54 type_name: "RemoteProcessExecutionEnvRef",
55 message: "env_ref must match `process-env:sha256:<64 lowercase hex>`".to_string(),
56 })
57 }
58 }
59
60 pub fn as_str(&self) -> &str {
61 &self.0
62 }
63
64 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
65 if is_canonical_process_execution_env_ref(&self.0) {
66 Ok(())
67 } else {
68 Err(RemoteProtocolError::InvalidEnvelope {
69 type_name,
70 message: "env_ref must match `process-env:sha256:<64 lowercase hex>`".to_string(),
71 })
72 }
73 }
74}
75
76impl std::fmt::Display for RemoteProcessExecutionEnvRef {
77 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 formatter.write_str(&self.0)
79 }
80}
81
82impl std::str::FromStr for RemoteProcessExecutionEnvRef {
83 type Err = RemoteProtocolError;
84
85 fn from_str(value: &str) -> Result<Self, Self::Err> {
86 Self::parse(value)
87 }
88}
89
90impl<'de> serde::Deserialize<'de> for RemoteProcessExecutionEnvRef {
91 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
92 where
93 D: serde::Deserializer<'de>,
94 {
95 let value = String::deserialize(deserializer)?;
96 Self::parse(value).map_err(serde::de::Error::custom)
97 }
98}
99
100fn is_canonical_process_execution_env_ref(value: &str) -> bool {
101 let Some(digest) = value.strip_prefix(RemoteProcessExecutionEnvRef::PREFIX) else {
102 return false;
103 };
104 digest.len() == 64
105 && digest
106 .bytes()
107 .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
108}
109
110#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
111#[serde(tag = "type", rename_all = "snake_case")]
112pub enum RemoteProcessOriginator {
113 Host {
114 #[serde(default, skip_serializing_if = "Option::is_none")]
115 scope: Option<String>,
116 },
117 Session {
118 scope: RemoteSessionScope,
119 },
120}
121
122impl RemoteProcessOriginator {
123 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
124 match self {
125 Self::Host { .. } => Ok(()),
126 Self::Session { scope } => scope.validate(type_name),
127 }
128 }
129}
130
131#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
132pub struct RemoteProcessProvenance {
133 pub originator: RemoteProcessOriginator,
134 #[serde(default, skip_serializing_if = "Option::is_none")]
135 pub caused_by: Option<RemoteCausalRef>,
136}
137
138impl RemoteProcessProvenance {
139 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
140 self.originator.validate(type_name)
141 }
142}
143
144#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
145pub struct RemoteProcessDefinitionIdentity {
146 #[serde(default)]
147 pub value: serde_json::Value,
148}
149
150impl RemoteProcessDefinitionIdentity {
151 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
152 if self.value.is_null() {
153 return Err(RemoteProtocolError::InvalidEnvelope {
154 type_name,
155 message: "definition value cannot be null".to_string(),
156 });
157 }
158 Ok(())
159 }
160}
161
162#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
163pub struct RemoteProcessIdentity {
164 pub kind: String,
165 #[serde(default, skip_serializing_if = "Option::is_none")]
166 pub label: Option<String>,
167 #[serde(default, skip_serializing_if = "Option::is_none")]
168 pub definition: Option<RemoteProcessDefinitionIdentity>,
169}
170
171impl RemoteProcessIdentity {
172 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
173 require_non_empty(type_name, "identity.kind", &self.kind)?;
174 if let Some(definition) = &self.definition {
175 definition.validate(type_name)?;
176 }
177 Ok(())
178 }
179}
180
181#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
182pub struct RemoteProcessHandleDescriptor {
183 #[serde(default, skip_serializing_if = "Option::is_none")]
184 pub kind: Option<String>,
185 #[serde(default, skip_serializing_if = "Option::is_none")]
186 pub label: Option<String>,
187}
188
189impl RemoteProcessHandleDescriptor {
190 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
191 if let Some(kind) = &self.kind {
192 require_non_empty(type_name, "descriptor.kind", kind)?;
193 }
194 if let Some(label) = &self.label {
195 require_non_empty(type_name, "descriptor.label", label)?;
196 }
197 Ok(())
198 }
199}
200
201#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
202pub struct RemoteProcessStartGrant {
203 pub session_scope: RemoteSessionScope,
204 pub descriptor: RemoteProcessHandleDescriptor,
205}
206
207impl RemoteProcessStartGrant {
208 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
209 self.session_scope.validate(type_name)?;
210 self.descriptor.validate(type_name)
211 }
212}
213
214#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
215#[serde(tag = "type", rename_all = "snake_case")]
216#[allow(clippy::large_enum_variant)]
218pub enum RemoteProcessInput {
219 ToolCall {
220 #[serde(default)]
221 prepared_tool_call: serde_json::Value,
222 },
223 Engine {
224 kind: String,
225 #[serde(default)]
226 payload: serde_json::Value,
227 },
228 SessionTurn {
229 #[serde(default)]
230 create_request: serde_json::Value,
231 turn_input: RemoteTurnInput,
232 #[serde(default, skip_serializing_if = "RemoteToolOutputContract::is_static")]
233 output_contract: RemoteToolOutputContract,
234 },
235 External {
236 #[serde(default)]
237 metadata: serde_json::Value,
238 },
239}
240
241impl RemoteProcessInput {
242 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
243 match self {
244 Self::ToolCall {
245 prepared_tool_call: _,
246 } => Ok(()),
247 Self::Engine { kind, payload: _ } => require_non_empty(type_name, "kind", kind),
248 Self::SessionTurn {
249 create_request: _,
250 turn_input,
251 output_contract,
252 } => {
253 turn_input.validate()?;
254 match output_contract {
255 RemoteToolOutputContract::Static => Ok(()),
256 RemoteToolOutputContract::FromInputSchema {
257 input_field,
258 default_schema: _,
259 } => require_non_empty(type_name, "output_contract.input_field", input_field),
260 }
261 }
262 Self::External { metadata: _ } => Ok(()),
263 }
264 }
265}
266
267#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
268#[serde(rename_all = "snake_case")]
269pub enum RemoteProcessLifecycleStatus {
270 #[default]
271 Running,
272 Completed,
273 Failed,
274 Cancelled,
275 Abandoned,
276}
277
278impl RemoteProcessLifecycleStatus {
279 pub fn is_terminal(self) -> bool {
280 !matches!(self, Self::Running)
281 }
282}
283
284#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
285#[serde(tag = "state", rename_all = "snake_case")]
286pub enum RemoteProcessStatus {
287 #[default]
288 Running,
289 Completed {
290 await_output: RemoteProcessAwaitOutput,
291 },
292 Failed {
293 await_output: RemoteProcessAwaitOutput,
294 },
295 Cancelled {
296 await_output: RemoteProcessAwaitOutput,
297 },
298 Abandoned {
299 await_output: RemoteProcessAwaitOutput,
300 },
301}
302
303#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
304#[serde(tag = "type", rename_all = "snake_case")]
305pub enum RemoteProcessAwaitOutput {
306 Success {
307 value: serde_json::Value,
308 #[serde(default, skip_serializing_if = "Option::is_none")]
309 control: Option<serde_json::Value>,
310 },
311 Failure {
312 class: RemoteToolFailureClass,
313 code: String,
314 message: String,
315 #[serde(default, skip_serializing_if = "Option::is_none")]
316 raw: Option<serde_json::Value>,
317 #[serde(default, skip_serializing_if = "Option::is_none")]
318 control: Option<serde_json::Value>,
319 },
320 Cancelled {
321 message: String,
322 #[serde(default, skip_serializing_if = "Option::is_none")]
323 raw: Option<serde_json::Value>,
324 #[serde(default, skip_serializing_if = "Option::is_none")]
325 control: Option<serde_json::Value>,
326 },
327 Abandoned {
328 evidence: RemoteAbandonEvidence,
329 #[serde(default, skip_serializing_if = "Option::is_none")]
330 control: Option<serde_json::Value>,
331 },
332}
333
334impl RemoteProcessAwaitOutput {
335 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
336 match self {
337 Self::Success { .. } | Self::Abandoned { .. } => Ok(()),
338 Self::Failure { code, message, .. } => {
339 require_non_empty(type_name, "await_output.code", code)?;
340 require_non_empty(type_name, "await_output.message", message)
341 }
342 Self::Cancelled { message, .. } => {
343 require_non_empty(type_name, "await_output.message", message)
344 }
345 }
346 }
347}
348
349#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
350#[serde(rename_all = "snake_case")]
351pub enum RemoteToolFailureClass {
352 InvalidRequest,
353 Unavailable,
354 PermissionDenied,
355 Timeout,
356 Execution,
357 External,
358 ResourceLimit,
359 Internal,
360}
361
362#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
363pub struct RemoteProcessExternalRef {
364 pub backend: String,
365 pub id: String,
366 #[serde(default, skip_serializing_if = "Option::is_none")]
367 pub metadata: Option<serde_json::Value>,
368}
369
370impl RemoteProcessExternalRef {
371 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
372 require_non_empty(type_name, "external_ref.backend", &self.backend)?;
373 require_non_empty(type_name, "external_ref.id", &self.id)
374 }
375}
376
377#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
378pub struct RemoteProcessWaitState {
379 pub kind: RemoteProcessWaitKind,
380 pub since_ms: u64,
381}
382
383#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
384#[serde(tag = "kind", rename_all = "snake_case")]
385pub enum RemoteProcessWaitKind {
386 Signal {
387 name: String,
388 event_type: String,
389 key: String,
390 ordinal: u64,
391 },
392}
393
394impl RemoteProcessWaitState {
395 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
396 match &self.kind {
397 RemoteProcessWaitKind::Signal {
398 name,
399 event_type,
400 key,
401 ordinal,
402 } => {
403 require_non_empty(type_name, "wait.name", name)?;
404 require_non_empty(type_name, "wait.event_type", event_type)?;
405 require_non_empty(type_name, "wait.key", key)?;
406 if *ordinal == 0 {
407 return Err(RemoteProtocolError::InvalidEnvelope {
408 type_name,
409 message: "wait ordinal must be non-zero".to_string(),
410 });
411 }
412 Ok(())
413 }
414 }
415 }
416}
417
418#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
419pub struct RemoteProcessSummary {
420 #[serde(rename = "__handle__")]
421 pub handle_type: String,
422 pub id: String,
423 pub process_id: String,
424 pub descriptor: RemoteProcessHandleDescriptor,
425 #[serde(default, skip_serializing_if = "Option::is_none")]
426 pub definition: Option<RemoteProcessDefinitionIdentity>,
427 pub status: RemoteProcessLifecycleStatus,
428}
429
430impl RemoteProcessSummary {
431 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
432 require_non_empty(type_name, "handle_type", &self.handle_type)?;
433 require_non_empty(type_name, "id", &self.id)?;
434 require_non_empty(type_name, "process_id", &self.process_id)?;
435 self.descriptor.validate(type_name)?;
436 if let Some(definition) = &self.definition {
437 definition.validate(type_name)?;
438 }
439 Ok(())
440 }
441}
442
443#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
444pub struct RemoteProcessRecord {
445 pub process_id: String,
446 pub input: RemoteProcessInput,
447 pub disposition: RemoteRecoveryDisposition,
448 pub identity: RemoteProcessIdentity,
449 #[serde(default, skip_serializing_if = "Vec::is_empty")]
450 pub event_types: Vec<RemoteProcessEventType>,
451 pub provenance: RemoteProcessProvenance,
452 #[serde(default, skip_serializing_if = "Option::is_none")]
453 pub env_ref: Option<RemoteProcessExecutionEnvRef>,
454 #[serde(default, skip_serializing_if = "Option::is_none")]
455 pub wake_target: Option<RemoteSessionScope>,
456 pub created_at_ms: u64,
457 pub updated_at_ms: u64,
458 #[serde(default, skip_serializing_if = "Option::is_none")]
459 pub external_ref: Option<RemoteProcessExternalRef>,
460 #[serde(default, skip_serializing_if = "Option::is_none")]
461 pub first_started: Option<RemoteProcessStarted>,
462 #[serde(default, skip_serializing_if = "Option::is_none")]
463 pub abandon_request: Option<RemoteAbandonRequest>,
464 #[serde(default, skip_serializing_if = "Option::is_none")]
465 pub wait: Option<RemoteProcessWaitState>,
466 #[serde(default)]
467 pub status: RemoteProcessStatus,
468}
469
470impl RemoteProcessRecord {
471 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
472 require_non_empty(type_name, "process_id", &self.process_id)?;
473 self.input.validate(type_name)?;
474 self.identity.validate(type_name)?;
475 for event_type in &self.event_types {
476 event_type.validate(type_name)?;
477 }
478 self.provenance.validate(type_name)?;
479 if let Some(env_ref) = &self.env_ref {
480 env_ref.validate(type_name)?;
481 }
482 if let Some(wake_target) = &self.wake_target {
483 wake_target.validate(type_name)?;
484 }
485 if let Some(external_ref) = &self.external_ref {
486 external_ref.validate(type_name)?;
487 }
488 if let Some(wait) = &self.wait {
489 wait.validate(type_name)?;
490 }
491 match &self.status {
492 RemoteProcessStatus::Running => Ok(()),
493 RemoteProcessStatus::Completed { await_output }
494 | RemoteProcessStatus::Failed { await_output }
495 | RemoteProcessStatus::Cancelled { await_output }
496 | RemoteProcessStatus::Abandoned { await_output } => await_output.validate(type_name),
497 }
498 }
499}
500
501#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
502pub struct RemoteProcessWorkSnapshot {
503 pub protocol_version: u32,
504 pub session_id: String,
505 #[serde(default)]
506 pub visible_process_ids: Vec<String>,
507 #[serde(default)]
508 pub items: Vec<RemoteProcessWorkItem>,
509}
510
511impl RemoteProcessWorkSnapshot {
512 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
513 ensure_protocol_version(self.protocol_version)?;
514 require_non_empty("RemoteProcessWorkSnapshot", "session_id", &self.session_id)?;
515 for process_id in &self.visible_process_ids {
516 require_non_empty(
517 "RemoteProcessWorkSnapshot",
518 "visible_process_ids",
519 process_id,
520 )?;
521 }
522 for item in &self.items {
523 item.validate("RemoteProcessWorkSnapshot")?;
524 }
525 Ok(())
526 }
527}
528
529#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
530pub struct RemoteProcessWorkItem {
531 pub process: RemoteObservedProcess,
532 pub descriptor: RemoteProcessHandleDescriptor,
533 #[serde(default)]
534 pub events: Vec<RemoteObservedProcessEvent>,
535 pub kind: String,
536 pub label: String,
537}
538
539impl RemoteProcessWorkItem {
540 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
541 self.process.validate(type_name)?;
542 self.descriptor.validate(type_name)?;
543 for event in &self.events {
544 event.validate(type_name)?;
545 }
546 require_non_empty(type_name, "kind", &self.kind)?;
547 require_non_empty(type_name, "label", &self.label)
548 }
549}
550
551#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
552pub struct RemoteObservedProcess {
553 pub process_id: String,
554 pub graph_key: String,
555 pub kind: String,
556 pub identity: RemoteProcessIdentity,
557 pub lifecycle: RemoteProcessLifecycleStatus,
558 pub status_label: String,
559 pub terminal: bool,
560 pub disposition: RemoteRecoveryDisposition,
561 #[serde(default, skip_serializing_if = "Option::is_none")]
562 pub error: Option<String>,
563 pub created_at_ms: u64,
564 pub updated_at_ms: u64,
565 #[serde(default, skip_serializing_if = "Option::is_none")]
566 pub first_started: Option<RemoteProcessStarted>,
567 #[serde(default, skip_serializing_if = "Option::is_none")]
568 pub lease_holder: Option<serde_json::Value>,
569 #[serde(default, skip_serializing_if = "Option::is_none")]
570 pub lease_expires_at_ms: Option<u64>,
571 #[serde(default, skip_serializing_if = "Option::is_none")]
572 pub abandon_request: Option<RemoteAbandonRequest>,
573 pub input: RemoteProcessInput,
574 pub originator: RemoteProcessOriginator,
575 #[serde(default, skip_serializing_if = "Option::is_none")]
576 pub env_ref: Option<RemoteProcessExecutionEnvRef>,
577 #[serde(default, skip_serializing_if = "Option::is_none")]
578 pub wake_target: Option<RemoteSessionScope>,
579 #[serde(default, skip_serializing_if = "Option::is_none")]
580 pub caused_by: Option<RemoteCausalRef>,
581 #[serde(default, skip_serializing_if = "Option::is_none")]
582 pub external_ref: Option<RemoteProcessExternalRef>,
583 #[serde(default, skip_serializing_if = "Option::is_none")]
584 pub wait: Option<RemoteProcessWaitState>,
585 #[serde(default, skip_serializing_if = "Option::is_none")]
586 pub child_session_id: Option<String>,
587 pub label: String,
588}
589
590impl RemoteObservedProcess {
591 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
592 require_non_empty(type_name, "process_id", &self.process_id)?;
593 require_non_empty(type_name, "graph_key", &self.graph_key)?;
594 require_non_empty(type_name, "kind", &self.kind)?;
595 self.identity.validate(type_name)?;
596 require_non_empty(type_name, "status_label", &self.status_label)?;
597 self.input.validate(type_name)?;
598 self.originator.validate(type_name)?;
599 if let Some(env_ref) = &self.env_ref {
600 env_ref.validate(type_name)?;
601 }
602 if let Some(wake_target) = &self.wake_target {
603 wake_target.validate(type_name)?;
604 }
605 if let Some(external_ref) = &self.external_ref {
606 external_ref.validate(type_name)?;
607 }
608 if let Some(wait) = &self.wait {
609 wait.validate(type_name)?;
610 }
611 if let Some(child_session_id) = &self.child_session_id {
612 require_non_empty(type_name, "child_session_id", child_session_id)?;
613 }
614 require_non_empty(type_name, "label", &self.label)
615 }
616}
617
618#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
619pub struct RemoteObservedProcessEvent {
620 pub sequence: u64,
621 pub event_type: String,
622 pub occurred_at_ms: u64,
623 #[serde(default)]
624 pub payload: serde_json::Value,
625}
626
627impl RemoteObservedProcessEvent {
628 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
629 require_non_empty(type_name, "event_type", &self.event_type)
630 }
631}
632
633#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
634pub struct RemoteProcessEvent {
635 pub process_id: String,
636 pub sequence: u64,
637 pub event_type: String,
638 #[serde(default)]
639 pub payload: serde_json::Value,
640 #[serde(default, skip_serializing_if = "Option::is_none")]
641 pub invocation: Option<RemoteRuntimeInvocation>,
642 #[serde(default)]
643 pub semantics: RemoteProcessEventSemantics,
644 pub occurred_at_ms: u64,
645}
646
647impl RemoteProcessEvent {
648 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
649 require_non_empty(type_name, "process_id", &self.process_id)?;
650 require_non_empty(type_name, "event_type", &self.event_type)?;
651 if let Some(invocation) = &self.invocation {
652 invocation.validate(type_name)?;
653 }
654 self.semantics.validate(type_name)
655 }
656}
657
658#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
659pub struct RemoteProcessEventType {
660 pub name: String,
661 #[serde(default)]
662 pub payload_schema: serde_json::Value,
663 #[serde(default)]
664 pub semantics: RemoteProcessEventSemanticsSpec,
665}
666
667impl RemoteProcessEventType {
668 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
669 require_non_empty(type_name, "event_type.name", &self.name)?;
670 self.semantics.validate(type_name)
671 }
672}
673
674#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
675pub struct RemoteProcessEventSemanticsSpec {
676 #[serde(default, skip_serializing_if = "Option::is_none")]
677 pub terminal: Option<RemoteProcessTerminalSpec>,
678 #[serde(default, skip_serializing_if = "Option::is_none")]
679 pub wake: Option<RemoteProcessWakeSpec>,
680}
681
682impl RemoteProcessEventSemanticsSpec {
683 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
684 if let Some(terminal) = &self.terminal {
685 terminal.validate(type_name)?;
686 }
687 if let Some(wake) = &self.wake {
688 wake.validate(type_name)?;
689 }
690 Ok(())
691 }
692}
693
694#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
695pub struct RemoteProcessTerminalSpec {
696 pub state: RemoteProcessTerminalState,
697 #[serde(default, skip_serializing_if = "Option::is_none")]
698 pub await_output: Option<RemoteProcessValueSelector>,
699}
700
701impl RemoteProcessTerminalSpec {
702 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
703 if let Some(await_output) = &self.await_output {
704 await_output.validate(type_name)?;
705 }
706 Ok(())
707 }
708}
709
710#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
711pub struct RemoteProcessWakeSpec {
712 #[serde(default, skip_serializing_if = "Option::is_none")]
713 pub when: Option<RemoteProcessValueSelector>,
714 pub input: RemoteProcessValueSelector,
715 #[serde(default)]
716 pub dedupe_key: RemoteProcessWakeDedupeKey,
717}
718
719impl RemoteProcessWakeSpec {
720 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
721 if let Some(when) = &self.when {
722 when.validate(type_name)?;
723 }
724 self.input.validate(type_name)?;
725 self.dedupe_key.validate(type_name)
726 }
727}
728
729#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
730pub struct RemoteProcessEventSemantics {
731 #[serde(default, skip_serializing_if = "Option::is_none")]
732 pub terminal: Option<RemoteProcessTerminalSemantics>,
733 #[serde(default, skip_serializing_if = "Option::is_none")]
734 pub wake: Option<RemoteProcessWake>,
735}
736
737impl RemoteProcessEventSemantics {
738 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
739 if let Some(terminal) = &self.terminal {
740 terminal.await_output.validate(type_name)?;
741 }
742 if let Some(wake) = &self.wake {
743 wake.validate(type_name)?;
744 }
745 Ok(())
746 }
747}
748
749#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
750#[serde(rename_all = "snake_case")]
751pub enum RemoteProcessTerminalState {
752 Completed,
753 Failed,
754 Cancelled,
755 Abandoned,
756}
757
758#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
760#[serde(rename_all = "snake_case")]
761pub enum RemoteRecoveryDisposition {
762 Rerunnable,
763 OwnerBound,
764 ExternallyOwned,
765}
766
767#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
769#[serde(rename_all = "snake_case")]
770pub enum RemoteAbandonWriter {
771 OwnerDrain,
772 Sweep,
773 ReconciledRequest,
774}
775
776#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
780pub struct RemoteAbandonEvidence {
781 pub writer: RemoteAbandonWriter,
782 #[serde(default, skip_serializing_if = "Option::is_none")]
783 pub owner: Option<serde_json::Value>,
784 pub epoch_ms: u64,
785}
786
787#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
789pub struct RemoteProcessStarted {
790 #[serde(default)]
791 pub owner: serde_json::Value,
792 pub started_at_ms: u64,
793}
794
795#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
797pub struct RemoteAbandonRequest {
798 pub requested_by: String,
799 pub requested_at_ms: u64,
800 #[serde(default, skip_serializing_if = "Option::is_none")]
801 pub reason: Option<String>,
802}
803
804#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
805pub struct RemoteProcessTerminalSemantics {
806 pub state: RemoteProcessTerminalState,
807 pub await_output: RemoteProcessAwaitOutput,
808}
809
810#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
811pub struct RemoteProcessWake {
812 pub input: String,
813 pub dedupe_key: String,
814}
815
816impl RemoteProcessWake {
817 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
818 require_non_empty(type_name, "wake.input", &self.input)?;
819 require_non_empty(type_name, "wake.dedupe_key", &self.dedupe_key)
820 }
821}
822
823#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
824#[serde(rename_all = "snake_case")]
825pub enum RemoteProcessWakeDedupeKey {
826 #[default]
827 EventIdentity,
828 Selector(RemoteProcessValueSelector),
829 Const(String),
830}
831
832impl RemoteProcessWakeDedupeKey {
833 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
834 match self {
835 Self::EventIdentity => Ok(()),
836 Self::Selector(selector) => selector.validate(type_name),
837 Self::Const(value) => require_non_empty(type_name, "wake.dedupe_key.const", value),
838 }
839 }
840}
841
842#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
843#[serde(rename_all = "snake_case")]
844pub enum RemoteProcessValueSelector {
845 Payload,
846 Pointer(String),
847 Const(serde_json::Value),
848 Template {
849 template: String,
850 #[serde(default)]
851 fields: BTreeMap<String, RemoteProcessValueSelector>,
852 },
853 Present(String),
854}
855
856impl RemoteProcessValueSelector {
857 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
858 match self {
859 Self::Payload | Self::Const(_) => Ok(()),
860 Self::Pointer(pointer) => require_non_empty(type_name, "selector.pointer", pointer),
861 Self::Template { template, fields } => {
862 require_non_empty(type_name, "selector.template", template)?;
863 for (name, selector) in fields {
864 require_non_empty(type_name, "selector.field", name)?;
865 selector.validate(type_name)?;
866 }
867 Ok(())
868 }
869 Self::Present(pointer) => require_non_empty(type_name, "selector.present", pointer),
870 }
871 }
872}
873
874#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
875pub struct RemoteRuntimeInvocation {
876 pub scope: RemoteRuntimeScope,
877 pub subject: RemoteRuntimeSubject,
878 #[serde(default, skip_serializing_if = "Option::is_none")]
879 pub caused_by: Option<RemoteCausalRef>,
880 #[serde(default, skip_serializing_if = "Option::is_none")]
881 pub replay: Option<RemoteRuntimeReplay>,
882}
883
884impl RemoteRuntimeInvocation {
885 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
886 self.scope.validate(type_name)?;
887 self.subject.validate(type_name)?;
888 if let Some(replay) = &self.replay {
889 require_non_empty(type_name, "replay.key", &replay.key)?;
890 }
891 Ok(())
892 }
893}
894
895#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
896pub struct RemoteRuntimeScope {
897 pub session_id: String,
898 #[serde(default, skip_serializing_if = "Option::is_none")]
899 pub turn_id: Option<String>,
900 #[serde(default, skip_serializing_if = "Option::is_none")]
901 pub turn_index: Option<usize>,
902 #[serde(default, skip_serializing_if = "Option::is_none")]
903 pub protocol_iteration: Option<usize>,
904}
905
906impl RemoteRuntimeScope {
907 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
908 require_non_empty(type_name, "runtime_scope.session_id", &self.session_id)?;
909 if let Some(turn_id) = &self.turn_id {
910 require_non_empty(type_name, "runtime_scope.turn_id", turn_id)?;
911 }
912 Ok(())
913 }
914}
915
916#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
917pub struct RemoteRuntimeReplay {
918 pub key: String,
919}
920
921#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
922#[serde(tag = "type", rename_all = "snake_case")]
923pub enum RemoteRuntimeSubject {
924 Effect {
925 effect_id: String,
926 kind: RemoteRuntimeEffectKind,
927 },
928 Process {
929 process_id: String,
930 },
931 ProcessEvent {
932 process_id: String,
933 sequence: u64,
934 event_type: String,
935 },
936 TriggerOccurrence {
937 occurrence_id: String,
938 },
939 SessionNode {
940 node_id: String,
941 },
942}
943
944impl RemoteRuntimeSubject {
945 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
946 match self {
947 Self::Effect { effect_id, .. } => {
948 require_non_empty(type_name, "runtime_subject.effect_id", effect_id)
949 }
950 Self::Process { process_id } => {
951 require_non_empty(type_name, "runtime_subject.process_id", process_id)
952 }
953 Self::ProcessEvent {
954 process_id,
955 event_type,
956 ..
957 } => {
958 require_non_empty(type_name, "runtime_subject.process_id", process_id)?;
959 require_non_empty(type_name, "runtime_subject.event_type", event_type)
960 }
961 Self::TriggerOccurrence { occurrence_id } => {
962 require_non_empty(type_name, "runtime_subject.occurrence_id", occurrence_id)
963 }
964 Self::SessionNode { node_id } => {
965 require_non_empty(type_name, "runtime_subject.node_id", node_id)
966 }
967 }
968 }
969}
970
971#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
972#[serde(rename_all = "snake_case")]
973pub enum RemoteRuntimeEffectKind {
974 LlmCall,
975 Direct,
976 ToolAttempt,
977 ToolBatch,
978 Process,
979 Trigger,
980 ExecCode,
981 Checkpoint,
982 SyncExecutionEnvironment,
983 Sleep,
984 AwaitEvent,
985 PeekAwaitEvent,
986 DurableStep,
987}
988
989#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
990#[serde(deny_unknown_fields)]
991pub struct RemoteProcessPluginOptions {
992 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
993 pub plugins: BTreeMap<String, serde_json::Value>,
994}
995
996fn default_remote_context_window_tokens() -> usize {
997 1
998}
999
1000#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1001#[serde(deny_unknown_fields)]
1002pub struct RemoteProcessModelLimits {
1003 #[serde(default = "default_remote_context_window_tokens")]
1004 pub context_window_tokens: usize,
1005 #[serde(default, skip_serializing_if = "Option::is_none")]
1006 pub output_token_capacity: Option<usize>,
1007}
1008
1009impl Default for RemoteProcessModelLimits {
1010 fn default() -> Self {
1011 Self {
1012 context_window_tokens: default_remote_context_window_tokens(),
1013 output_token_capacity: None,
1014 }
1015 }
1016}
1017
1018#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1019#[serde(deny_unknown_fields)]
1020pub struct RemoteProcessModelSpec {
1021 #[serde(default)]
1022 pub id: String,
1023 #[serde(default)]
1024 pub variant: crate::llm::RemoteReasoningSelection,
1025 #[serde(
1026 default,
1027 skip_serializing_if = "crate::llm::RemoteModelCapability::is_empty"
1028 )]
1029 pub capability: crate::llm::RemoteModelCapability,
1030 #[serde(default)]
1031 pub limits: RemoteProcessModelLimits,
1032}
1033
1034#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
1035#[serde(deny_unknown_fields)]
1036pub struct RemoteProcessExecutionPolicy {
1037 #[serde(default)]
1038 pub model: RemoteProcessModelSpec,
1039 #[serde(default)]
1040 pub provider_id: String,
1041 #[serde(default, skip_serializing_if = "Option::is_none")]
1042 pub session_id: Option<String>,
1043 #[serde(default)]
1044 pub autonomous: bool,
1045 #[serde(default, skip_serializing_if = "Option::is_none")]
1046 pub max_turns: Option<usize>,
1047 #[serde(default, skip_serializing_if = "RemotePromptLayer::is_empty")]
1048 pub prompt: RemotePromptLayer,
1049}
1050
1051#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
1052#[serde(deny_unknown_fields)]
1053pub struct RemoteProcessExecutionEnvSpec {
1054 #[serde(default, skip_serializing_if = "RemoteProcessPluginOptions::is_empty")]
1055 pub plugin_options: RemoteProcessPluginOptions,
1056 #[serde(
1057 default,
1058 skip_serializing_if = "RemoteProcessExecutionPolicy::is_empty"
1059 )]
1060 pub policy: RemoteProcessExecutionPolicy,
1061}
1062
1063impl RemoteProcessPluginOptions {
1064 pub fn is_empty(&self) -> bool {
1065 self.plugins.is_empty()
1066 }
1067}
1068
1069impl RemoteProcessExecutionPolicy {
1070 pub fn is_empty(&self) -> bool {
1071 self == &Self::default()
1072 }
1073}
1074
1075impl RemoteProcessExecutionEnvSpec {
1076 pub fn is_empty(&self) -> bool {
1077 self.plugin_options.is_empty() && self.policy.is_empty()
1078 }
1079
1080 pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
1081 if self.policy.model.limits.context_window_tokens == 0 {
1082 return Err(RemoteProtocolError::InvalidEnvelope {
1083 type_name,
1084 message:
1085 "env_spec.policy.model.limits.context_window_tokens must be greater than zero"
1086 .to_string(),
1087 });
1088 }
1089 if self
1090 .policy
1091 .model
1092 .limits
1093 .output_token_capacity
1094 .is_some_and(|value| value == 0)
1095 {
1096 return Err(RemoteProtocolError::InvalidEnvelope {
1097 type_name,
1098 message:
1099 "env_spec.policy.model.limits.output_token_capacity must be greater than zero"
1100 .to_string(),
1101 });
1102 }
1103 Ok(())
1104 }
1105}
1106
1107#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1108pub struct RemotePersistProcessEnvRequest {
1109 pub protocol_version: u32,
1110 pub env_spec: RemoteProcessExecutionEnvSpec,
1111}
1112
1113impl RemotePersistProcessEnvRequest {
1114 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1115 ensure_protocol_version(self.protocol_version)?;
1116 self.env_spec.validate("RemotePersistProcessEnvRequest")
1117 }
1118}
1119
1120#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1121pub struct RemotePersistProcessEnvResult {
1122 pub protocol_version: u32,
1123 pub env_ref: RemoteProcessExecutionEnvRef,
1124}
1125
1126impl RemotePersistProcessEnvResult {
1127 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1128 ensure_protocol_version(self.protocol_version)?;
1129 self.env_ref.validate("RemotePersistProcessEnvResult")
1130 }
1131}
1132
1133#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1134pub struct RemoteProcessStartRequest {
1135 pub protocol_version: u32,
1136 pub id: String,
1137 pub input: RemoteProcessInput,
1138 pub disposition: RemoteRecoveryDisposition,
1139 #[serde(default, skip_serializing_if = "Option::is_none")]
1140 pub env_spec: Option<RemoteProcessExecutionEnvSpec>,
1141 pub originator: RemoteProcessOriginator,
1142 #[serde(default, skip_serializing_if = "Option::is_none")]
1143 pub wake_target: Option<RemoteSessionScope>,
1144 #[serde(default, skip_serializing_if = "Option::is_none")]
1145 pub grant: Option<RemoteProcessStartGrant>,
1146 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1147 pub event_types: Vec<RemoteProcessEventType>,
1148}
1149
1150impl RemoteProcessStartRequest {
1151 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1152 ensure_protocol_version(self.protocol_version)?;
1153 require_non_empty("RemoteProcessStartRequest", "id", &self.id)?;
1154 self.input.validate("RemoteProcessStartRequest")?;
1155 if let Some(env_spec) = &self.env_spec {
1156 env_spec.validate("RemoteProcessStartRequest")?;
1157 }
1158 if let RemoteProcessInput::SessionTurn { turn_input, .. } = &self.input
1159 && turn_input.protocol_version != self.protocol_version
1160 {
1161 return Err(RemoteProtocolError::MismatchedNestedProtocolVersion {
1162 parent: "RemoteProcessStartRequest",
1163 child: "input.turn_input",
1164 parent_version: self.protocol_version,
1165 child_version: turn_input.protocol_version,
1166 });
1167 }
1168 self.originator.validate("RemoteProcessStartRequest")?;
1169 if let Some(wake_target) = &self.wake_target {
1170 wake_target.validate("RemoteProcessStartRequest")?;
1171 }
1172 if let Some(grant) = &self.grant {
1173 grant.validate("RemoteProcessStartRequest")?;
1174 }
1175 for event_type in &self.event_types {
1176 event_type.validate("RemoteProcessStartRequest")?;
1177 }
1178 Ok(())
1179 }
1180}
1181
1182#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1183pub struct RemoteProcessStartResult {
1184 pub protocol_version: u32,
1185 pub record: RemoteProcessRecord,
1186 #[serde(default, skip_serializing_if = "Option::is_none")]
1187 pub summary: Option<RemoteProcessSummary>,
1188}
1189
1190impl RemoteProcessStartResult {
1191 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1192 ensure_protocol_version(self.protocol_version)?;
1193 self.record.validate("RemoteProcessStartResult")?;
1194 if let Some(summary) = &self.summary {
1195 summary.validate("RemoteProcessStartResult")?;
1196 }
1197 Ok(())
1198 }
1199}
1200
1201#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1202#[serde(rename_all = "snake_case")]
1203pub enum RemoteProcessStatusFilter {
1204 #[default]
1205 Running,
1206 Completed,
1207 Failed,
1208 Cancelled,
1209 Abandoned,
1210 Any,
1211}
1212
1213#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1214pub struct RemoteProcessListFilter {
1215 pub protocol_version: u32,
1216 #[serde(default, skip_serializing_if = "Option::is_none")]
1217 pub definition: Option<RemoteProcessDefinitionIdentity>,
1218 #[serde(default)]
1219 pub status: RemoteProcessStatusFilter,
1220 #[serde(default, skip_serializing_if = "Option::is_none")]
1221 pub waiting: Option<bool>,
1222 #[serde(default, skip_serializing_if = "Option::is_none")]
1223 pub originator_scope_id: Option<String>,
1224 #[serde(default, skip_serializing_if = "Option::is_none")]
1225 pub identity_kind: Option<String>,
1226 #[serde(default, skip_serializing_if = "Option::is_none")]
1227 pub identity_label: Option<String>,
1228 #[serde(default, skip_serializing_if = "Option::is_none")]
1229 pub caused_by_occurrence_id: Option<String>,
1230 #[serde(default, skip_serializing_if = "Option::is_none")]
1231 pub caused_by_subscription_id: Option<String>,
1232 #[serde(default, skip_serializing_if = "Option::is_none")]
1233 pub created_at_start_ms: Option<u64>,
1234 #[serde(default, skip_serializing_if = "Option::is_none")]
1235 pub created_at_end_ms: Option<u64>,
1236}
1237
1238impl Default for RemoteProcessListFilter {
1239 fn default() -> Self {
1240 Self {
1241 protocol_version: REMOTE_PROTOCOL_VERSION,
1242 definition: None,
1243 status: RemoteProcessStatusFilter::Running,
1244 waiting: None,
1245 originator_scope_id: None,
1246 identity_kind: None,
1247 identity_label: None,
1248 caused_by_occurrence_id: None,
1249 caused_by_subscription_id: None,
1250 created_at_start_ms: None,
1251 created_at_end_ms: None,
1252 }
1253 }
1254}
1255
1256impl RemoteProcessListFilter {
1257 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1258 ensure_protocol_version(self.protocol_version)?;
1259 if let Some(definition) = &self.definition {
1260 definition.validate("RemoteProcessListFilter")?;
1261 }
1262 Ok(())
1263 }
1264}
1265
1266#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1267pub struct RemoteProcessListResponse {
1268 pub protocol_version: u32,
1269 #[serde(default)]
1270 pub records: Vec<RemoteObservedProcess>,
1271}
1272
1273impl RemoteProcessListResponse {
1274 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1275 ensure_protocol_version(self.protocol_version)?;
1276 for record in &self.records {
1277 record.validate("RemoteProcessListResponse")?;
1278 }
1279 Ok(())
1280 }
1281}
1282
1283#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1284pub struct RemoteProcessCancelRequest {
1285 pub protocol_version: u32,
1286 pub process_id: String,
1287 #[serde(default, skip_serializing_if = "Option::is_none")]
1288 pub reason: Option<String>,
1289}
1290
1291impl RemoteProcessCancelRequest {
1292 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1293 ensure_protocol_version(self.protocol_version)?;
1294 require_non_empty("RemoteProcessCancelRequest", "process_id", &self.process_id)?;
1295 if let Some(reason) = &self.reason {
1296 require_non_empty("RemoteProcessCancelRequest", "reason", reason)?;
1297 }
1298 Ok(())
1299 }
1300}
1301
1302#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1303pub struct RemoteProcessCancelResult {
1304 pub protocol_version: u32,
1305 pub process_id: String,
1306 pub status: RemoteProcessLifecycleStatus,
1307 #[serde(default, skip_serializing_if = "Option::is_none")]
1308 pub record: Option<RemoteProcessRecord>,
1309}
1310
1311impl RemoteProcessCancelResult {
1312 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1313 ensure_protocol_version(self.protocol_version)?;
1314 require_non_empty("RemoteProcessCancelResult", "process_id", &self.process_id)?;
1315 if let Some(record) = &self.record {
1316 record.validate("RemoteProcessCancelResult")?;
1317 }
1318 Ok(())
1319 }
1320}
1321
1322#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1323pub struct RemoteProcessSignalRequest {
1324 pub protocol_version: u32,
1325 pub process_id: String,
1326 pub signal_name: String,
1327 pub signal_id: String,
1328 #[serde(default)]
1329 pub payload: serde_json::Value,
1330 #[serde(default, skip_serializing_if = "Option::is_none")]
1331 pub replay_key: Option<String>,
1332 #[serde(default, skip_serializing_if = "Option::is_none")]
1333 pub wake_target_scope: Option<RemoteSessionScope>,
1334}
1335
1336impl RemoteProcessSignalRequest {
1337 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1338 ensure_protocol_version(self.protocol_version)?;
1339 require_non_empty("RemoteProcessSignalRequest", "process_id", &self.process_id)?;
1340 require_non_empty(
1341 "RemoteProcessSignalRequest",
1342 "signal_name",
1343 &self.signal_name,
1344 )?;
1345 require_non_empty("RemoteProcessSignalRequest", "signal_id", &self.signal_id)?;
1346 if let Some(replay_key) = &self.replay_key {
1347 require_non_empty("RemoteProcessSignalRequest", "replay_key", replay_key)?;
1348 }
1349 if let Some(scope) = &self.wake_target_scope {
1350 scope.validate("RemoteProcessSignalRequest")?;
1351 }
1352 Ok(())
1353 }
1354}
1355
1356#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1357pub struct RemoteProcessSignalResult {
1358 pub protocol_version: u32,
1359 pub event: RemoteProcessEvent,
1360}
1361
1362impl RemoteProcessSignalResult {
1363 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1364 ensure_protocol_version(self.protocol_version)?;
1365 self.event.validate("RemoteProcessSignalResult")
1366 }
1367}
1368
1369#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1370pub struct RemoteProcessAwaitRequest {
1371 pub protocol_version: u32,
1372 pub process_id: String,
1373}
1374
1375impl RemoteProcessAwaitRequest {
1376 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1377 ensure_protocol_version(self.protocol_version)?;
1378 require_non_empty("RemoteProcessAwaitRequest", "process_id", &self.process_id)
1379 }
1380}
1381
1382#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1383pub struct RemoteProcessAwaitResult {
1384 pub protocol_version: u32,
1385 pub process_id: String,
1386 pub output: RemoteProcessAwaitOutput,
1387}
1388
1389impl RemoteProcessAwaitResult {
1390 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1391 ensure_protocol_version(self.protocol_version)?;
1392 require_non_empty("RemoteProcessAwaitResult", "process_id", &self.process_id)?;
1393 self.output.validate("RemoteProcessAwaitResult")
1394 }
1395}
1396
1397#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
1398pub struct RemoteProcessEventsRequest {
1399 pub protocol_version: u32,
1400 pub process_id: String,
1401 #[serde(default)]
1402 pub after_sequence: u64,
1403}
1404
1405impl RemoteProcessEventsRequest {
1406 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1407 ensure_protocol_version(self.protocol_version)?;
1408 require_non_empty("RemoteProcessEventsRequest", "process_id", &self.process_id)
1409 }
1410}
1411
1412#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1413pub struct RemoteProcessEventsResponse {
1414 pub protocol_version: u32,
1415 pub process_id: String,
1416 #[serde(default)]
1417 pub events: Vec<RemoteProcessEvent>,
1418}
1419
1420impl RemoteProcessEventsResponse {
1421 pub fn validate(&self) -> Result<(), RemoteProtocolError> {
1422 ensure_protocol_version(self.protocol_version)?;
1423 require_non_empty(
1424 "RemoteProcessEventsResponse",
1425 "process_id",
1426 &self.process_id,
1427 )?;
1428 for event in &self.events {
1429 event.validate("RemoteProcessEventsResponse")?;
1430 }
1431 Ok(())
1432 }
1433}