From d36a51358efbc48de3d5b732727455efc60acae1 Mon Sep 17 00:00:00 2001 From: t Date: Sun, 7 Jun 2026 10:57:49 -0600 Subject: R1: move tool registry off Config onto Agent The tool set is no longer part of the per-turn Config snapshot. Agent now owns a ToolRegistry (created empty at init), populated via the new Agent.registerTool / registerToolSource methods. openStream and OpenStreamFn take the registry as an explicit parameter rather than reading it from cfg.registry, so swapping provider/model between turns (setConfig) no longer disturbs the tool set. CLI migrated to register the Lua tool source onto the agent instead of a locally-owned registry. Test harnesses updated to stage tools on the agent. --- libpanto/src/config.zig | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) (limited to 'libpanto/src/config.zig') diff --git a/libpanto/src/config.zig b/libpanto/src/config.zig index eca81ff..8efa810 100644 --- a/libpanto/src/config.zig +++ b/libpanto/src/config.zig @@ -5,20 +5,20 @@ //! new tag and a new payload struct here; nothing else in libpanto needs a //! central enum refresh. //! -//! `Config` bundles the active `ProviderConfig` together with the -//! `ToolRegistry` the agent should expose this turn. It is an **immutable -//! snapshot**: the agent holds a `*const Config` and re-reads it at the top -//! of every turn, so swapping that pointer (e.g. from a `panto.configure` -//! hook) changes provider, model, base_url, and/or the visible tool set -//! atomically at the next turn boundary. Because the snapshot is read-only -//! while a turn is in flight, concurrent tool workers reading the old -//! snapshot stay consistent. +//! `Config` carries the active `ProviderConfig` (plus retry/compaction +//! policy). It is an **immutable snapshot**: the agent holds a `*const +//! Config` and re-reads it at the top of every turn, so swapping that +//! pointer (e.g. from a `panto.configure` hook) changes provider, model, +//! and base_url atomically at the next turn boundary. Because the snapshot +//! is read-only while a turn is in flight, concurrent tool workers reading +//! the old snapshot stay consistent. +//! +//! The tool set is **not** part of `Config` — it lives on the `Agent` +//! (`Agent.registerTool`/`registerToolSource`), so swapping provider/model +//! between turns no longer means rebuilding the tool list. const std = @import("std"); const Io = std.Io; -const tool_registry_mod = @import("tool_registry.zig"); - -pub const ToolRegistry = tool_registry_mod.ToolRegistry; /// The wire dialect a provider speaks. pub const APIStyle = enum { @@ -106,17 +106,13 @@ pub const RetryConfig = struct { jitter: bool = true, }; -/// An immutable snapshot of everything the agent consults per turn: which -/// provider/model to talk to, and which tools to expose. The agent holds a -/// `*const Config` and re-reads it each turn; replacing the pointer swaps -/// the active configuration wholesale at the next turn boundary. -/// -/// `registry` is borrowed, not owned — its lifetime is managed by whoever -/// built the snapshot (typically the embedder). A `Config` may be copied -/// freely; copies share the same borrowed registry. +/// An immutable snapshot of the provider/model the agent talks to, plus +/// retry and compaction policy. The agent holds a `*const Config` and +/// re-reads it each turn; replacing the pointer swaps the active +/// configuration at the next turn boundary. The tool set is owned by the +/// `Agent`, not the snapshot, so a swap never touches tools. pub const Config = struct { provider: ProviderConfig, - registry: *const ToolRegistry, compaction: CompactionConfig = .{}, retry: RetryConfig = .{}, @@ -196,12 +192,9 @@ test "ProviderConfig - openai_chat reasoning defaults to .default" { try t.expectEqual(ReasoningEffort.default, cfg.openai_chat.reasoning); } -test "Config bundles provider + registry and forwards style" { - var reg = ToolRegistry.init(t.allocator); - defer reg.deinit(); +test "Config carries provider and forwards style" { const cfg: Config = .{ .provider = .{ .openai_chat = .{ .api_key = "k", .base_url = "u", .model = "m" } }, - .registry = ®, }; try t.expectEqual(APIStyle.openai_chat, cfg.style()); } -- cgit v1.3