agent: derive Action enum from tool_defs and clean up Verifier

- Derives the `Action` enum in `src/browser/tools.zig` from `tool_defs` to prevent manual maintenance and potential drift.
- Refactors `verifyElementValue` in `src/script/Verifier.zig` to use a `Check` struct for its parameters.
- Reorganizes and cleans up imports in `src/agent/Agent.zig`.
This commit is contained in:
Adrià Arrufat
2026-05-13 13:18:18 +02:00
parent f35c4219c9
commit b4b533d2be
3 changed files with 29 additions and 35 deletions

View File

@@ -4,15 +4,16 @@ const lp = @import("lightpanda");
const log = lp.log;
const Config = lp.Config;
const App = @import("../App.zig");
const ToolExecutor = @import("ToolExecutor.zig");
const Terminal = @import("Terminal.zig");
const script = lp.script;
const Command = lp.script.Command;
const Recorder = lp.script.Recorder;
const Verifier = lp.script.Verifier;
const App = @import("../App.zig");
const ToolExecutor = @import("ToolExecutor.zig");
const Terminal = @import("Terminal.zig");
const CommandExecutor = @import("CommandExecutor.zig");
const SlashCommand = @import("SlashCommand.zig");
const script = lp.script;
const Agent = @This();

View File

@@ -369,30 +369,17 @@ const ActionTarget = union(enum) {
const NodeAndPage = struct { node: *DOMNode, page: *lp.Frame, target: ActionTarget };
pub const Action = enum {
goto,
search,
markdown,
links,
nodeDetails,
interactiveElements,
structuredData,
detectForms,
eval,
tree,
click,
fill,
scroll,
waitForSelector,
hover,
press,
selectOption,
setChecked,
findElement,
getEnv,
consoleLogs,
getUrl,
getCookies,
/// Derived from `tool_defs` so the enum and the tool table can't drift.
/// Tag order follows declaration order in `tool_defs`.
pub const Action = blk: {
var fields: [tool_defs.len]std.builtin.Type.EnumField = undefined;
for (tool_defs, 0..) |td, i| fields[i] = .{ .name = td.name[0..td.name.len :0], .value = i };
break :blk @Type(.{ .@"enum" = .{
.tag_type = u8,
.fields = &fields,
.decls = &.{},
.is_exhaustive = true,
} });
};
pub fn call(

View File

@@ -46,24 +46,30 @@ fn verifyFill(self: *Self, arena: std.mem.Allocator, selector: []const u8, expec
};
return .{ .result = .passed };
}
return self.verifyElementValue(arena, selector, "value", expected_value, "value");
return self.verifyElementValue(arena, selector, .{ .js_property = "value", .expected = expected_value, .label = "value" });
}
fn verifyCheck(self: *Self, arena: std.mem.Allocator, selector: []const u8, expected: bool) VerifyResult {
const expected_str: []const u8 = if (expected) "true" else "false";
return self.verifyElementValue(arena, selector, "String(el.checked)", expected_str, "checked state");
return self.verifyElementValue(arena, selector, .{ .js_property = "String(el.checked)", .expected = expected_str, .label = "checked state" });
}
fn verifySelect(self: *Self, arena: std.mem.Allocator, selector: []const u8, expected_value: []const u8) VerifyResult {
return self.verifyElementValue(arena, selector, "value", expected_value, "selected value");
return self.verifyElementValue(arena, selector, .{ .js_property = "value", .expected = expected_value, .label = "selected value" });
}
fn verifyElementValue(self: *Self, arena: std.mem.Allocator, selector: []const u8, js_property: []const u8, expected: []const u8, label: []const u8) VerifyResult {
const actual = self.queryElementProperty(arena, selector, js_property) orelse return .{ .result = .inconclusive };
if (!std.mem.eql(u8, actual, expected))
const Check = struct {
js_property: []const u8,
expected: []const u8,
label: []const u8,
};
fn verifyElementValue(self: *Self, arena: std.mem.Allocator, selector: []const u8, check: Check) VerifyResult {
const actual = self.queryElementProperty(arena, selector, check.js_property) orelse return .{ .result = .inconclusive };
if (!std.mem.eql(u8, actual, check.expected))
return .{
.result = .failed,
.reason = std.fmt.allocPrint(arena, "element {s} is \"{s}\" (expected \"{s}\")", .{ label, actual, expected }) catch null,
.reason = std.fmt.allocPrint(arena, "element {s} is \"{s}\" (expected \"{s}\")", .{ check.label, actual, check.expected }) catch null,
};
return .{ .result = .passed };
}