From fc15027100bd3f1dbadd7cf38e357cff9b09081b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Arrufat?= Date: Sun, 31 May 2026 16:27:28 +0200 Subject: [PATCH] eval: clarify automatic JSON serialization Update agent docs and tool descriptions to note that objects and arrays are automatically serialized to JSON, making manual `JSON.stringify` calls unnecessary. --- docs/agent.md | 7 ++++--- src/browser/tools.zig | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/agent.md b/docs/agent.md index 39a95eb2..193b8dbe 100644 --- a/docs/agent.md +++ b/docs/agent.md @@ -210,13 +210,14 @@ for (const s of lp.front.stories) { ''' /eval ''' -JSON.stringify(lp.front.stories) +lp.front.stories ''' ``` A body with no explicit `return` resolves to `undefined`, which the eval -treats as silent — so the loop above prints nothing, and only the final -`JSON.stringify` lands on stdout. +treats as silent — so the loop above prints nothing. The final `/eval` +yields the array, which lands on stdout as JSON: objects and arrays are +serialized automatically, so no `JSON.stringify` is needed. The store is **script-run scoped**: it's bound to the Session that runs the script, and goes away when that Session does. There is no diff --git a/src/browser/tools.zig b/src/browser/tools.zig index d1ce2b7c..e4515b62 100644 --- a/src/browser/tools.zig +++ b/src/browser/tools.zig @@ -192,7 +192,7 @@ pub const Tool = enum { .input_schema = url_params_schema, }, .eval => .{ - .description = "Evaluate JavaScript in the current page context. A bare trailing expression yields its value; top-level `await` and `return` are supported (the body then runs as an async function, so use `return` to produce a value). If a url is provided, it navigates to that url first. The `globalThis.lp` object exposes a Session-scoped bridge store: values written via `lp.foo = ...` auto-sync at end of eval, surviving navigation; values previously set via `/extract save=` or `/eval save=` appear as `lp.`.", + .description = "Evaluate JavaScript in the current page context. A bare trailing expression yields its value; top-level `await` and `return` are supported (the body then runs as an async function, so use `return` to produce a value). Objects and arrays are returned as JSON, so no `JSON.stringify` is needed. If a url is provided, it navigates to that url first. The `globalThis.lp` object exposes a Session-scoped bridge store: values written via `lp.foo = ...` auto-sync at end of eval, surviving navigation; values previously set via `/extract save=` or `/eval save=` appear as `lp.`.", .summary = "Run JavaScript in the page", .input_schema = minify( \\{ @@ -202,7 +202,7 @@ pub const Tool = enum { \\ "url": { "type": "string", "description": "Optional URL to navigate to before evaluating." }, \\ "timeout": { "type": "integer", "description": "Optional timeout in milliseconds. Defaults to 10000." }, \\ "waitUntil": { "type": "string", "enum": ["load", "domcontentloaded", "networkidle", "done"], "description": "Optional wait strategy. Defaults to 'done'." }, - \\ "save": { "type": "string", "description": "Optional bridge-store key. The eval's return value is stored under this name and re-exposed as `lp.` to subsequent evals. Value must be JSON; wrap non-strings with JSON.stringify(...)." } + \\ "save": { "type": "string", "description": "Optional bridge-store key. The eval's return value is stored under this name and re-exposed as `lp.` to subsequent evals. Objects and arrays are stored as JSON automatically; a returned value must be JSON-serializable." } \\ }, \\ "required": ["script"] \\}