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