diff --git a/src/agent/Agent.zig b/src/agent/Agent.zig index 09f7daf1..13051f3f 100644 --- a/src/agent/Agent.zig +++ b/src/agent/Agent.zig @@ -442,9 +442,10 @@ fn runRepl(self: *Agent) void { self.browser.env.cancelTerminate(); } - if (line.len == 0) continue; + const trimmed = std.mem.trim(u8, line, &std.ascii.whitespace); + if (trimmed.len == 0) continue; - const slash_split: ?SlashCommand.Split = if (line[0] == '/') SlashCommand.splitNameRest(line[1..]) else null; + const slash_split: ?SlashCommand.Split = if (trimmed[0] == '/') SlashCommand.splitNameRest(trimmed[1..]) else null; if (slash_split) |split| { if (SlashCommand.findMeta(split.name) != null) { if (self.handleMeta(split.name, split.rest)) break :repl; diff --git a/src/script.zig b/src/script.zig index 8b8e1957..a88ef035 100644 --- a/src/script.zig +++ b/src/script.zig @@ -30,6 +30,7 @@ //! heal roundtrip themselves. const std = @import("std"); +const browser_tools = @import("browser/tools.zig"); pub const Command = @import("script/command.zig").Command; pub const Recorder = @import("script/Recorder.zig"); @@ -369,7 +370,8 @@ test "applyReplacements: heals a multi-line /eval block using iterator span" { fn buildToolCall(arena: std.mem.Allocator, name: []const u8, kvs: []const struct { []const u8, []const u8 }) Command { var obj: std.json.ObjectMap = .init(arena); for (kvs) |kv| obj.put(kv[0], .{ .string = kv[1] }) catch unreachable; - return .{ .tool_call = .{ .name = name, .args = .{ .object = obj } } }; + const action = std.meta.stringToEnum(browser_tools.Action, name).?; + return .{ .tool_call = .{ .action = action, .args = .{ .object = obj } } }; } test "formatHealReplacement: single command produces one-line replacement" { diff --git a/src/script/schema.zig b/src/script/schema.zig index 89794efa..459f2437 100644 --- a/src/script/schema.zig +++ b/src/script/schema.zig @@ -407,7 +407,7 @@ test "parseValue: single-required positional binds" { const schemas = globalSchemas(); const goto = findSchema(schemas, "goto").?; const v = (try parseValue(arena.allocator(), goto, "https://example.com")).?; - try testing.expectEqualStrings("https://example.com", v.object.get("url").?.string); + try testing.expectString("https://example.com", v.object.get("url").?.string); } test "parseValue: positional then kv tail" { @@ -416,7 +416,7 @@ test "parseValue: positional then kv tail" { const schemas = globalSchemas(); const goto = findSchema(schemas, "goto").?; const v = (try parseValue(arena.allocator(), goto, "https://example.com timeout=5000")).?; - try testing.expectEqualStrings("https://example.com", v.object.get("url").?.string); + try testing.expectString("https://example.com", v.object.get("url").?.string); try testing.expectEqual(@as(i64, 5000), v.object.get("timeout").?.integer); } @@ -426,8 +426,8 @@ test "parseValue: kv-only multi-required" { const schemas = globalSchemas(); const fill = findSchema(schemas, "fill").?; const v = (try parseValue(arena.allocator(), fill, "selector='#email' value='foo@x.com'")).?; - try testing.expectEqualStrings("#email", v.object.get("selector").?.string); - try testing.expectEqualStrings("foo@x.com", v.object.get("value").?.string); + try testing.expectString("#email", v.object.get("selector").?.string); + try testing.expectString("foo@x.com", v.object.get("value").?.string); } test "parseValue: kv-only zero-required" { @@ -461,7 +461,7 @@ test "parseValue: setChecked defaults checked=true when omitted" { const schemas = globalSchemas(); const set_checked = findSchema(schemas, "setChecked").?; const v = (try parseValue(arena.allocator(), set_checked, "selector='#agree'")).?; - try testing.expectEqualStrings("#agree", v.object.get("selector").?.string); + try testing.expectString("#agree", v.object.get("selector").?.string); try testing.expect(v.object.get("checked").?.bool); } @@ -479,15 +479,15 @@ test "parseValue: bare JSON passthrough" { const schemas = globalSchemas(); const find = findSchema(schemas, "findElement").?; const v = (try parseValue(arena.allocator(), find, "{\"role\":\"button\"}")).?; - try testing.expectEqualStrings("button", v.object.get("role").?.string); + try testing.expectString("button", v.object.get("role").?.string); } test "splitNameRest: trims and handles empty" { try testing.expect(splitNameRest("") == null); try testing.expect(splitNameRest(" ") == null); const r = splitNameRest(" goto https://x ").?; - try testing.expectEqualStrings("goto", r.name); - try testing.expectEqualStrings("https://x", r.rest); + try testing.expectString("goto", r.name); + try testing.expectString("https://x", r.rest); } test "tokenize: inline triple quotes with spaces" { @@ -495,6 +495,6 @@ test "tokenize: inline triple quotes with spaces" { defer arena.deinit(); const tokens = try tokenize(arena.allocator(), "selector='''hello world''' value=\"\"\"foo bar\"\"\""); try testing.expectEqual(@as(usize, 2), tokens.len); - try testing.expectEqualStrings("selector='''hello world'''", tokens[0]); - try testing.expectEqualStrings("value=\"\"\"foo bar\"\"\"", tokens[1]); + try testing.expectString("selector='''hello world'''", tokens[0]); + try testing.expectString("value=\"\"\"foo bar\"\"\"", tokens[1]); }