kaish_client/traits.rs
1//! Common trait for kernel clients.
2
3use std::collections::HashMap;
4
5use async_trait::async_trait;
6use thiserror::Error;
7
8use kaish_kernel::ast::Value;
9use kaish_kernel::interpreter::ExecResult;
10use kaish_kernel::tools::ToolSchema;
11
12/// Result type for client operations.
13pub type ClientResult<T> = Result<T, ClientError>;
14
15/// Errors that can occur when using a kernel client.
16#[derive(Debug, Error)]
17pub enum ClientError {
18 /// Connection to the kernel failed.
19 #[error("connection error: {0}")]
20 Connection(String),
21
22 /// The kernel returned an error during execution.
23 #[error("execution error: {0}")]
24 Execution(String),
25
26 /// I/O error.
27 #[error("io error: {0}")]
28 Io(#[from] std::io::Error),
29
30 /// UTF-8 decoding error.
31 #[error("utf8 error: {0}")]
32 Utf8(#[from] std::str::Utf8Error),
33
34 /// The kernel is not connected.
35 #[error("not connected")]
36 NotConnected,
37
38 /// Other errors.
39 #[error("{0}")]
40 Other(#[from] anyhow::Error),
41}
42
43/// Common interface for interacting with a kaish kernel.
44///
45/// Both `EmbeddedClient` and custom client implementations can implement this trait,
46/// allowing code to work with any client type.
47#[async_trait(?Send)]
48pub trait KernelClient {
49 /// Execute kaish source code.
50 ///
51 /// Returns the result of the last statement executed.
52 async fn execute(&self, input: &str) -> ClientResult<ExecResult>;
53
54 /// Execute kaish source code with a transient overlay of exported variables.
55 ///
56 /// The overlay vars are visible (and exported to subprocesses) for the
57 /// duration of this call only, then removed. Names already exported in
58 /// the persistent state retain their outer value on return.
59 async fn execute_with_vars(
60 &self,
61 input: &str,
62 vars: HashMap<String, Value>,
63 ) -> ClientResult<ExecResult>;
64
65 /// Get a variable value.
66 async fn get_var(&self, name: &str) -> ClientResult<Option<Value>>;
67
68 /// Set a variable value.
69 async fn set_var(&self, name: &str, value: Value) -> ClientResult<()>;
70
71 /// List all variables.
72 async fn list_vars(&self) -> ClientResult<Vec<(String, Value)>>;
73
74 /// List the schemas of all available tools (builtins + registered tools).
75 ///
76 /// Each [`ToolSchema`] carries the tool's name, description, parameters
77 /// (flags and positionals, with types/aliases/defaults), and examples.
78 /// This is the introspection surface embedders use to build command and
79 /// option completion, generate help, or validate arguments client-side.
80 async fn tool_schemas(&self) -> ClientResult<Vec<ToolSchema>>;
81
82 /// Report whether a user-defined function with the given name exists.
83 ///
84 /// Lets a frontend probe for optional hooks (e.g. a `kaish_prompt`
85 /// function that customizes the prompt) before invoking them.
86 async fn has_function(&self, name: &str) -> ClientResult<bool>;
87
88 /// Cancel the kernel's in-flight execution.
89 ///
90 /// Signals the kernel's cancellation token, which cascades to any
91 /// attached forks and external child processes. Used by interactive
92 /// frontends to wire Ctrl-C to the running statement. Idempotent and
93 /// safe to call when nothing is executing.
94 async fn cancel(&self) -> ClientResult<()>;
95
96 /// Get the current working directory.
97 async fn cwd(&self) -> ClientResult<String>;
98
99 /// Set the current working directory.
100 async fn set_cwd(&self, path: &str) -> ClientResult<()>;
101
102 /// Get the last execution result ($?).
103 async fn last_result(&self) -> ClientResult<ExecResult>;
104
105 /// Reset the kernel to initial state.
106 async fn reset(&self) -> ClientResult<()>;
107
108 /// Ping the kernel (health check).
109 async fn ping(&self) -> ClientResult<String>;
110
111 /// Shutdown the kernel.
112 async fn shutdown(&self) -> ClientResult<()>;
113
114 /// Read a blob by ID.
115 ///
116 /// Returns the blob contents as raw bytes.
117 async fn read_blob(&self, id: &str) -> ClientResult<Vec<u8>>;
118
119 /// Write a blob and return its ID.
120 ///
121 /// The blob is stored in `/v/blobs/{id}` and can be referenced via BlobRef.
122 async fn write_blob(&self, content_type: &str, data: &[u8]) -> ClientResult<String>;
123
124 /// Delete a blob by ID.
125 ///
126 /// Returns true if the blob was deleted, false if it didn't exist.
127 async fn delete_blob(&self, id: &str) -> ClientResult<bool>;
128}