#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteLashlangProcessRef {
pub component: String,
pub pos: u32,
}
impl RemoteLashlangProcessRef {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "process_ref.component", &self.component)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteSessionScope {
pub session_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_frame_id: Option<String>,
}
impl RemoteSessionScope {
pub fn new(session_id: impl Into<String>) -> Self {
Self {
session_id: session_id.into(),
agent_frame_id: None,
}
}
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "session_id", &self.session_id)?;
if let Some(agent_frame_id) = &self.agent_frame_id {
require_non_empty(type_name, "agent_frame_id", agent_frame_id)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RemoteProcessOriginator {
Host,
Session { scope: RemoteSessionScope },
}
impl RemoteProcessOriginator {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
match self {
Self::Host => Ok(()),
Self::Session { scope } => scope.validate(type_name),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessProvenance {
pub originator: RemoteProcessOriginator,
pub host_profile_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub caused_by: Option<RemoteCausalRef>,
}
impl RemoteProcessProvenance {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
self.originator.validate(type_name)?;
require_non_empty(type_name, "host_profile_id", &self.host_profile_id)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessDefinitionIdentity {
pub module_ref: String,
pub host_requirements_ref: String,
pub process_ref: RemoteLashlangProcessRef,
pub process_name: String,
}
impl RemoteProcessDefinitionIdentity {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "module_ref", &self.module_ref)?;
require_non_empty(type_name, "host_requirements_ref", &self.host_requirements_ref)?;
self.process_ref.validate(type_name)?;
require_non_empty(type_name, "process_name", &self.process_name)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessDefinitionSummary {
pub name: String,
}
impl RemoteProcessDefinitionSummary {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "definition.name", &self.name)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessHandleDescriptor {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
}
impl RemoteProcessHandleDescriptor {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
if let Some(kind) = &self.kind {
require_non_empty(type_name, "descriptor.kind", kind)?;
}
if let Some(label) = &self.label {
require_non_empty(type_name, "descriptor.label", label)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessStartGrant {
pub session_scope: RemoteSessionScope,
pub descriptor: RemoteProcessHandleDescriptor,
}
impl RemoteProcessStartGrant {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
self.session_scope.validate(type_name)?;
self.descriptor.validate(type_name)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RemoteProcessInput {
ToolCall {
#[serde(default)]
prepared_tool_call: serde_json::Value,
},
LashlangProcess {
module_ref: String,
process_ref: RemoteLashlangProcessRef,
host_requirements_ref: String,
process_name: String,
#[serde(default, skip_serializing_if = "serde_json::Map::is_empty")]
args: serde_json::Map<String, serde_json::Value>,
},
SessionTurn {
#[serde(default)]
create_request: serde_json::Value,
turn_input: RemoteTurnInput,
#[serde(default, skip_serializing_if = "RemoteToolOutputContract::is_static")]
output_contract: RemoteToolOutputContract,
},
External {
#[serde(default)]
metadata: serde_json::Value,
},
}
impl RemoteProcessInput {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
match self {
Self::ToolCall {
prepared_tool_call: _,
} => Ok(()),
Self::LashlangProcess {
module_ref,
process_ref,
host_requirements_ref,
process_name,
args: _,
} => {
require_non_empty(type_name, "module_ref", module_ref)?;
process_ref.validate(type_name)?;
require_non_empty(type_name, "host_requirements_ref", host_requirements_ref)?;
require_non_empty(type_name, "process_name", process_name)
}
Self::SessionTurn {
create_request: _,
turn_input,
output_contract,
} => {
turn_input.validate()?;
match output_contract {
RemoteToolOutputContract::Static => Ok(()),
RemoteToolOutputContract::FromInputSchema {
input_field,
default_schema: _,
} => require_non_empty(type_name, "output_contract.input_field", input_field),
}
}
Self::External { metadata: _ } => Ok(()),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RemoteProcessLifecycleStatus {
#[default]
Running,
Completed,
Failed,
Cancelled,
}
impl RemoteProcessLifecycleStatus {
pub fn is_terminal(self) -> bool {
!matches!(self, Self::Running)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "state", rename_all = "snake_case")]
pub enum RemoteProcessStatus {
Running,
Completed { await_output: RemoteProcessAwaitOutput },
Failed { await_output: RemoteProcessAwaitOutput },
Cancelled { await_output: RemoteProcessAwaitOutput },
}
impl Default for RemoteProcessStatus {
fn default() -> Self {
Self::Running
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RemoteProcessAwaitOutput {
Success {
value: serde_json::Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
control: Option<serde_json::Value>,
},
Failure {
class: RemoteToolFailureClass,
code: String,
message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
raw: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
control: Option<serde_json::Value>,
},
Cancelled {
message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
raw: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
control: Option<serde_json::Value>,
},
}
impl RemoteProcessAwaitOutput {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
match self {
Self::Success { .. } => Ok(()),
Self::Failure { code, message, .. } => {
require_non_empty(type_name, "await_output.code", code)?;
require_non_empty(type_name, "await_output.message", message)
}
Self::Cancelled { message, .. } => {
require_non_empty(type_name, "await_output.message", message)
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RemoteToolFailureClass {
InvalidRequest,
Unavailable,
PermissionDenied,
Timeout,
Execution,
External,
ResourceLimit,
Internal,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessExternalRef {
pub backend: String,
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
impl RemoteProcessExternalRef {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "external_ref.backend", &self.backend)?;
require_non_empty(type_name, "external_ref.id", &self.id)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessWaitState {
pub kind: RemoteProcessWaitKind,
pub since_ms: u64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum RemoteProcessWaitKind {
Signal {
name: String,
event_type: String,
key: String,
ordinal: u64,
},
}
impl RemoteProcessWaitState {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
match &self.kind {
RemoteProcessWaitKind::Signal {
name,
event_type,
key,
ordinal,
} => {
require_non_empty(type_name, "wait.name", name)?;
require_non_empty(type_name, "wait.event_type", event_type)?;
require_non_empty(type_name, "wait.key", key)?;
if *ordinal == 0 {
return Err(RemoteProtocolError::InvalidEnvelope {
type_name,
message: "wait ordinal must be non-zero".to_string(),
});
}
Ok(())
}
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessSummary {
#[serde(rename = "__handle__")]
pub handle_type: String,
pub id: String,
pub process_id: String,
pub descriptor: RemoteProcessHandleDescriptor,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub definition: Option<RemoteProcessDefinitionSummary>,
pub status: RemoteProcessLifecycleStatus,
}
impl RemoteProcessSummary {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "handle_type", &self.handle_type)?;
require_non_empty(type_name, "id", &self.id)?;
require_non_empty(type_name, "process_id", &self.process_id)?;
self.descriptor.validate(type_name)?;
if let Some(definition) = &self.definition {
definition.validate(type_name)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessRecord {
pub process_id: String,
pub input: RemoteProcessInput,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub event_types: Vec<RemoteProcessEventType>,
pub provenance: RemoteProcessProvenance,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub env_ref: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake_target: Option<RemoteSessionScope>,
pub created_at_ms: u64,
pub updated_at_ms: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub external_ref: Option<RemoteProcessExternalRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wait: Option<RemoteProcessWaitState>,
#[serde(default)]
pub status: RemoteProcessStatus,
}
impl RemoteProcessRecord {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "process_id", &self.process_id)?;
self.input.validate(type_name)?;
for event_type in &self.event_types {
event_type.validate(type_name)?;
}
self.provenance.validate(type_name)?;
if let Some(env_ref) = &self.env_ref {
require_non_empty(type_name, "env_ref", env_ref)?;
}
if let Some(wake_target) = &self.wake_target {
wake_target.validate(type_name)?;
}
if let Some(external_ref) = &self.external_ref {
external_ref.validate(type_name)?;
}
if let Some(wait) = &self.wait {
wait.validate(type_name)?;
}
match &self.status {
RemoteProcessStatus::Running => Ok(()),
RemoteProcessStatus::Completed { await_output }
| RemoteProcessStatus::Failed { await_output }
| RemoteProcessStatus::Cancelled { await_output } => await_output.validate(type_name),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessWorkSnapshot {
pub protocol_version: u32,
pub session_id: String,
#[serde(default)]
pub visible_process_ids: Vec<String>,
#[serde(default)]
pub items: Vec<RemoteProcessWorkItem>,
}
impl RemoteProcessWorkSnapshot {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty("RemoteProcessWorkSnapshot", "session_id", &self.session_id)?;
for process_id in &self.visible_process_ids {
require_non_empty("RemoteProcessWorkSnapshot", "visible_process_ids", process_id)?;
}
for item in &self.items {
item.validate("RemoteProcessWorkSnapshot")?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessWorkItem {
pub process: RemoteObservedProcess,
pub descriptor: RemoteProcessHandleDescriptor,
#[serde(default)]
pub events: Vec<RemoteObservedProcessEvent>,
pub kind: String,
pub label: String,
}
impl RemoteProcessWorkItem {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
self.process.validate(type_name)?;
self.descriptor.validate(type_name)?;
for event in &self.events {
event.validate(type_name)?;
}
require_non_empty(type_name, "kind", &self.kind)?;
require_non_empty(type_name, "label", &self.label)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteObservedProcess {
pub process_id: String,
pub graph_key: String,
pub kind: String,
pub lifecycle: RemoteProcessLifecycleStatus,
pub status_label: String,
pub terminal: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
pub created_at_ms: u64,
pub updated_at_ms: u64,
pub input: RemoteProcessInput,
pub originator: RemoteProcessOriginator,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub env_ref: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake_target: Option<RemoteSessionScope>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub caused_by: Option<RemoteCausalRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub external_ref: Option<RemoteProcessExternalRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wait: Option<RemoteProcessWaitState>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub child_session_id: Option<String>,
pub label: String,
}
impl RemoteObservedProcess {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "process_id", &self.process_id)?;
require_non_empty(type_name, "graph_key", &self.graph_key)?;
require_non_empty(type_name, "kind", &self.kind)?;
require_non_empty(type_name, "status_label", &self.status_label)?;
self.input.validate(type_name)?;
self.originator.validate(type_name)?;
if let Some(env_ref) = &self.env_ref {
require_non_empty(type_name, "env_ref", env_ref)?;
}
if let Some(wake_target) = &self.wake_target {
wake_target.validate(type_name)?;
}
if let Some(external_ref) = &self.external_ref {
external_ref.validate(type_name)?;
}
if let Some(wait) = &self.wait {
wait.validate(type_name)?;
}
if let Some(child_session_id) = &self.child_session_id {
require_non_empty(type_name, "child_session_id", child_session_id)?;
}
require_non_empty(type_name, "label", &self.label)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteObservedProcessEvent {
pub sequence: u64,
pub event_type: String,
pub occurred_at_ms: u64,
#[serde(default)]
pub payload: serde_json::Value,
}
impl RemoteObservedProcessEvent {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "event_type", &self.event_type)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessEvent {
pub process_id: String,
pub sequence: u64,
pub event_type: String,
#[serde(default)]
pub payload: serde_json::Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub invocation: Option<RemoteRuntimeInvocation>,
#[serde(default)]
pub semantics: RemoteProcessEventSemantics,
pub occurred_at_ms: u64,
}
impl RemoteProcessEvent {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "process_id", &self.process_id)?;
require_non_empty(type_name, "event_type", &self.event_type)?;
if let Some(invocation) = &self.invocation {
invocation.validate(type_name)?;
}
self.semantics.validate(type_name)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessEventType {
pub name: String,
#[serde(default)]
pub payload_schema: serde_json::Value,
#[serde(default)]
pub semantics: RemoteProcessEventSemanticsSpec,
}
impl RemoteProcessEventType {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "event_type.name", &self.name)?;
self.semantics.validate(type_name)
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessEventSemanticsSpec {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub terminal: Option<RemoteProcessTerminalSpec>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake: Option<RemoteProcessWakeSpec>,
}
impl RemoteProcessEventSemanticsSpec {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
if let Some(terminal) = &self.terminal {
terminal.validate(type_name)?;
}
if let Some(wake) = &self.wake {
wake.validate(type_name)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessTerminalSpec {
pub state: RemoteProcessTerminalState,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub await_output: Option<RemoteProcessValueSelector>,
}
impl RemoteProcessTerminalSpec {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
if let Some(await_output) = &self.await_output {
await_output.validate(type_name)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessWakeSpec {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub when: Option<RemoteProcessValueSelector>,
pub input: RemoteProcessValueSelector,
#[serde(default)]
pub dedupe_key: RemoteProcessWakeDedupeKey,
}
impl RemoteProcessWakeSpec {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
if let Some(when) = &self.when {
when.validate(type_name)?;
}
self.input.validate(type_name)?;
self.dedupe_key.validate(type_name)
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessEventSemantics {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub terminal: Option<RemoteProcessTerminalSemantics>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake: Option<RemoteProcessWake>,
}
impl RemoteProcessEventSemantics {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
if let Some(terminal) = &self.terminal {
terminal.await_output.validate(type_name)?;
}
if let Some(wake) = &self.wake {
wake.validate(type_name)?;
}
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RemoteProcessTerminalState {
Completed,
Failed,
Cancelled,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessTerminalSemantics {
pub state: RemoteProcessTerminalState,
pub await_output: RemoteProcessAwaitOutput,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessWake {
pub input: String,
pub dedupe_key: String,
}
impl RemoteProcessWake {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "wake.input", &self.input)?;
require_non_empty(type_name, "wake.dedupe_key", &self.dedupe_key)
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RemoteProcessWakeDedupeKey {
#[default]
EventIdentity,
Selector(RemoteProcessValueSelector),
Const(String),
}
impl RemoteProcessWakeDedupeKey {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
match self {
Self::EventIdentity => Ok(()),
Self::Selector(selector) => selector.validate(type_name),
Self::Const(value) => require_non_empty(type_name, "wake.dedupe_key.const", value),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RemoteProcessValueSelector {
Payload,
Pointer(String),
Const(serde_json::Value),
Template {
template: String,
#[serde(default)]
fields: BTreeMap<String, RemoteProcessValueSelector>,
},
Present(String),
}
impl RemoteProcessValueSelector {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
match self {
Self::Payload | Self::Const(_) => Ok(()),
Self::Pointer(pointer) => require_non_empty(type_name, "selector.pointer", pointer),
Self::Template { template, fields } => {
require_non_empty(type_name, "selector.template", template)?;
for (name, selector) in fields {
require_non_empty(type_name, "selector.field", name)?;
selector.validate(type_name)?;
}
Ok(())
}
Self::Present(pointer) => require_non_empty(type_name, "selector.present", pointer),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteRuntimeInvocation {
pub scope: RemoteRuntimeScope,
pub subject: RemoteRuntimeSubject,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub caused_by: Option<RemoteCausalRef>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub replay: Option<RemoteRuntimeReplay>,
}
impl RemoteRuntimeInvocation {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
self.scope.validate(type_name)?;
self.subject.validate(type_name)?;
if let Some(replay) = &self.replay {
require_non_empty(type_name, "replay.key", &replay.key)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteRuntimeScope {
pub session_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub turn_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub turn_index: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub protocol_iteration: Option<usize>,
}
impl RemoteRuntimeScope {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "runtime_scope.session_id", &self.session_id)?;
if let Some(turn_id) = &self.turn_id {
require_non_empty(type_name, "runtime_scope.turn_id", turn_id)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteRuntimeReplay {
pub key: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RemoteRuntimeSubject {
Effect {
effect_id: String,
kind: RemoteRuntimeEffectKind,
},
Process {
process_id: String,
},
ProcessEvent {
process_id: String,
sequence: u64,
event_type: String,
},
TriggerOccurrence {
occurrence_id: String,
},
SessionNode {
node_id: String,
},
}
impl RemoteRuntimeSubject {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
match self {
Self::Effect { effect_id, .. } => {
require_non_empty(type_name, "runtime_subject.effect_id", effect_id)
}
Self::Process { process_id } => {
require_non_empty(type_name, "runtime_subject.process_id", process_id)
}
Self::ProcessEvent {
process_id,
event_type,
..
} => {
require_non_empty(type_name, "runtime_subject.process_id", process_id)?;
require_non_empty(type_name, "runtime_subject.event_type", event_type)
}
Self::TriggerOccurrence { occurrence_id } => {
require_non_empty(type_name, "runtime_subject.occurrence_id", occurrence_id)
}
Self::SessionNode { node_id } => {
require_non_empty(type_name, "runtime_subject.node_id", node_id)
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RemoteRuntimeEffectKind {
LlmCall,
Direct,
ToolCall,
Process,
ExecCode,
Checkpoint,
SyncExecutionEnvironment,
Sleep,
AwaitEvent,
DurableStep,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessStartRequest {
pub protocol_version: u32,
pub id: String,
pub input: RemoteProcessInput,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub env_spec: Option<serde_json::Value>,
pub originator: RemoteProcessOriginator,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake_target: Option<RemoteSessionScope>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub grant: Option<RemoteProcessStartGrant>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub event_types: Vec<RemoteProcessEventType>,
}
impl RemoteProcessStartRequest {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty("RemoteProcessStartRequest", "id", &self.id)?;
self.input.validate("RemoteProcessStartRequest")?;
if let RemoteProcessInput::SessionTurn { turn_input, .. } = &self.input
&& turn_input.protocol_version != self.protocol_version
{
return Err(RemoteProtocolError::MismatchedNestedProtocolVersion {
parent: "RemoteProcessStartRequest",
child: "input.turn_input",
parent_version: self.protocol_version,
child_version: turn_input.protocol_version,
});
}
self.originator.validate("RemoteProcessStartRequest")?;
if let Some(wake_target) = &self.wake_target {
wake_target.validate("RemoteProcessStartRequest")?;
}
if let Some(grant) = &self.grant {
grant.validate("RemoteProcessStartRequest")?;
}
for event_type in &self.event_types {
event_type.validate("RemoteProcessStartRequest")?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessStartResult {
pub protocol_version: u32,
pub record: RemoteProcessRecord,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub summary: Option<RemoteProcessSummary>,
}
impl RemoteProcessStartResult {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
self.record.validate("RemoteProcessStartResult")?;
if let Some(summary) = &self.summary {
summary.validate("RemoteProcessStartResult")?;
}
Ok(())
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RemoteProcessStatusFilter {
#[default]
Running,
Completed,
Failed,
Cancelled,
Any,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessListFilter {
pub protocol_version: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub definition: Option<RemoteProcessDefinitionIdentity>,
#[serde(default)]
pub status: RemoteProcessStatusFilter,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub waiting: Option<bool>,
}
impl Default for RemoteProcessListFilter {
fn default() -> Self {
Self {
protocol_version: REMOTE_PROTOCOL_VERSION,
definition: None,
status: RemoteProcessStatusFilter::Running,
waiting: None,
}
}
}
impl RemoteProcessListFilter {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
if let Some(definition) = &self.definition {
definition.validate("RemoteProcessListFilter")?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessListResponse {
pub protocol_version: u32,
#[serde(default)]
pub records: Vec<RemoteObservedProcess>,
}
impl RemoteProcessListResponse {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
for record in &self.records {
record.validate("RemoteProcessListResponse")?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessCancelRequest {
pub protocol_version: u32,
pub process_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
impl RemoteProcessCancelRequest {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteProcessCancelRequest",
"process_id",
&self.process_id,
)?;
if let Some(reason) = &self.reason {
require_non_empty("RemoteProcessCancelRequest", "reason", reason)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessCancelResult {
pub protocol_version: u32,
pub process_id: String,
pub status: RemoteProcessLifecycleStatus,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub record: Option<RemoteProcessRecord>,
}
impl RemoteProcessCancelResult {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteProcessCancelResult",
"process_id",
&self.process_id,
)?;
if let Some(record) = &self.record {
record.validate("RemoteProcessCancelResult")?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessSignalRequest {
pub protocol_version: u32,
pub process_id: String,
pub signal_name: String,
pub signal_id: String,
#[serde(default)]
pub payload: serde_json::Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub replay_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake_target_scope: Option<RemoteSessionScope>,
}
impl RemoteProcessSignalRequest {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteProcessSignalRequest",
"process_id",
&self.process_id,
)?;
require_non_empty(
"RemoteProcessSignalRequest",
"signal_name",
&self.signal_name,
)?;
require_non_empty(
"RemoteProcessSignalRequest",
"signal_id",
&self.signal_id,
)?;
if let Some(replay_key) = &self.replay_key {
require_non_empty("RemoteProcessSignalRequest", "replay_key", replay_key)?;
}
if let Some(scope) = &self.wake_target_scope {
scope.validate("RemoteProcessSignalRequest")?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessSignalResult {
pub protocol_version: u32,
pub event: RemoteProcessEvent,
}
impl RemoteProcessSignalResult {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
self.event.validate("RemoteProcessSignalResult")
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessAwaitRequest {
pub protocol_version: u32,
pub process_id: String,
}
impl RemoteProcessAwaitRequest {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteProcessAwaitRequest",
"process_id",
&self.process_id,
)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessAwaitResult {
pub protocol_version: u32,
pub process_id: String,
pub output: RemoteProcessAwaitOutput,
}
impl RemoteProcessAwaitResult {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteProcessAwaitResult",
"process_id",
&self.process_id,
)?;
self.output.validate("RemoteProcessAwaitResult")
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessEventsRequest {
pub protocol_version: u32,
pub process_id: String,
#[serde(default)]
pub after_sequence: u64,
}
impl RemoteProcessEventsRequest {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteProcessEventsRequest",
"process_id",
&self.process_id,
)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteProcessEventsResponse {
pub protocol_version: u32,
pub process_id: String,
#[serde(default)]
pub events: Vec<RemoteProcessEvent>,
}
impl RemoteProcessEventsResponse {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteProcessEventsResponse",
"process_id",
&self.process_id,
)?;
for event in &self.events {
event.validate("RemoteProcessEventsResponse")?;
}
Ok(())
}
}