diff --git a/src/agent/Agent.zig b/src/agent/Agent.zig index d9a50844..0a0ab330 100644 --- a/src/agent/Agent.zig +++ b/src/agent/Agent.zig @@ -143,9 +143,8 @@ notification: *lp.Notification, browser: lp.Browser, session: *lp.Session, node_registry: CDPNode.Registry, -tool_schema_arena: std.heap.ArenaAllocator, -/// Provider-facing tool list, built from `SlashCommand.globalSchemas()`. The -/// slice lives in `tool_schema_arena`; the JSON `Value` each entry points at +/// Provider-facing tool list, built from `SlashCommand.globalSchemas()`. Slice +/// is owned by `allocator`; the `parameters` JSON `Value` each entry points at /// lives in the schema module's process-lifetime arena. tools: []const zenai.provider.Tool, terminal: Terminal, @@ -244,7 +243,6 @@ pub fn init(allocator: std.mem.Allocator, app: *App, opts: Config.Agent) !*Agent .browser = undefined, .session = undefined, .node_registry = CDPNode.Registry.init(allocator), - .tool_schema_arena = .init(allocator), .tools = &.{}, .terminal = .init(allocator, history_path, Config.agentVerbosity(opts), will_repl), .cmd_runner = undefined, @@ -260,12 +258,12 @@ pub fn init(allocator: std.mem.Allocator, app: *App, opts: Config.Agent) !*Agent .one_shot_task = opts.task, .one_shot_attachments = if (opts.attach.items.len == 0) null else opts.attach.items, }; - errdefer self.tool_schema_arena.deinit(); errdefer self.node_registry.deinit(); errdefer self.terminal.deinit(); errdefer self.message_arena.deinit(); - self.tools = try buildTools(self.tool_schema_arena.allocator()); + self.tools = try buildTools(allocator); + errdefer allocator.free(self.tools); try self.browser.init(app, .{}, null); errdefer self.browser.deinit(); @@ -311,7 +309,7 @@ pub fn deinit(self: *Agent) void { self.terminal.deinit(); self.message_arena.deinit(); self.messages.deinit(self.allocator); - self.tool_schema_arena.deinit(); + self.allocator.free(self.tools); self.node_registry.deinit(); self.browser.deinit(); self.notification.deinit(); @@ -327,9 +325,9 @@ pub fn deinit(self: *Agent) void { self.allocator.destroy(self); } -fn buildTools(arena: std.mem.Allocator) ![]const zenai.provider.Tool { +fn buildTools(allocator: std.mem.Allocator) ![]const zenai.provider.Tool { const schemas = SlashCommand.globalSchemas(); - const tools = try arena.alloc(zenai.provider.Tool, schemas.len); + const tools = try allocator.alloc(zenai.provider.Tool, schemas.len); for (schemas, 0..) |s, i| { tools[i] = .{ .name = s.tool_name, .description = s.description, .parameters = s.parameters }; } diff --git a/src/script/schema.zig b/src/script/schema.zig index 8f931900..bfa3b15b 100644 --- a/src/script/schema.zig +++ b/src/script/schema.zig @@ -66,14 +66,13 @@ pub const SchemaInfo = struct { recorded: bool, can_heal: bool, produces_data: bool, - is_multiline_capable: bool, parameters: std.json.Value, /// True when this tool's args fit a multi-line `/ '''…'''` opener: /// exactly one required field, and that field is a string. Used by /// `Command.ScriptIterator` to detect block openers. pub fn isMultiLineCapable(self: *const SchemaInfo) bool { - return self.is_multiline_capable; + return self.required.len == 1 and self.fieldType(self.required[0]) == .string; } pub fn findField(self: *const SchemaInfo, key: []const u8) ?FieldEntry { @@ -115,7 +114,6 @@ fn buildOne(arena: std.mem.Allocator, td: browser_tools.ToolDef, parsed: std.jso .recorded = td.recorded, .can_heal = td.can_heal, .produces_data = td.produces_data, - .is_multiline_capable = false, .parameters = parsed, }; @@ -153,8 +151,6 @@ fn buildOne(arena: std.mem.Allocator, td: browser_tools.ToolDef, parsed: std.jso info.hints = try buildHints(arena, info.required, info.fields); std.debug.assert(info.hints.len <= max_hint_slots); - info.is_multiline_capable = (info.required.len == 1 and info.fieldType(info.required[0]) == .string); - return info; }