Skip to main content

deepseek_protocol/
lib.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Envelope<T> {
8    pub request_id: String,
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub thread_id: Option<String>,
11    pub body: T,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
15#[serde(rename_all = "snake_case")]
16pub enum ThreadStatus {
17    Running,
18    Idle,
19    Completed,
20    Failed,
21    Paused,
22    Archived,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
26#[serde(rename_all = "snake_case")]
27pub enum SessionSource {
28    Interactive,
29    Resume,
30    Fork,
31    Api,
32    Unknown,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct Thread {
37    pub id: String,
38    pub preview: String,
39    pub ephemeral: bool,
40    pub model_provider: String,
41    pub created_at: i64,
42    pub updated_at: i64,
43    pub status: ThreadStatus,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub path: Option<PathBuf>,
46    pub cwd: PathBuf,
47    pub cli_version: String,
48    pub source: SessionSource,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub name: Option<String>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct ThreadStartParams {
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub model: Option<String>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub model_provider: Option<String>,
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub cwd: Option<PathBuf>,
61    #[serde(default)]
62    pub persist_extended_history: bool,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct ThreadResumeParams {
67    pub thread_id: String,
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub history: Option<Vec<Value>>,
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub path: Option<PathBuf>,
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub model: Option<String>,
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub model_provider: Option<String>,
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub cwd: Option<PathBuf>,
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub approval_policy: Option<String>,
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub sandbox: Option<String>,
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub config: Option<Value>,
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub base_instructions: Option<String>,
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub developer_instructions: Option<String>,
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub personality: Option<String>,
90    #[serde(default)]
91    pub persist_extended_history: bool,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct ThreadForkParams {
96    pub thread_id: String,
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub path: Option<PathBuf>,
99    #[serde(skip_serializing_if = "Option::is_none")]
100    pub model: Option<String>,
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub model_provider: Option<String>,
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub cwd: Option<PathBuf>,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub approval_policy: Option<String>,
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub sandbox: Option<String>,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub config: Option<Value>,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub base_instructions: Option<String>,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub developer_instructions: Option<String>,
115    #[serde(default)]
116    pub persist_extended_history: bool,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct ThreadListParams {
121    #[serde(default)]
122    pub include_archived: bool,
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub limit: Option<usize>,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct ThreadReadParams {
129    pub thread_id: String,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct ThreadSetNameParams {
134    pub thread_id: String,
135    pub name: String,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139#[serde(tag = "kind", rename_all = "snake_case")]
140pub enum ThreadRequest {
141    Create {
142        #[serde(default)]
143        metadata: Value,
144    },
145    Start(ThreadStartParams),
146    Resume(ThreadResumeParams),
147    Fork(ThreadForkParams),
148    List(ThreadListParams),
149    Read(ThreadReadParams),
150    SetName(ThreadSetNameParams),
151    Archive {
152        thread_id: String,
153    },
154    Unarchive {
155        thread_id: String,
156    },
157    Message {
158        thread_id: String,
159        input: String,
160    },
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct ThreadResponse {
165    pub thread_id: String,
166    pub status: String,
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub thread: Option<Thread>,
169    #[serde(default)]
170    pub threads: Vec<Thread>,
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub model: Option<String>,
173    #[serde(skip_serializing_if = "Option::is_none")]
174    pub model_provider: Option<String>,
175    #[serde(skip_serializing_if = "Option::is_none")]
176    pub cwd: Option<PathBuf>,
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub approval_policy: Option<String>,
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub sandbox: Option<String>,
181    #[serde(default)]
182    pub events: Vec<EventFrame>,
183    #[serde(default)]
184    pub data: Value,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
188#[serde(tag = "kind", rename_all = "snake_case")]
189pub enum AppRequest {
190    Capabilities,
191    ConfigGet { key: String },
192    ConfigSet { key: String, value: String },
193    ConfigUnset { key: String },
194    ConfigList,
195    Models,
196    ThreadLoadedList,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct AppResponse {
201    pub ok: bool,
202    pub data: Value,
203    #[serde(default)]
204    pub events: Vec<EventFrame>,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct PromptRequest {
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub thread_id: Option<String>,
211    pub prompt: String,
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub model: Option<String>,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct PromptResponse {
218    pub output: String,
219    pub model: String,
220    #[serde(default)]
221    pub events: Vec<EventFrame>,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
225#[serde(rename_all = "snake_case")]
226pub enum AskForApproval {
227    UnlessTrusted,
228    OnFailure,
229    OnRequest,
230    Reject {
231        sandbox_approval: bool,
232        rules: bool,
233        mcp_elicitations: bool,
234    },
235    Never,
236}
237
238#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
239#[serde(rename_all = "snake_case")]
240pub enum ToolKind {
241    Function,
242    Mcp,
243}
244
245#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct LocalShellParams {
247    pub command: String,
248    #[serde(skip_serializing_if = "Option::is_none")]
249    pub cwd: Option<String>,
250    #[serde(skip_serializing_if = "Option::is_none")]
251    pub timeout_ms: Option<u64>,
252}
253
254#[derive(Debug, Clone, Serialize, Deserialize)]
255#[serde(tag = "type", rename_all = "snake_case")]
256pub enum ToolPayload {
257    Function {
258        arguments: String,
259    },
260    Custom {
261        input: String,
262    },
263    LocalShell {
264        params: LocalShellParams,
265    },
266    Mcp {
267        server: String,
268        tool: String,
269        raw_arguments: Value,
270        #[serde(skip_serializing_if = "Option::is_none")]
271        raw_tool_call_id: Option<String>,
272    },
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
276#[serde(tag = "type", rename_all = "snake_case")]
277pub enum ToolOutput {
278    Function {
279        #[serde(skip_serializing_if = "Option::is_none")]
280        body: Option<Value>,
281        success: bool,
282    },
283    Mcp {
284        result: Value,
285    },
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
289#[serde(rename_all = "snake_case")]
290pub enum NetworkPolicyRuleAction {
291    Allow,
292    Deny,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
296pub struct NetworkPolicyAmendment {
297    pub host: String,
298    pub action: NetworkPolicyRuleAction,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
302#[serde(tag = "type", rename_all = "snake_case")]
303pub enum ReviewDecision {
304    Approved,
305    ApprovedExecpolicyAmendment,
306    ApprovedForSession,
307    NetworkPolicyAmendment {
308        host: String,
309        action: NetworkPolicyRuleAction,
310    },
311    Denied,
312    Abort,
313}
314
315#[derive(Debug, Clone, Serialize, Deserialize)]
316#[serde(rename_all = "snake_case")]
317pub enum McpStartupStatus {
318    Starting,
319    Ready,
320    Failed { error: String },
321    Cancelled,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
325pub struct McpStartupUpdateEvent {
326    pub server_name: String,
327    pub status: McpStartupStatus,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct McpStartupFailure {
332    pub server_name: String,
333    pub error: String,
334}
335
336#[derive(Debug, Clone, Serialize, Deserialize)]
337pub struct McpStartupCompleteEvent {
338    pub ready: Vec<String>,
339    pub failed: Vec<McpStartupFailure>,
340    pub cancelled: Vec<String>,
341}
342
343#[derive(Debug, Clone, Serialize, Deserialize)]
344pub struct NetworkApprovalContext {
345    pub host: String,
346    pub protocol: String,
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct ExecApprovalRequestEvent {
351    pub call_id: String,
352    pub approval_id: String,
353    pub turn_id: String,
354    pub command: String,
355    pub cwd: String,
356    pub reason: String,
357    #[serde(skip_serializing_if = "Option::is_none")]
358    pub network_approval_context: Option<NetworkApprovalContext>,
359    #[serde(default)]
360    pub proposed_execpolicy_amendment: Vec<String>,
361    #[serde(default)]
362    pub proposed_network_policy_amendments: Vec<NetworkPolicyAmendment>,
363    #[serde(default)]
364    pub additional_permissions: Vec<String>,
365    #[serde(default)]
366    pub available_decisions: Vec<ReviewDecision>,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
370#[serde(tag = "event", rename_all = "snake_case")]
371pub enum EventFrame {
372    ResponseStart {
373        response_id: String,
374    },
375    ResponseDelta {
376        response_id: String,
377        delta: String,
378    },
379    ResponseEnd {
380        response_id: String,
381    },
382    ToolCallStart {
383        response_id: String,
384        tool_name: String,
385        arguments: Value,
386    },
387    ToolCallResult {
388        response_id: String,
389        tool_name: String,
390        output: Value,
391    },
392    McpStartupUpdate {
393        update: McpStartupUpdateEvent,
394    },
395    McpStartupComplete {
396        summary: McpStartupCompleteEvent,
397    },
398    McpToolCallBegin {
399        server_name: String,
400        tool_name: String,
401    },
402    McpToolCallEnd {
403        server_name: String,
404        tool_name: String,
405        ok: bool,
406    },
407    ExecApprovalRequest {
408        request: ExecApprovalRequestEvent,
409    },
410    ApplyPatchApprovalRequest {
411        request: ExecApprovalRequestEvent,
412    },
413    ElicitationRequest {
414        server_name: String,
415        request_id: String,
416        prompt: String,
417    },
418    ExecCommandBegin {
419        command: String,
420        cwd: String,
421    },
422    ExecCommandOutputDelta {
423        command: String,
424        delta: String,
425    },
426    ExecCommandEnd {
427        command: String,
428        exit_code: i32,
429    },
430    PatchApplyBegin {
431        path: String,
432    },
433    PatchApplyEnd {
434        path: String,
435        ok: bool,
436    },
437    TurnStarted {
438        turn_id: String,
439    },
440    TurnComplete {
441        turn_id: String,
442    },
443    TurnAborted {
444        turn_id: String,
445        reason: String,
446    },
447    Error {
448        response_id: String,
449        message: String,
450    },
451}