diff options
Diffstat (limited to 'libpanto/src/tool_source.zig')
| -rw-r--r-- | libpanto/src/tool_source.zig | 104 |
1 files changed, 0 insertions, 104 deletions
diff --git a/libpanto/src/tool_source.zig b/libpanto/src/tool_source.zig deleted file mode 100644 index d5bc716..0000000 --- a/libpanto/src/tool_source.zig +++ /dev/null @@ -1,104 +0,0 @@ -//! Batch-dispatched tool extension API: `ToolSource`. -//! -//! Where `Tool` is a single, thread-safe handler (one tool, one vtable, -//! reentrant), `ToolSource` is a single owner of many tools whose runtime -//! prefers to receive calls in *batches* on a single thread. -//! -//! Motivation: Lua. A Lua extension runtime maintains one long-lived -//! `lua_State` so that module-globals, lazy connection pools, rate -//! limiters, etc. survive across calls. A single `lua_State` is not safe -//! for concurrent host entry, so the runtime can't satisfy `Tool`'s -//! thread-safety contract directly. The runtime *can* dispatch many calls -//! cooperatively (coroutines + an event loop), but it needs to be told -//! all of them at once. -//! -//! The contract libpanto provides: -//! -//! - For a given turn, every `ToolUse` block whose tool name belongs to -//! a particular source is delivered in a single `invoke_batch` call, -//! on one thread. -//! - Distinct sources still execute concurrently (one OS thread per -//! source per turn), so a Lua source and a native source can run in -//! parallel. -//! - Single `Tool` registrations are unchanged. They each get their own -//! thread when they appear alongside other tool calls in a turn. -//! -//! The "thread-safe" promise that `Tool.invoke` carries relaxes to -//! "coroutine-safe within the source's runtime" for source-backed tools — -//! enforcement is the source's problem. - -const std = @import("std"); -const Allocator = std.mem.Allocator; -const tool = @import("tool.zig"); - -/// Tool metadata: re-exported from `tool.zig`, which owns the more atomic -/// type. `ToolSource`s declare their tools this way because they share a -/// single dispatch path. -pub const ToolDecl = tool.ToolDecl; -pub const ResultPart = tool.ResultPart; -pub const ResultParts = tool.ResultParts; - -/// One pending invocation passed to `invoke_batch`. Slices borrowed from -/// the caller for the duration of the call. -pub const Call = struct { - /// Which of the source's declared tools this call targets. - tool_name: []const u8, - /// Raw JSON bytes the provider sent. Borrowed. - input: []const u8, -}; - -/// Result for a single call. Mirrors the success/error split of -/// `Tool.invoke`'s return shape. Owned by the caller-supplied allocator. -pub const CallResult = union(enum) { - /// Owned parts (the `ResultParts` slice + each part's bytes), freed by - /// libpanto after assembling the ToolResult block (see - /// `tool.ResultParts.deinit`). - ok: ResultParts, - err: anyerror, -}; - -/// A grouped tool runtime. -pub const ToolSource = struct { - /// Diagnostic name; surfaced in error messages and logs. Example - /// values: `"panto-lua"`, `"panto-python"`. Borrowed; lifetime owned - /// by the source. - name: []const u8, - /// Tool metadata for every tool this source owns. Borrowed. - tools: []const ToolDecl, - ctx: *anyopaque, - vtable: *const VTable, - - pub const VTable = struct { - /// libpanto guarantees: for a given turn, every ToolUse call - /// whose tool name belongs to this source is delivered in one - /// `invoke_batch`, on one thread. Different sources still - /// execute in parallel. - /// - /// `calls` and `results` are parallel arrays of length N. - /// `results` is pre-allocated by libpanto; the source fills each - /// slot. The source decides internal scheduling — sequential, - /// coroutine fan-out, worker pool, etc. - /// - /// Two failure modes, both normally model-visible: - /// - Per-call: record `.{ .err = e }` in a `results[i]` slot. - /// That call gets an error `ToolResult`; siblings are - /// unaffected. - /// - Whole-batch: return an error from this function. libpanto - /// frees any `ok` slots already filled and maps the error onto - /// *every* member call as an error `ToolResult`. - /// In both cases the agent loop continues so the model can react. - /// Only hard host failures (`error.Canceled`, `error.OutOfMemory`) - /// abort the whole turn and propagate to the embedder. - invoke_batch: *const fn ( - ctx: *anyopaque, - calls: []const Call, - results: []CallResult, - allocator: Allocator, - ) anyerror!void, - - /// Called when the source is removed from the registry or the - /// registry is torn down. Frees any resources owned by `ctx`, - /// including `ctx` itself if heap-allocated. - deinit: *const fn (ctx: *anyopaque, allocator: Allocator) void, - }; -}; |
