Skip to main content

Kernel

Struct Kernel 

Source
pub struct Kernel { /* private fields */ }
Expand description

The Kernel (核) — executes kaish code.

This is the primary interface for running kaish commands. It owns all the runtime state: variables, tools, VFS, jobs, and persistence.

Implementations§

Source§

impl Kernel

Source

pub fn new(config: KernelConfig) -> Result<Self>

Create a new kernel with the given configuration.

Source

pub fn transient() -> Result<Self>

Create a transient kernel (no persistence).

Source

pub fn with_backend( backend: Arc<dyn KernelBackend>, config: KernelConfig, configure_vfs: impl FnOnce(&mut VfsRouter), configure_tools: impl FnOnce(&mut ToolRegistry), ) -> Result<Self>

Create a kernel with a custom backend and /v/* virtual path support.

This is the constructor for embedding kaish in other systems that provide their own storage backend (e.g., CRDT-backed storage in kaijutsu).

A VirtualOverlayBackend routes paths automatically:

  • /v/* → Internal VFS (JobFs at /v/jobs, MemoryFs at /v/blobs)
  • Everything else → Your custom backend

The optional configure_vfs closure lets you add additional virtual mounts (e.g., /v/docs for CRDT blocks) after the built-in mounts are set up.

Note: The config’s vfs_mode is ignored — all non-/v/* path routing is handled by your custom backend. The config is only used for name, cwd, skip_validation, and interactive.

§Example
// Simple: default /v/* mounts only
let kernel = Kernel::with_backend(backend, config, |_| {}, |_| {})?;

// With custom mounts
let kernel = Kernel::with_backend(backend, config, |vfs| {
    vfs.mount_arc("/v/docs", docs_fs);
    vfs.mount_arc("/v/g", git_fs);
}, |_| {})?;

// With custom tools
let kernel = Kernel::with_backend(backend, config, |_| {}, |tools| {
    tools.register(MyCustomTool::new());
})?;
Source

pub fn name(&self) -> &str

Get the kernel name.

Source

pub fn into_arc(self) -> Arc<Self>

Wrap this Kernel in an Arc and initialize its self-reference.

This enables the Kernel to hand out Arc<dyn CommandDispatcher> references to child contexts, allowing builtins like timeout to dispatch inner commands through the full resolution chain (user tools → builtins → .kai scripts → external commands).

Source

pub async fn fork(&self) -> Arc<Self>

Fork a subsidiary kernel for concurrent execution.

The fork is a fully-functional Kernel that:

  • Snapshots per-session state from the parent: scope (COW — cheap), user-defined tools, cwd, aliases, ignore config, etc. Mutations on the fork do NOT propagate back to the parent — matching bash subshell / background-job semantics.
  • Shares read-mostly resources with the parent via Arc: the tool registry, the VFS router, and the job manager. A job registered by the fork is visible to the parent’s jobs builtin, and the fork sees the same VFS mounts.
  • Owns its own stderr_receiver, cancel_token, and execute_lock. It is never the TTY owner, so interactive is false and terminal_state is None.

The returned Arc has its self_weak populated (via into_arc), so nested dispatch through ctx.dispatcher (e.g. the timeout builtin) routes through the fork itself, not the parent — which is essential for concurrency safety.

Use this for detached background concurrency where the fork should survive parent cancellation: the & background-job operator and any other “fire and forget” worker. The fork gets a fresh, independent cancellation token.

For foreground concurrency (scatter workers, concurrent pipeline stages, $(...) cmdsubs) where parent timeout/cancel must cascade into the fork’s external children, use Self::fork_attached.

Source

pub async fn fork_attached(&self) -> Arc<Self>

Fork attached to the parent’s cancellation.

Same as Self::fork but the fork’s cancel_token is a child of the parent’s. When the parent cancels (request timeout, embedder Kernel::cancel, etc.), the fork’s token also cancels, which in turn kills any external children spawned in the fork via the wait_or_kill / SIGTERM-grace-SIGKILL path.

Source

pub fn dispatcher(&self) -> Option<Arc<dyn CommandDispatcher>>

Get an Arc<dyn CommandDispatcher> to this Kernel, if wrapped via into_arc().

Returns None if the Kernel was not wrapped, or if all strong references have been dropped (the Weak can no longer upgrade).

Source

pub fn cancel(&self)

Cancel the current execution.

This cancels the current cancellation token, causing any execution loop to exit at the next checkpoint with exit code 130 (SIGINT). A fresh token is installed for the next execute() call.

Source

pub fn is_cancelled(&self) -> bool

Check if the current execution has been cancelled.

Source

pub async fn execute(&self, input: &str) -> Result<ExecResult>

Execute kaish source code with default options.

Equivalent to execute_with_options(input, ExecuteOptions::default()). Returns the result of the last statement executed.

Source

pub async fn execute_with_options( &self, input: &str, opts: ExecuteOptions, ) -> Result<ExecResult>

Execute with per-call options. The primary entry point for embedders that don’t need per-statement output streaming.

opts carries timeout, transient vars overlay, optional cwd override, and optional embedder-owned cancellation token. See ExecuteOptions for semantics. For streaming, use Self::execute_with_options_streaming.

Cancellation: if opts.cancel_token is Some, it is raced against the kernel’s internal token. Either firing cancels and kills external children. The embedder’s token is read-only — kernel timeouts do NOT propagate into it. Distinguish via the returned code: 124 = timeout, 130 = cancellation.

Timeout: opts.timeout overrides KernelConfig::request_timeout. Some(Duration::ZERO) returns 124 immediately without spawning.

Concurrent callers on the same Kernel serialize on the kernel-wide execute lock. For true parallelism, call Kernel::fork (detached) or Kernel::fork_attached (cancellation cascades from this kernel).

Source

pub async fn execute_with_options_streaming( &self, input: &str, opts: ExecuteOptions, on_output: &mut (dyn FnMut(&ExecResult) + Send), ) -> Result<ExecResult>

Same as Self::execute_with_options but with a per-statement output callback. The callback fires after each top-level statement so the embedder (REPL, MCP streaming) can flush output incrementally.

Source

pub async fn execute_with_vars( &self, input: &str, vars: HashMap<String, Value>, ) -> Result<ExecResult>

👎Deprecated:

use Kernel::execute_with_options with ExecuteOptions::with_vars

Execute kaish source code with a transient overlay of exported variables.

Deprecated thin wrapper over Self::execute_with_options. New code should use that method directly: execute_with_options(input, ExecuteOptions::new().with_vars(vars)).

Source

pub async fn execute_streaming( &self, input: &str, on_output: &mut (dyn FnMut(&ExecResult) + Send), ) -> Result<ExecResult>

👎Deprecated:

use Kernel::execute_with_options_streaming

Execute kaish source code with a per-statement callback.

Deprecated thin wrapper. New code should use Self::execute_with_options_streaming.

Source

pub async fn get_var(&self, name: &str) -> Option<Value>

Get a variable value.

Source

pub async fn set_var(&self, name: &str, value: Value)

Set a variable value.

Source

pub async fn set_positional( &self, script_name: impl Into<String>, args: Vec<String>, )

Set positional parameters ($0 script name and $1-$9 args).

Source

pub async fn list_vars(&self) -> Vec<(String, Value)>

List all variables.

Source

pub async fn exported_vars(&self) -> Vec<(String, Value)>

List exported variables (name, value), sorted by name. These are the vars a child process would see (see dispatch’s hermetic env build).

Source

pub async fn cwd(&self) -> PathBuf

Get current working directory.

Source

pub async fn set_cwd(&self, path: PathBuf)

Set current working directory.

Source

pub async fn try_set_cwd(&self, path: PathBuf) -> bool

Set the working directory only if path resolves to a directory in the kernel’s backend — the same namespace cd validates against. Unlike a raw host-FS is_dir() check, this correctly accepts virtual mounts (/v/docs, in-memory scratch, …) and rejects real paths that have since disappeared. Returns whether the cwd was changed.

Source

pub async fn last_result(&self) -> ExecResult

Get the last result ($?).

Source

pub async fn has_function(&self, name: &str) -> bool

Check if a user-defined function exists.

Source

pub fn tool_schemas(&self) -> Vec<ToolSchema>

Get available tool schemas.

Source

pub fn jobs(&self) -> Arc<JobManager>

Get job manager.

Source

pub fn vfs(&self) -> Arc<VfsRouter>

Get VFS router.

Source

pub async fn reset(&self) -> Result<()>

Reset kernel to initial state.

Clears in-memory variables and resets cwd to root. History is not cleared (it persists across resets).

Source

pub async fn shutdown(self) -> Result<()>

Shutdown the kernel.

Trait Implementations§

Source§

impl CommandDispatcher for Kernel

Source§

fn dispatch<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, cmd: &'life1 Command, ctx: &'life2 mut ExecContext, ) -> Pin<Box<dyn Future<Output = Result<ExecResult>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Dispatch a command through the Kernel’s full resolution chain.

This is the single path for all command execution when called from the pipeline runner. It provides the full dispatch chain: user tools → builtins → .kai scripts → external commands → backend tools.

Source§

fn eval_expr<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, expr: &'life1 Expr, _ctx: &'life2 ExecContext, ) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Evaluate an expression through the kernel’s async chain, including command substitution. Delegates to eval_expr_async, which snapshots the kernel’s scope/cwd and restores them after any $(...) runs, so only command output escapes. The ctx is unused here because the kernel evaluates against its own session state (a fork carries the pipeline stage’s snapshot); var refs resolve against that scope.

Source§

fn fork<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Arc<dyn CommandDispatcher>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Produce a forked dispatcher with independent mutable state (detached).

Calls the inherent Kernel::fork method (note the UFCS to avoid recursing into the trait method we’re defining) and coerces the returned Arc<Kernel> to Arc<dyn CommandDispatcher>.

Source§

fn fork_attached<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Arc<dyn CommandDispatcher>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Produce a forked dispatcher with cancellation cascading from this kernel.

Auto Trait Implementations§

§

impl !Freeze for Kernel

§

impl !RefUnwindSafe for Kernel

§

impl !UnwindSafe for Kernel

§

impl Send for Kernel

§

impl Sync for Kernel

§

impl Unpin for Kernel

§

impl UnsafeUnpin for Kernel

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<'src, T> IntoMaybe<'src, T> for T
where T: 'src,

Source§

type Proj<U: 'src> = U

Source§

fn map_maybe<R>( self, _f: impl FnOnce(&'src T) -> &'src R, g: impl FnOnce(T) -> R, ) -> <T as IntoMaybe<'src, T>>::Proj<R>
where R: 'src,

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more