1use serde::{Deserialize, Serialize};
4
5pub const VERSION: u32 = 1;
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10#[serde(default)]
11pub struct InvokeRequest {
12 #[serde(rename = "version", default)]
13 pub version: u32,
14 #[serde(rename = "request_id", default)]
15 pub request_id: String,
16 #[serde(rename = "trace_id", default)]
17 pub trace_id: String,
18 #[serde(rename = "session_id", default)]
19 pub session_id: String,
20 #[serde(rename = "llm_session_id", default)]
21 pub llm_session_id: String,
22 #[serde(rename = "method", default)]
23 pub method: String,
24 #[serde(rename = "skill_id", default)]
25 pub skill_id: String,
26 #[serde(rename = "caller_id", default, skip_serializing_if = "String::is_empty")]
28 pub caller_id: String,
29 #[serde(rename = "state", default, with = "crate::bytes_or_null")]
30 pub state: Vec<u8>,
31 #[serde(rename = "payload", default, with = "crate::bytes_or_null")]
32 pub payload: Vec<u8>,
33 #[serde(rename = "deadline_ns", default)]
34 pub deadline_ns: i64,
35}
36
37#[derive(Debug, Clone, Default, Serialize, Deserialize)]
39#[serde(default)]
40pub struct InvokeResponse {
41 #[serde(rename = "version", default)]
42 pub version: u32,
43 #[serde(rename = "state", default, with = "crate::bytes_or_null")]
44 pub state: Vec<u8>,
45 #[serde(rename = "payload", default, with = "crate::bytes_or_null")]
46 pub payload: Vec<u8>,
47 #[serde(rename = "error", default, skip_serializing_if = "String::is_empty")]
48 pub error: String,
49 #[serde(rename = "commands", default, skip_serializing_if = "Vec::is_empty", with = "crate::vec_or_null")]
50 pub commands: Vec<Command>,
51 #[serde(rename = "llm_context", default, skip_serializing_if = "String::is_empty")]
53 pub llm_context: String,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize, Default)]
58#[serde(default)]
59pub struct Command {
60 #[serde(rename = "type")]
61 pub kind: CommandType,
62 #[serde(rename = "payload", default, skip_serializing_if = "Option::is_none")]
63 pub payload: Option<rmpv::Value>,
64}
65
66#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
68#[serde(rename_all = "snake_case")]
69pub enum CommandType {
70 #[default]
71 CallModule,
72 BatchInvoke,
73 Schedule,
74 EmitEvent,
75 Subscribe,
76 StoreKv,
77 LoadKv,
78 Spawn,
79 Terminate,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize, Default)]
84#[serde(default)]
85pub struct BatchItem {
86 #[serde(rename = "index")]
87 pub index: u32,
88 #[serde(rename = "skill_id")]
89 pub skill_id: String,
90 #[serde(rename = "method")]
91 pub method: String,
92 #[serde(rename = "payload", with = "crate::bytes_or_null")]
93 pub payload: Vec<u8>,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize, Default)]
98#[serde(default)]
99pub struct BatchItemResult {
100 #[serde(rename = "index")]
101 pub index: u32,
102 #[serde(rename = "payload", default, with = "crate::bytes_or_null", skip_serializing_if = "Vec::is_empty")]
103 pub payload: Vec<u8>,
104 #[serde(rename = "error", default, skip_serializing_if = "String::is_empty")]
105 pub error: String,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize, Default)]
110#[serde(default)]
111pub struct BatchResult {
112 #[serde(rename = "batch_id")]
113 pub batch_id: String,
114 #[serde(rename = "items", with = "crate::vec_or_null")]
115 pub items: Vec<BatchItemResult>,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, Default)]
120#[serde(default)]
121pub struct HistoryMessage {
122 #[serde(rename = "role")]
123 pub role: String,
124 #[serde(rename = "content")]
125 pub content: String,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize, Default)]
130#[serde(default)]
131pub struct PromptRequest {
132 #[serde(rename = "prompt")]
133 pub prompt: String,
134 #[serde(rename = "temperature")]
135 pub temperature: f64,
136 #[serde(rename = "max_tokens")]
137 pub max_tokens: u32,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize, Default)]
142#[serde(default)]
143pub struct PromptResponse {
144 #[serde(rename = "content")]
145 pub content: String,
146 #[serde(rename = "error", default, skip_serializing_if = "String::is_empty")]
147 pub error: String,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize, Default)]
152#[serde(default)]
153pub struct FsRequest {
154 #[serde(rename = "path")]
155 pub path: String,
156 #[serde(rename = "content", default, with = "crate::bytes_or_null", skip_serializing_if = "Vec::is_empty")]
157 pub content: Vec<u8>,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize, Default)]
162#[serde(default)]
163pub struct FsResponse {
164 #[serde(rename = "content", default, with = "crate::bytes_or_null", skip_serializing_if = "Vec::is_empty")]
165 pub content: Vec<u8>,
166 #[serde(rename = "error", default, skip_serializing_if = "String::is_empty")]
167 pub error: String,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize, Default)]
172#[serde(default)]
173pub struct FsMkdirRequest {
174 #[serde(rename = "path")]
175 pub path: String,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize, Default)]
180#[serde(default)]
181pub struct FsLsRequest {
182 #[serde(rename = "path")]
183 pub path: String,
184 #[serde(rename = "long")]
186 pub long: bool,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize, Default)]
191#[serde(default)]
192pub struct DirEntry {
193 #[serde(rename = "name")]
194 pub name: String,
195 #[serde(rename = "size")]
196 pub size: i64,
197 #[serde(rename = "is_dir")]
198 pub is_dir: bool,
199 #[serde(rename = "mod_time", default, skip_serializing_if = "is_zero_i64")]
200 pub mod_time: i64,
201 #[serde(rename = "mode", default, skip_serializing_if = "is_zero_u32")]
202 pub mode: u32,
203 #[serde(rename = "mode_str", default, skip_serializing_if = "String::is_empty")]
204 pub mode_str: String,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize, Default)]
209#[serde(default)]
210pub struct FsLsResponse {
211 #[serde(rename = "entries", with = "crate::vec_or_null")]
212 pub entries: Vec<DirEntry>,
213 #[serde(rename = "error", default, skip_serializing_if = "String::is_empty")]
214 pub error: String,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize, Default)]
219#[serde(default)]
220pub struct FsChmodRequest {
221 #[serde(rename = "path")]
222 pub path: String,
223 #[serde(rename = "mode")]
224 pub mode: u32,
225 #[serde(rename = "recursive")]
226 pub recursive: bool,
227}
228
229pub mod perm {
231 pub const OWNER_READ: u32 = 0o400;
232 pub const OWNER_WRITE: u32 = 0o200;
233 pub const OWNER_EXEC: u32 = 0o100;
234 pub const GROUP_READ: u32 = 0o040;
235 pub const GROUP_WRITE: u32 = 0o020;
236 pub const GROUP_EXEC: u32 = 0o010;
237 pub const OTHER_READ: u32 = 0o004;
238 pub const OTHER_WRITE: u32 = 0o002;
239 pub const OTHER_EXEC: u32 = 0o001;
240
241 pub const READ_ONLY: u32 = 0o444;
242 pub const DEFAULT: u32 = 0o644;
243 pub const DEFAULT_DIR: u32 = 0o755;
244 pub const PRIVATE: u32 = 0o600;
245 pub const PRIVATE_DIR: u32 = 0o700;
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize, Default)]
250#[serde(default)]
251pub struct FsReadLinesRequest {
252 #[serde(rename = "path")]
253 pub path: String,
254 #[serde(rename = "offset", default)]
255 pub offset: i64,
256 #[serde(rename = "limit", default)]
257 pub limit: i64,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize, Default)]
262#[serde(default)]
263pub struct TextFileContent {
264 #[serde(rename = "lines", with = "crate::vec_or_null")]
265 pub lines: Vec<String>,
266 #[serde(rename = "total_lines")]
267 pub total_lines: i64,
268 #[serde(rename = "offset")]
269 pub offset: i64,
270 #[serde(rename = "is_truncated")]
271 pub is_truncated: bool,
272}
273
274#[derive(Debug, Clone, Serialize, Deserialize, Default)]
275#[serde(default)]
276pub(crate) struct TextFileContentResponse {
277 #[serde(rename = "lines", with = "crate::vec_or_null")]
278 pub lines: Vec<String>,
279 #[serde(rename = "total_lines")]
280 pub total_lines: i64,
281 #[serde(rename = "offset")]
282 pub offset: i64,
283 #[serde(rename = "is_truncated")]
284 pub is_truncated: bool,
285 #[serde(rename = "error", default)]
286 pub error: String,
287}
288
289#[derive(Debug, Clone, Default, Serialize, Deserialize)]
291#[serde(default)]
292pub struct GrepOptions {
293 #[serde(rename = "pattern")]
294 pub pattern: String,
295 #[serde(rename = "path", default, skip_serializing_if = "String::is_empty")]
296 pub path: String,
297 #[serde(rename = "fixed", default, skip_serializing_if = "is_false")]
298 pub fixed: bool,
299 #[serde(rename = "case_insensitive", default, skip_serializing_if = "is_false")]
300 pub case_insensitive: bool,
301 #[serde(rename = "max_depth", default, skip_serializing_if = "is_zero_i64")]
302 pub max_depth: i64,
303 #[serde(rename = "max_count", default, skip_serializing_if = "is_zero_i64")]
304 pub max_count: i64,
305 #[serde(rename = "workers", default, skip_serializing_if = "is_zero_i64")]
306 pub workers: i64,
307 #[serde(rename = "type_filter", default, skip_serializing_if = "String::is_empty")]
308 pub type_filter: String,
309 #[serde(rename = "include", default, skip_serializing_if = "Vec::is_empty", with = "crate::vec_or_null")]
310 pub include: Vec<String>,
311 #[serde(rename = "exclude", default, skip_serializing_if = "Vec::is_empty", with = "crate::vec_or_null")]
312 pub exclude: Vec<String>,
313 #[serde(rename = "ignore_dirs", default, skip_serializing_if = "Option::is_none")]
314 pub ignore_dirs: Option<Vec<String>>,
315 #[serde(rename = "with_lines", default, skip_serializing_if = "is_false")]
316 pub with_lines: bool,
317 #[serde(rename = "filename_only", default, skip_serializing_if = "is_false")]
318 pub filename_only: bool,
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize, Default)]
323#[serde(default)]
324pub struct GrepFileMatch {
325 #[serde(rename = "path")]
326 pub path: String,
327 #[serde(rename = "matches", with = "crate::vec_or_null")]
328 pub matches: Vec<GrepLineMatch>,
329}
330
331#[derive(Debug, Clone, Serialize, Deserialize, Default)]
333#[serde(default)]
334pub struct GrepLineMatch {
335 #[serde(rename = "line_num")]
337 pub line_num: i64,
338 #[serde(rename = "line", default, skip_serializing_if = "String::is_empty")]
339 pub line: String,
340 #[serde(rename = "ranges", default, skip_serializing_if = "Vec::is_empty", with = "crate::vec_or_null")]
341 pub ranges: Vec<GrepRange>,
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize, Default)]
346#[serde(default)]
347pub struct GrepRange {
348 #[serde(rename = "start")]
349 pub start: i64,
350 #[serde(rename = "end")]
351 pub end: i64,
352}
353
354#[derive(Debug, Clone, Default, Serialize, Deserialize)]
356#[serde(default)]
357pub struct GlobOptions {
358 #[serde(rename = "patterns", with = "crate::vec_or_null")]
359 pub patterns: Vec<String>,
360 #[serde(rename = "path", default, skip_serializing_if = "String::is_empty")]
361 pub path: String,
362 #[serde(rename = "match_hidden", default, skip_serializing_if = "is_false")]
363 pub match_hidden: bool,
364 #[serde(rename = "ignore_dirs", default, skip_serializing_if = "Option::is_none")]
365 pub ignore_dirs: Option<Vec<String>>,
366 #[serde(rename = "max_depth", default, skip_serializing_if = "is_zero_i64")]
367 pub max_depth: i64,
368 #[serde(rename = "only_files", default, skip_serializing_if = "is_false")]
369 pub only_files: bool,
370 #[serde(rename = "only_dirs", default, skip_serializing_if = "is_false")]
371 pub only_dirs: bool,
372}
373
374#[derive(Debug, Clone, Serialize, Deserialize, Default)]
376#[serde(default)]
377pub struct GlobEntry {
378 #[serde(rename = "path")]
379 pub path: String,
380 #[serde(rename = "is_dir")]
381 pub is_dir: bool,
382}
383
384#[derive(Debug, Clone, Serialize, Deserialize, Default)]
386pub struct TcpRequestOptions {
387 #[serde(rename = "addr")]
388 pub addr: String,
389 #[serde(rename = "data", default, with = "crate::bytes_or_null")]
390 pub data: Vec<u8>,
391 #[serde(rename = "tls", default)]
392 pub tls: bool,
393 #[serde(rename = "insecure", default)]
394 pub insecure: bool,
395 #[serde(rename = "timeout_ms", default)]
396 pub timeout_ms: i64,
397 #[serde(rename = "max_bytes", default)]
398 pub max_bytes: i64,
399}
400
401#[derive(Debug, Clone, Serialize, Deserialize, Default)]
403#[serde(default)]
404pub struct TcpRequestResult {
405 #[serde(rename = "data", default, with = "crate::bytes_or_null")]
406 pub data: Vec<u8>,
407 #[serde(rename = "error", default)]
408 pub error: String,
409}
410
411#[derive(Debug, Clone, Serialize, Deserialize, Default)]
413pub struct ShellExecRequest {
414 #[serde(rename = "command")]
416 pub command: String,
417 #[serde(rename = "workdir", default)]
419 pub workdir: String,
420 #[serde(rename = "timeout_ms", default)]
422 pub timeout_ms: i64,
423 #[serde(rename = "tail", default)]
425 pub tail: i64,
426 #[serde(rename = "grep", default)]
428 pub grep: String,
429 #[serde(rename = "as_daemon", default, skip_serializing_if = "is_false")]
431 pub as_daemon: bool,
432 #[serde(rename = "log_file", default, skip_serializing_if = "String::is_empty")]
434 pub log_file: String,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize, Default)]
439pub struct ShellExecResult {
440 #[serde(rename = "output", default)]
442 pub output: String,
443 #[serde(rename = "exit_code", default)]
445 pub exit_code: i64,
446 #[serde(rename = "pid", default)]
448 pub pid: i64,
449 #[serde(rename = "log_file", default, skip_serializing_if = "String::is_empty")]
451 pub log_file: String,
452 #[serde(rename = "error", default)]
453 pub error: String,
454}
455
456#[derive(Debug, Clone, Serialize, Deserialize, Default)]
458#[serde(default)]
459pub struct SysInfoResult {
460 pub os: String,
461 pub arch: String,
462 pub hostname: String,
463 pub num_cpu: i64,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize, Default)]
468#[serde(default)]
469pub struct TimeNowResult {
470 pub unix: i64,
471 pub unix_nano: i64,
472 pub rfc3339: String,
473 pub timezone: String,
474 pub utc_offset: i64,
475}
476
477#[derive(Debug, Clone, Serialize, Deserialize, Default)]
479#[serde(default)]
480pub struct DiskUsageResult {
481 pub total_bytes: i64,
482 pub free_bytes: i64,
483 pub used_bytes: i64,
484 pub used_pct: f64,
485 #[serde(default)]
486 pub error: String,
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize, Default)]
491#[serde(default)]
492pub struct AllowedDir {
493 pub path: String,
494 pub mode: String,
495}
496
497#[derive(Debug, Clone)]
499pub struct SkillError(pub String);
500
501impl std::fmt::Display for SkillError {
502 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
503 write!(f, "abi error: {}", self.0)
504 }
505}
506
507impl std::error::Error for SkillError {}
508
509impl From<rmp_serde::encode::Error> for SkillError {
510 fn from(e: rmp_serde::encode::Error) -> Self {
511 SkillError(format!("msgpack encode: {e}"))
512 }
513}
514
515impl From<rmp_serde::decode::Error> for SkillError {
516 fn from(e: rmp_serde::decode::Error) -> Self {
517 SkillError(format!("msgpack decode: {e}"))
518 }
519}
520
521#[inline]
522fn is_false(v: &bool) -> bool { !v }
523
524#[inline]
525fn is_zero_i64(v: &i64) -> bool { *v == 0 }
526
527#[inline]
528fn is_zero_u32(v: &u32) -> bool { *v == 0 }