mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-15 15:32:03 -04:00
agent: use global tools and simplify meta commands
- Initialize tools once globally instead of allocating per-agent. - Refactor meta commands to use an enum for cleaner dispatch. - Remove unused `findSchemaCanonical` and simplify command parsing.
This commit is contained in:
1 parent
6177d51c4e
commit
a3eeec0b26
7 files changed
+62
-99
No files matched your search
+5
-11
@@ -87,10 +87,6 @@ pub const Command = union(enum) {
|
||||
}
|
||||
|
||||
pub fn parse(arena: std.mem.Allocator, line: []const u8) ParseError!Command {
|
||||
return parseWithSchemas(arena, line, schema.globalSchemas());
|
||||
}
|
||||
|
||||
pub fn parseWithSchemas(arena: std.mem.Allocator, line: []const u8, schemas: []const schema.SchemaInfo) ParseError!Command {
|
||||
const trimmed = std.mem.trim(u8, line, &std.ascii.whitespace);
|
||||
if (trimmed.len == 0) return .{ .comment = {} };
|
||||
if (trimmed[0] == '#') return .{ .comment = {} };
|
||||
@@ -107,7 +103,7 @@ pub const Command = union(enum) {
|
||||
return .{ .accept_cookies = {} };
|
||||
}
|
||||
|
||||
const s = schema.findSchema(schemas, split.name) orelse return error.UnknownTool;
|
||||
const s = schema.findSchema(schema.globalSchemas(), split.name) orelse return error.UnknownTool;
|
||||
const args = try schema.parseValue(arena, s, split.rest);
|
||||
return .{ .tool_call = .{ .action = s.action, .args = args } };
|
||||
}
|
||||
@@ -162,8 +158,6 @@ pub const Command = union(enum) {
|
||||
};
|
||||
|
||||
pub fn next(self: *ScriptIterator) ParseError!?Entry {
|
||||
const schemas = schema.globalSchemas();
|
||||
|
||||
while (self.lines.next()) |line| {
|
||||
self.line_num += 1;
|
||||
const trimmed = std.mem.trim(u8, line, &std.ascii.whitespace);
|
||||
@@ -171,7 +165,7 @@ pub const Command = union(enum) {
|
||||
|
||||
const line_start = @intFromPtr(line.ptr) - @intFromPtr(self.lines.buffer.ptr);
|
||||
|
||||
if (try self.tryBlockOpener(trimmed, schemas)) |opener| {
|
||||
if (tryBlockOpener(trimmed)) |opener| {
|
||||
const start_line = self.line_num;
|
||||
const body = try self.collectMultiLineBlock(opener.quote_type);
|
||||
const span_end = self.lines.index orelse self.lines.buffer.len;
|
||||
@@ -194,7 +188,7 @@ pub const Command = union(enum) {
|
||||
.line_num = self.line_num,
|
||||
.opener_line = trimmed,
|
||||
.raw_span = self.lines.buffer[line_start..span_end],
|
||||
.command = try Command.parseWithSchemas(self.allocator, trimmed, schemas),
|
||||
.command = try Command.parse(self.allocator, trimmed),
|
||||
};
|
||||
}
|
||||
return null;
|
||||
@@ -206,10 +200,10 @@ pub const Command = union(enum) {
|
||||
quote_type: QuoteType,
|
||||
};
|
||||
|
||||
fn tryBlockOpener(_: *ScriptIterator, line: []const u8, schemas: []const schema.SchemaInfo) ParseError!?BlockOpener {
|
||||
fn tryBlockOpener(line: []const u8) ?BlockOpener {
|
||||
if (line.len < 2 or line[0] != '/') return null;
|
||||
const split = schema.splitNameRest(line[1..]) orelse return null;
|
||||
const s = schema.findSchema(schemas, split.name) orelse return null;
|
||||
const s = schema.findSchema(schema.globalSchemas(), split.name) orelse return null;
|
||||
if (!s.isMultiLineCapable()) return null;
|
||||
const qt = QuoteType.fromLiteral(split.rest) orelse return null;
|
||||
return .{ .action = s.action, .field = s.required[0], .quote_type = qt };
|
||||
|
||||
+7
-25
@@ -188,12 +188,6 @@ pub fn findSchema(schemas: []const SchemaInfo, name: []const u8) ?*const SchemaI
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn findSchemaCanonical(schemas: []const SchemaInfo, name: []const u8) ?*const SchemaInfo {
|
||||
std.debug.assert(schemas.len == browser_tools.tool_defs.len);
|
||||
const action = std.meta.stringToEnum(browser_tools.Action, name) orelse return null;
|
||||
return &schemas[@intFromEnum(action)];
|
||||
}
|
||||
|
||||
pub const Split = struct {
|
||||
name: []const u8,
|
||||
rest: []const u8,
|
||||
@@ -246,21 +240,10 @@ pub fn parseValue(arena: std.mem.Allocator, schema: *const SchemaInfo, rest: []c
|
||||
|
||||
// Default-true booleans (e.g. setChecked.checked) so `/setChecked
|
||||
// selector='#a'` works without `checked=true`.
|
||||
for (schema.required) |req| {
|
||||
var found = false;
|
||||
for (list.items) |p| {
|
||||
if (std.mem.eql(u8, p.key, req)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (schema.isFieldDefaultTrue(req)) {
|
||||
list.appendAssumeCapacity(.{ .key = req, .value = "true" });
|
||||
} else {
|
||||
return error.MissingRequired;
|
||||
}
|
||||
}
|
||||
required: for (schema.required) |req| {
|
||||
for (list.items) |p| if (std.mem.eql(u8, p.key, req)) continue :required;
|
||||
if (!schema.isFieldDefaultTrue(req)) return error.MissingRequired;
|
||||
list.appendAssumeCapacity(.{ .key = req, .value = "true" });
|
||||
}
|
||||
|
||||
return try buildValue(arena, schema, list.items);
|
||||
@@ -348,7 +331,9 @@ fn coerce(arena: std.mem.Allocator, schema: *const SchemaInfo, key: []const u8,
|
||||
return .{ .string = try arena.dupe(u8, value) };
|
||||
}
|
||||
|
||||
// --- Global lazy schema cache (process-lifetime) ---
|
||||
// --- Global lazy schema cache ---
|
||||
//
|
||||
// `global_arena` is never deinit'd: it's process-lifetime, freed at exit.
|
||||
|
||||
var global_schemas_storage: [browser_tools.tool_defs.len]SchemaInfo = undefined;
|
||||
var global_arena: std.heap.ArenaAllocator = undefined;
|
||||
@@ -396,9 +381,6 @@ test "globalSchemas: comptime tool defs reduce cleanly" {
|
||||
if (std.mem.eql(u8, f.name, "checked")) checked_default_true = f.default_true;
|
||||
}
|
||||
try testing.expect(checked_default_true);
|
||||
|
||||
try testing.expect(findSchemaCanonical(schemas, "goto") == goto);
|
||||
try testing.expect(findSchemaCanonical(schemas, "unknown_tool") == null);
|
||||
}
|
||||
|
||||
test "parseValue: single-required positional binds" {
|
||||
|
||||
Reference in new issue
Block a user