use super::{
types::{
AgentRosterRow, MiddlewareDecisionEvidence, ModelRouteDecisionPayload,
OrchestrationObservation, ProtocolEventMeta, SelfReviewProposalDraft,
},
UserQuestion, VerificationIssue,
};
use crate::message::TranscriptMessage;
use crate::task::TaskNode;
use crate::tool::ToolCall;
use crate::trust::TrustEnvelope;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct GoalStepV1 {
pub id: String,
pub label: String,
pub weight: i64,
pub state: String,
pub verification_state: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct GoalSnapshotV1 {
pub goal_id: String,
pub objective: String,
pub status: String,
pub started_at: String,
pub closed_at: Option<String>,
pub dismissed_at: Option<String>,
pub decomposition_state: String,
pub plan_revision: i64,
pub completion_percent: Option<i64>,
pub now: Option<String>,
pub next: Option<String>,
pub steps: Vec<GoalStepV1>,
pub verification_state: String,
pub budget_tokens: i64,
pub tokens_used: i64,
pub continuation_count: i64,
pub no_progress_count: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct CompactionFederationSelectionReceiptV1 {
pub selected_item_ids: Vec<String>,
pub selection_hash: String,
}
pub const COMPACTION_FEDERATION_SCHEMA_V1: &str = "compaction-federation-v1";
fn compaction_federation_schema_v1() -> String {
COMPACTION_FEDERATION_SCHEMA_V1.to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct CompactionFederationDecisionV1 {
#[serde(rename = "$schema", default = "compaction_federation_schema_v1")]
pub schema: String,
pub identity: String,
pub fence: String,
pub scope: String,
pub decision: String,
pub selection_receipt: CompactionFederationSelectionReceiptV1,
pub issued_monotonic_elapsed_ms: u64,
pub expires_after_elapsed_ms: u64,
pub restart_epoch: u64,
}
impl CompactionFederationDecisionV1 {
pub fn is_live(&self, now_monotonic_elapsed_ms: u64, current_restart_epoch: u64) -> bool {
if current_restart_epoch != self.restart_epoch {
return false;
}
match now_monotonic_elapsed_ms.checked_sub(self.issued_monotonic_elapsed_ms) {
Some(elapsed) => elapsed <= self.expires_after_elapsed_ms,
None => false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "$kind")]
pub enum ProtocolEvent {
#[serde(rename = "sessionStarted", rename_all = "camelCase")]
SessionStarted {
session_id: String,
seq: i64,
created_at: String,
title: Option<String>,
},
#[serde(rename = "sessionTitleUpdated", rename_all = "camelCase")]
SessionTitleUpdated {
session_id: String,
seq: i64,
created_at: String,
title: String,
},
#[serde(rename = "assistantDelta", rename_all = "camelCase")]
AssistantDelta {
session_id: String,
seq: i64,
created_at: String,
text: String,
is_reasoning: bool,
},
#[serde(rename = "assistantMessageCompleted", rename_all = "camelCase")]
AssistantMessageCompleted {
session_id: String,
seq: i64,
created_at: String,
message: TranscriptMessage,
},
#[serde(rename = "toolCallStarted", rename_all = "camelCase")]
ToolCallStarted {
session_id: String,
seq: i64,
created_at: String,
call: ToolCall,
},
#[serde(rename = "toolApprovalRequested", rename_all = "camelCase")]
ToolApprovalRequested {
session_id: String,
seq: i64,
created_at: String,
call: ToolCall,
risk_label: String,
proposed_change: Option<String>,
policy_source: Option<String>,
#[serde(default)]
middleware_decisions: Vec<MiddlewareDecisionEvidence>,
},
#[serde(rename = "toolApprovalResolved", rename_all = "camelCase")]
ToolApprovalResolved {
session_id: String,
seq: i64,
created_at: String,
tool_call_id: String,
approved: bool,
},
#[serde(rename = "toolApprovalReviewed", rename_all = "camelCase")]
ToolApprovalReviewed {
session_id: String,
seq: i64,
created_at: String,
tool_call_id: String,
tool_name: String,
correlation_id: String,
verdict: String,
reason: String,
reviewer_configured: bool,
},
#[serde(rename = "toolResultAdded", rename_all = "camelCase")]
ToolResultAdded {
session_id: String,
seq: i64,
created_at: String,
result: TranscriptMessage,
},
#[serde(rename = "sessionTurnFinished", rename_all = "camelCase")]
SessionTurnFinished {
session_id: String,
seq: i64,
created_at: String,
turn_id: String,
status: String,
},
#[serde(rename = "streamResyncRequired", rename_all = "camelCase")]
StreamResyncRequired {
session_id: String,
seq: i64,
created_at: String,
after_seq: i64,
oldest_available_seq: i64,
high_water_mark: i64,
},
#[serde(rename = "persistenceFailed", rename_all = "camelCase")]
PersistenceFailed {
session_id: String,
seq: i64,
created_at: String,
reason: String,
},
#[serde(rename = "overloaded", rename_all = "camelCase")]
Overloaded {
session_id: String,
seq: i64,
created_at: String,
scope: String,
limit: u64,
current: u64,
#[serde(default)]
retry_after_ms: u64,
},
#[serde(rename = "providerRetrying", rename_all = "camelCase")]
ProviderRetrying {
session_id: String,
seq: i64,
created_at: String,
provider: String,
reason: String,
attempt: u32,
max_attempts: u32,
delay_ms: u64,
},
#[serde(rename = "sessionCompactionStarted", rename_all = "camelCase")]
SessionCompactionStarted {
session_id: String,
seq: i64,
created_at: String,
#[serde(default)]
trigger: String,
#[serde(default)]
command_id: String,
},
#[serde(rename = "verificationFinished", rename_all = "camelCase")]
VerificationFinished {
session_id: String,
seq: i64,
created_at: String,
summary: String,
passed: bool,
#[serde(default)]
tool: String,
#[serde(default)]
issue_count: i32,
#[serde(default)]
issues: Vec<VerificationIssue>,
},
#[serde(rename = "taskGraphUpdated", rename_all = "camelCase")]
TaskGraphUpdated {
session_id: String,
seq: i64,
created_at: String,
summary: String,
#[serde(default)]
tasks: Vec<TaskNode>,
},
#[serde(rename = "taskStatusUpdated", rename_all = "camelCase")]
TaskStatusUpdated {
session_id: String,
seq: i64,
created_at: String,
task_id: String,
context_id: String,
state: String,
task: Value,
},
#[serde(rename = "taskArtifactUpdated", rename_all = "camelCase")]
TaskArtifactUpdated {
session_id: String,
seq: i64,
created_at: String,
task_id: String,
context_id: String,
artifact_id: String,
artifact: Value,
},
#[serde(rename = "artifactLineageUpdated", rename_all = "camelCase")]
ArtifactLineageUpdated {
session_id: String,
seq: i64,
created_at: String,
task_id: String,
context_id: String,
artifact_id: String,
lineage: Value,
},
#[serde(rename = "runInterrupted", rename_all = "camelCase")]
RunInterrupted {
session_id: String,
seq: i64,
created_at: String,
reason: Option<String>,
},
#[serde(rename = "runFailed", rename_all = "camelCase")]
RunFailed {
session_id: String,
seq: i64,
created_at: String,
error: String,
#[serde(default)]
kind: String,
#[serde(default)]
hint: String,
},
#[serde(rename = "sessionCompacted", rename_all = "camelCase")]
SessionCompacted {
session_id: String,
seq: i64,
created_at: String,
summary: String,
#[serde(default)]
dropped_count: i32,
#[serde(default)]
tier: String,
#[serde(default)]
tokens_before: u64,
#[serde(default)]
tokens_after: u64,
#[serde(default)]
epoch: u64,
#[serde(default)]
command_id: String,
retained_turns: u32,
},
#[serde(rename = "sessionContextFolded", rename_all = "camelCase")]
SessionContextFolded {
session_id: String,
seq: i64,
created_at: String,
subtask_id: String,
start_marker: String,
end_marker: String,
fold: TranscriptMessage,
},
#[serde(rename = "usageUpdated", rename_all = "camelCase")]
UsageUpdated {
session_id: String,
seq: i64,
created_at: String,
prompt_tokens: i32,
completion_tokens: i32,
cost_usd: f64,
context_tokens: i32,
context_percent: f64,
#[serde(default)]
cache_read_tokens: i32,
#[serde(default)]
cache_creation_tokens: i32,
#[serde(default = "default_cost_known")]
cost_known: bool,
},
#[serde(rename = "turnUsage", rename_all = "camelCase")]
TurnUsage {
session_id: String,
seq: i64,
created_at: String,
input_tokens: i64,
cached_input_tokens: i64,
#[serde(default)]
cache_creation_tokens: i64,
output_tokens: i64,
#[serde(default)]
reasoning_tokens: i64,
#[serde(default)]
context_window: i64,
#[serde(default)]
context_used_tokens: i64,
#[serde(default)]
context_used_pct: f64,
#[serde(default)]
cache_hit_pct: f64,
#[serde(default)]
session_cache_hit_pct: f64,
},
#[serde(rename = "promptCacheBreak", rename_all = "camelCase")]
PromptCacheBreak {
session_id: String,
seq: i64,
created_at: String,
reason: String,
expected: bool,
tokens_lost: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
estimated_cost_lost: Option<f64>,
turn: i64,
#[serde(default)]
detail: String,
#[serde(default)]
previous_cache_read_tokens: i64,
#[serde(default)]
cache_read_tokens: i64,
#[serde(default)]
cache_creation_tokens: i64,
},
#[serde(rename = "toolOutputDelta", rename_all = "camelCase")]
ToolOutputDelta {
session_id: String,
seq: i64,
created_at: String,
call_id: String,
stream: String,
text: String,
},
#[serde(rename = "backgroundShellExited", rename_all = "camelCase")]
BackgroundShellExited {
session_id: String,
seq: i64,
created_at: String,
shell_id: String,
#[serde(default)]
command: String,
status: super::types::ShellExitStatus,
#[serde(default)]
output_bytes: u64,
},
#[serde(rename = "budgetExceeded", rename_all = "camelCase")]
BudgetExceeded {
session_id: String,
seq: i64,
created_at: String,
#[serde(default)]
scope: String,
current_usd: f64,
ceiling_usd: f64,
#[serde(default)]
hint: String,
},
#[serde(rename = "providerRouteUpdated", rename_all = "camelCase")]
ProviderRouteUpdated {
session_id: String,
seq: i64,
created_at: String,
#[serde(default)]
state: String,
#[serde(default)]
provider: String,
#[serde(default)]
model: String,
#[serde(default)]
failure_kind: String,
#[serde(default)]
detail: String,
},
#[serde(rename = "accountRateLimited", rename_all = "camelCase")]
AccountRateLimited {
session_id: String,
seq: i64,
created_at: String,
#[serde(default)]
provider: String,
#[serde(default)]
account: String,
#[serde(default)]
account_id: Option<String>,
#[serde(default)]
account_kind: Option<String>,
#[serde(default)]
email: Option<String>,
#[serde(default)]
organization: Option<String>,
#[serde(default)]
status: String,
#[serde(default)]
rate_limit_type: Option<String>,
#[serde(default)]
resets_at: Option<u64>,
#[serde(default)]
utilization: Option<f64>,
#[serde(default)]
overage_status: Option<String>,
#[serde(default)]
error_code: Option<String>,
},
#[serde(rename = "accountUsageReported", rename_all = "camelCase")]
AccountUsageReported {
session_id: String,
seq: i64,
created_at: String,
#[serde(default)]
provider: String,
#[serde(default)]
account: String,
#[serde(default)]
account_id: Option<String>,
#[serde(default)]
account_kind: Option<String>,
#[serde(default)]
email: Option<String>,
#[serde(default)]
total_cost_usd: Option<f64>,
#[serde(default)]
duration_ms: Option<u64>,
#[serde(default)]
num_turns: Option<u64>,
#[serde(default)]
input_tokens: u64,
#[serde(default)]
output_tokens: u64,
#[serde(default)]
cache_read_tokens: u64,
#[serde(default)]
cache_creation_tokens: u64,
#[serde(default)]
models: Vec<String>,
},
#[serde(rename = "dispatchDecided", rename_all = "camelCase")]
DispatchDecided {
session_id: String,
seq: i64,
created_at: String,
strategy: String,
rationale: String,
},
#[serde(rename = "orchestrationObservationRecorded", rename_all = "camelCase")]
OrchestrationObservationRecorded {
session_id: String,
seq: i64,
created_at: String,
observation: OrchestrationObservation,
},
#[serde(rename = "agentQueryIssued", rename_all = "camelCase")]
AgentQueryIssued {
session_id: String,
seq: i64,
created_at: String,
query_id: String,
from_role: String,
to_role: String,
query_type: String,
expected_format: String,
},
#[serde(rename = "agentQueryResponded", rename_all = "camelCase")]
AgentQueryResponded {
session_id: String,
seq: i64,
created_at: String,
query_id: String,
from_role: String,
to_role: String,
confidence: f64,
},
#[serde(rename = "humanSteeringInjected", rename_all = "camelCase")]
HumanSteeringInjected {
session_id: String,
seq: i64,
created_at: String,
injected_by: String,
content_preview: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
text: Option<String>,
},
#[serde(rename = "subAgentSpawned", rename_all = "camelCase")]
SubAgentSpawned {
session_id: String,
seq: i64,
created_at: String,
sub_session_id: String,
role: String,
task_title: String,
},
#[serde(rename = "subAgentCompleted", rename_all = "camelCase")]
SubAgentCompleted {
session_id: String,
seq: i64,
created_at: String,
sub_session_id: String,
role: String,
success: bool,
summary: String,
#[serde(default = "default_worker_outcome")]
outcome: String,
#[serde(default)]
outcome_detail: String,
},
#[serde(rename = "subAgentCancelled", rename_all = "camelCase")]
SubAgentCancelled {
session_id: String,
seq: i64,
created_at: String,
sub_session_id: String,
role: String,
cancelled_by: String,
},
#[serde(rename = "userMessageSubmitted", rename_all = "camelCase")]
UserMessageSubmitted {
session_id: String,
seq: i64,
created_at: String,
text: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
nonce: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
trust: Option<TrustEnvelope>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
attachments: Vec<crate::ReferenceMeta>,
},
#[serde(rename = "userQuestionAsked", rename_all = "camelCase")]
UserQuestionAsked {
session_id: String,
seq: i64,
created_at: String,
question_id: String,
questions: Vec<UserQuestion>,
},
#[serde(rename = "mcpElicitationRequested", rename_all = "camelCase")]
McpElicitationRequested {
session_id: String,
seq: i64,
created_at: String,
request: crate::approvals::ElicitationRequestEvent,
},
#[serde(rename = "credentialRequested", rename_all = "camelCase")]
CredentialRequested {
session_id: String,
seq: i64,
created_at: String,
tool_call_id: String,
provider: String,
},
#[serde(rename = "credentialResolved", rename_all = "camelCase")]
CredentialResolved {
session_id: String,
seq: i64,
created_at: String,
tool_call_id: String,
outcome: String,
},
#[serde(rename = "userQuestionAnswered", rename_all = "camelCase")]
UserQuestionAnswered {
session_id: String,
seq: i64,
created_at: String,
question_id: String,
},
#[serde(rename = "planPresented", rename_all = "camelCase")]
PlanPresented {
session_id: String,
seq: i64,
created_at: String,
plan_id: String,
plan: String,
},
#[serde(rename = "agentRosterUpdated", rename_all = "camelCase")]
AgentRosterUpdated {
session_id: String,
seq: i64,
created_at: String,
agents: Vec<AgentRosterRow>,
},
#[serde(rename = "checkRunCompleted", rename_all = "camelCase")]
CheckRunCompleted {
session_id: String,
seq: i64,
created_at: String,
check_id: String,
command: String,
exit_code: i32,
attempts: u32,
duration_ms: u64,
passed: bool,
jury_skipped: bool,
},
#[serde(rename = "goalProgressUpdated", rename_all = "camelCase")]
GoalProgressUpdated {
session_id: String,
seq: i64,
created_at: String,
#[serde(flatten)]
snapshot: GoalSnapshotV1,
},
#[serde(rename = "selfReviewProposalReceived", rename_all = "camelCase")]
SelfReviewProposalReceived {
session_id: String,
seq: i64,
created_at: String,
proposal: SelfReviewProposalDraft,
},
#[serde(rename = "modelRouteDecision", rename_all = "camelCase")]
ModelRouteDecision {
session_id: String,
seq: i64,
created_at: String,
#[serde(flatten)]
decision: ModelRouteDecisionPayload,
},
#[serde(rename = "runGovernanceRejected", rename_all = "camelCase")]
RunGovernanceRejected {
session_id: String,
seq: i64,
created_at: String,
kind: super::types::RunFailureKind,
tool_call_id: String,
#[serde(default)]
budget: Option<super::types::RunBudgetExhausted>,
#[serde(default)]
ownership: Option<super::types::RunOwnershipFailure>,
#[serde(default)]
origin: Option<super::types::RunOriginFailure>,
},
}
fn default_cost_known() -> bool {
true
}
fn default_worker_outcome() -> String {
"complete".to_string()
}
mod methods;