From 6cd75c454e07db481999c246f1975a5ea7931d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Arrufat?= Date: Fri, 22 May 2026 09:23:52 +0200 Subject: [PATCH] script: optimize hint allocation and inline helper Calculate the exact size needed for hint slots in schema.zig to avoid overallocating. Also inline the single-use helper isDefaultTrueBool in command.zig. --- src/script/command.zig | 6 +----- src/script/schema.zig | 14 +++++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/script/command.zig b/src/script/command.zig index e1fd44f9..05d51af2 100644 --- a/src/script/command.zig +++ b/src/script/command.zig @@ -284,16 +284,12 @@ fn formatToolCall(tc: Command.ToolCall, writer: *std.Io.Writer) std.Io.Writer.Er } } -fn isDefaultTrueBool(s: *const schema.SchemaInfo, key: []const u8, v: std.json.Value) bool { - return v == .bool and v.bool and s.isFieldDefaultTrue(key); -} - /// Args that the recorder must NOT emit: /// - `backendNodeId`: ephemeral identifier, never replayable. /// - boolean fields whose value equals the schema default (cosmetic). fn skipForFormat(s: *const schema.SchemaInfo, key: []const u8, v: std.json.Value) bool { if (std.mem.eql(u8, key, "backendNodeId")) return true; - return isDefaultTrueBool(s, key, v); + return v == .bool and v.bool and s.isFieldDefaultTrue(key); } fn formatString(writer: *std.Io.Writer, s: []const u8) std.Io.Writer.Error!void { diff --git a/src/script/schema.zig b/src/script/schema.zig index 4a691e13..e8cb4f98 100644 --- a/src/script/schema.zig +++ b/src/script/schema.zig @@ -141,11 +141,15 @@ fn buildOne(arena: std.mem.Allocator, action: browser_tools.Action, td: browser_ fn buildHints(arena: std.mem.Allocator, required: []const []const u8, fields: []const FieldEntry) ![]const HintSlot { if (fields.len == 0 and required.len == 0) return &.{}; - // Worst case: every required name is absent from `properties`, so we emit - // one slot per required entry plus one per field. The returned slice is - // truncated to the actual count. - const out = try arena.alloc(HintSlot, required.len + fields.len); + var optional_count: usize = 0; + for (fields) |f| { + if (!containsName(required, f.name)) { + optional_count += 1; + } + } + const out = try arena.alloc(HintSlot, required.len + optional_count); var idx: usize = 0; + defer std.debug.assert(idx == out.len); for (required) |name| { out[idx] = .{ .name = name, @@ -163,7 +167,7 @@ fn buildHints(arena: std.mem.Allocator, required: []const []const u8, fields: [] }; idx += 1; } - return out[0..idx]; + return out; } fn containsName(names: []const []const u8, target: []const u8) bool {