Skip to main content

tandem_server/routines/
types.rs

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}