Skip to main content

soma_codemode/
protocol.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::cell::RefCell;
4use std::io::{self, BufReader, BufWriter};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7#[serde(tag = "type", rename_all = "snake_case")]
8pub enum CodeModeRunnerInput {
9    Start {
10        code: String,
11        #[serde(default)]
12        proxy: String,
13    },
14    ToolResult {
15        seq: u64,
16        result: Value,
17    },
18    SnippetResolved {
19        seq: u64,
20        code: String,
21        input: Value,
22    },
23    ToolError {
24        seq: u64,
25        kind: String,
26        message: String,
27    },
28    StepDecision {
29        seq: u64,
30        #[serde(default)]
31        replay: Option<Value>,
32    },
33    StepRecorded {
34        seq: u64,
35    },
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39#[serde(tag = "type", rename_all = "snake_case")]
40pub enum CodeModeRunnerOutput {
41    ToolCall {
42        seq: u64,
43        id: String,
44        params: Value,
45    },
46    ArtifactWrite {
47        seq: u64,
48        path: String,
49        content: String,
50        #[serde(default)]
51        content_type: Option<String>,
52    },
53    SnippetResolve {
54        seq: u64,
55        name: String,
56        #[serde(default)]
57        input: Value,
58    },
59    StepBegin {
60        seq: u64,
61        name: String,
62    },
63    StepResult {
64        seq: u64,
65        value: Value,
66    },
67    Done {
68        #[serde(default)]
69        result: CodeModeRunnerResult,
70        #[serde(default)]
71        logs: Vec<String>,
72    },
73    Error {
74        kind: String,
75        message: String,
76    },
77}
78
79#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
80#[serde(tag = "state", content = "value", rename_all = "snake_case")]
81pub enum CodeModeRunnerResult {
82    #[default]
83    Undefined,
84    Json(Value),
85}
86
87impl CodeModeRunnerResult {
88    #[must_use]
89    pub fn from_response_result(result: Option<Value>) -> Self {
90        result.map_or(Self::Undefined, Self::Json)
91    }
92
93    #[must_use]
94    pub fn into_response_result(self) -> Option<Value> {
95        match self {
96            Self::Undefined => None,
97            Self::Json(value) => Some(value),
98        }
99    }
100}
101
102pub const CODE_MODE_STACK_SIZE_LIMIT: usize = 256 * 1024;
103
104pub(crate) struct CodeModeRunnerState {
105    pub reader: BufReader<io::Stdin>,
106    pub writer: BufWriter<io::Stdout>,
107    pub next_seq: u64,
108}
109
110thread_local! {
111    pub(crate) static RUNNER_STATE: RefCell<Option<CodeModeRunnerState>> =
112        const { RefCell::new(None) };
113}