adk_computer_use/contracts/receipt.rs
1//! Capability, policy, preview, and execution-receipt contracts.
2
3use super::action::{ActionEnvelope, ExecutionMode};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7/// A verified execution capability advertised by the runtime.
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct ExecutionCapability {
11 /// Application/bundle identifier, or `*` for any.
12 pub app_id: String,
13 /// Operation the capability covers.
14 pub operation: String,
15 /// Backend that provides the capability.
16 pub backend: String,
17 /// Execution modes the capability supports.
18 pub supported_modes: Vec<ExecutionMode>,
19 /// Interference classification for the capability.
20 pub interference: String,
21 /// Confidence in `0.0..=1.0`.
22 pub confidence: f64,
23 /// RFC 3339 timestamp the capability was last verified, when known.
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub verified_at: Option<String>,
26 /// Source of the capability verification.
27 pub verification_source: String,
28}
29
30/// A policy decision for a previewed action.
31#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct PolicyDecision {
34 /// The decision (e.g. `allow`, `confirm`, `deny`).
35 pub decision: String,
36 /// Digest of the policy that produced the decision.
37 pub policy_digest: String,
38 /// Human-readable reasons contributing to the decision.
39 pub reasons: Vec<String>,
40 /// Approval grant identifier, when a grant was issued.
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub grant_id: Option<String>,
43}
44
45/// Result of `preview_action` used for deterministic graph routing.
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47#[serde(rename_all = "camelCase")]
48pub struct ActionPreview {
49 /// The runtime-bound action envelope.
50 pub envelope: ActionEnvelope,
51 /// Whether the action is currently executable.
52 pub executable: bool,
53 /// Reason the action is blocked, when not executable.
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub blocker: Option<String>,
56 /// The policy decision for the action.
57 pub policy: PolicyDecision,
58 /// The capability backing the action.
59 pub capability: ExecutionCapability,
60}
61
62/// Terminal status of an execution receipt.
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
64#[serde(rename_all = "snake_case")]
65pub enum ReceiptStatus {
66 /// The action committed successfully.
67 Committed,
68 /// The action was rejected before commit.
69 Rejected,
70 /// The action was interrupted.
71 Interrupted,
72 /// The commit outcome is indeterminate.
73 Indeterminate,
74}
75
76/// Idempotency receipt returned by `execute_action`.
77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub struct ExecutionReceipt {
80 /// Unique receipt identifier used for idempotent replay.
81 pub receipt_id: String,
82 /// The session the receipt belongs to.
83 pub session_id: String,
84 /// The action the receipt covers.
85 pub action_id: String,
86 /// Digest of the executed action arguments.
87 pub action_digest: String,
88 /// Execution attempt number.
89 pub attempt: u32,
90 /// Terminal status of the execution.
91 pub status: ReceiptStatus,
92 /// RFC 3339 creation timestamp, when known.
93 #[serde(skip_serializing_if = "Option::is_none")]
94 pub created_at: Option<String>,
95 /// RFC 3339 update timestamp, when known.
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub updated_at: Option<String>,
98 /// Structured result payload, when present.
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub result: Option<Value>,
101 /// Structured error payload, when present.
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub error: Option<Value>,
104}