1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5#[serde(rename_all = "snake_case")]
6pub enum RoutineSchedule {
7 IntervalSeconds { seconds: u64 },
8 Cron { expression: String },
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12#[serde(rename_all = "snake_case", tag = "type")]
13pub enum RoutineMisfirePolicy {
14 Skip,
15 RunOnce,
16 CatchUp { max_runs: u32 },
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
20#[serde(rename_all = "snake_case")]
21pub enum RoutineStatus {
22 Active,
23 Paused,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct RoutineSpec {
28 pub routine_id: String,
29 pub name: String,
30 pub status: RoutineStatus,
31 pub schedule: RoutineSchedule,
32 pub timezone: String,
33 pub misfire_policy: RoutineMisfirePolicy,
34 pub entrypoint: String,
35 #[serde(default)]
36 pub args: Value,
37 #[serde(default)]
38 pub allowed_tools: Vec<String>,
39 #[serde(default)]
40 pub output_targets: Vec<String>,
41 pub creator_type: String,
42 pub creator_id: String,
43 pub requires_approval: bool,
44 pub external_integrations_allowed: bool,
45 #[serde(default, skip_serializing_if = "Option::is_none")]
46 pub next_fire_at_ms: Option<u64>,
47 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub last_fired_at_ms: Option<u64>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct RoutineHistoryEvent {
53 pub routine_id: String,
54 pub trigger_type: String,
55 pub run_count: u32,
56 pub fired_at_ms: u64,
57 pub status: String,
58 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub detail: Option<String>,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
63#[serde(rename_all = "snake_case")]
64pub enum RoutineRunStatus {
65 Queued,
66 PendingApproval,
67 Running,
68 Paused,
69 BlockedPolicy,
70 Denied,
71 Completed,
72 Failed,
73 Cancelled,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct RoutineRunArtifact {
78 pub artifact_id: String,
79 pub uri: String,
80 pub kind: String,
81 #[serde(default, skip_serializing_if = "Option::is_none")]
82 pub label: Option<String>,
83 pub created_at_ms: u64,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub metadata: Option<Value>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize, Default)]
89pub struct ExternalActionRecord {
90 pub action_id: String,
91 pub operation: String,
92 pub status: String,
93 #[serde(default, skip_serializing_if = "Option::is_none")]
94 pub source_kind: Option<String>,
95 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub source_id: Option<String>,
97 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub routine_run_id: Option<String>,
99 #[serde(default, skip_serializing_if = "Option::is_none")]
100 pub context_run_id: Option<String>,
101 #[serde(default, skip_serializing_if = "Option::is_none")]
102 pub capability_id: Option<String>,
103 #[serde(default, skip_serializing_if = "Option::is_none")]
104 pub provider: Option<String>,
105 #[serde(default, skip_serializing_if = "Option::is_none")]
106 pub target: Option<String>,
107 #[serde(default, skip_serializing_if = "Option::is_none")]
108 pub approval_state: Option<String>,
109 #[serde(default, skip_serializing_if = "Option::is_none")]
110 pub idempotency_key: Option<String>,
111 #[serde(default, skip_serializing_if = "Option::is_none")]
112 pub receipt: Option<Value>,
113 #[serde(default, skip_serializing_if = "Option::is_none")]
114 pub error: Option<String>,
115 #[serde(default, skip_serializing_if = "Option::is_none")]
116 pub metadata: Option<Value>,
117 pub created_at_ms: u64,
118 pub updated_at_ms: u64,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct RoutineRunRecord {
123 pub run_id: String,
124 pub routine_id: String,
125 pub trigger_type: String,
126 pub run_count: u32,
127 pub status: RoutineRunStatus,
128 pub created_at_ms: u64,
129 pub updated_at_ms: u64,
130 #[serde(default, skip_serializing_if = "Option::is_none")]
131 pub fired_at_ms: Option<u64>,
132 #[serde(default, skip_serializing_if = "Option::is_none")]
133 pub started_at_ms: Option<u64>,
134 #[serde(default, skip_serializing_if = "Option::is_none")]
135 pub finished_at_ms: Option<u64>,
136 pub requires_approval: bool,
137 #[serde(default, skip_serializing_if = "Option::is_none")]
138 pub approval_reason: Option<String>,
139 #[serde(default, skip_serializing_if = "Option::is_none")]
140 pub denial_reason: Option<String>,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
142 pub paused_reason: Option<String>,
143 #[serde(default, skip_serializing_if = "Option::is_none")]
144 pub detail: Option<String>,
145 pub entrypoint: String,
146 #[serde(default)]
147 pub args: Value,
148 #[serde(default)]
149 pub allowed_tools: Vec<String>,
150 #[serde(default)]
151 pub output_targets: Vec<String>,
152 #[serde(default)]
153 pub artifacts: Vec<RoutineRunArtifact>,
154 #[serde(default)]
155 pub active_session_ids: Vec<String>,
156 #[serde(default, skip_serializing_if = "Option::is_none")]
157 pub latest_session_id: Option<String>,
158 #[serde(default)]
159 pub prompt_tokens: u64,
160 #[serde(default)]
161 pub completion_tokens: u64,
162 #[serde(default)]
163 pub total_tokens: u64,
164 #[serde(default)]
165 pub estimated_cost_usd: f64,
166}
167
168#[derive(Debug, Clone)]
169pub struct RoutineSessionPolicy {
170 pub session_id: String,
171 pub run_id: String,
172 pub routine_id: String,
173 pub allowed_tools: Vec<String>,
174}
175
176#[derive(Debug, Clone, Serialize)]
177pub struct RoutineTriggerPlan {
178 pub routine_id: String,
179 pub run_count: u32,
180 pub scheduled_at_ms: u64,
181 pub next_fire_at_ms: u64,
182}