* Revert "agent: enhance /save progress and verification feedback"
This reverts commit 54f467d1fa.
* Revert "agent: verify synthesized scripts during /save"
This reverts commit b141da30ca.
* agent: extract save helpers to save.zig
Moves pure helper functions related to the `/save` command (parsing,
validation, file writing, prompt shaping) from `Agent.zig` to a
dedicated `save.zig` module.
Introduces a multi-step synthesis process for `/save` that derives a
logical JSON output schema and uses a dry-run runtime to verify
candidate scripts. The LLM can now run and self-correct its scripts
using a new `run_script` tool before finalizing the save.
Removes the `waitUntil` option from `goto` and other navigation tools,
making them default to the fast `load` event. Introduces a dedicated
`waitForState` tool to wait for specific load states on demand.
Replaces manual tool-by-tool argument parsing in the runtime with a
schema-driven `marshalArgs` function. This supports merging trailing
options objects with leading positional arguments (e.g., `goto(url,
options)`). Also unifies positional definitions in `Schema` for both
the runtime and the recorder.
Only unwrap the `__root` sentinel injected for array schemas, ensuring
single-field object schemas retain their shape. Also update synthesis
prompt instructions for modern JS and tool fidelity.
Removes the `-i`/`--interactive` CLI flag and live file-based
recording. Instead, the REPL now supports a `/load <path>` command
to run scripts from disk, and `/save` to export the in-memory
session recording.
The `Recorder` is simplified to be purely in-memory, and the script
runtime is moved to `src/script/Runtime.zig`.
BREAKING CHANGE: The `-i`/`--interactive` flag has been removed. Use
the `/save` and `/load` commands within the REPL instead.
- Add `recordRaw` to record raw JS lines in the REPL.
- Only record commands if they succeed without error.
- Fix kitty terminal cursor keys by forcing legacy arrow encoding.
Removes the `--self-heal` CLI option, the `scriptStep` and `scriptHeal`
MCP tools, and associated verification/iterator machinery. Replaces
"PandaScript" terminology with "slash commands" and moves shared
helpers to `tools.zig`.
BREAKING CHANGE: The `--self-heal` CLI flag and the `scriptStep` and
`scriptHeal` MCP tools have been removed.
- Use `std.enums.values` and `@tagName` in `ScriptRuntime` to eliminate
the manual `primitive_specs` and `console_specs` arrays.
- Simplify `Primitive.tool()` using `std.meta.stringToEnum`.
- Clean up `writeConsoleLine` and remove `writeJsPositional`.
Replace recorded agent replay with a standalone JavaScript script runtime.
Install synchronous agent primitives in an isolated V8 context, add console
output, return structured extract values as JS objects/arrays, and route script
execution through the new runtime.
Update recording to emit .js function calls, default /save filenames to .js,
drop script-level extract save support, and refresh agent docs/tutorials for
the new format.
Self-healing is disabled for now.
Replaces the fragile `firstSentence` parser with an explicit `summary`
field on tool definitions. Also standardizes user-facing REPL
terminology to "command" instead of "slash command" or "tool".
* tools: add session-scoped bridge store
Exposes `globalThis.lp` to `/eval` calls, allowing state to persist
across evaluations and page navigations. Adds a `save` parameter to
both `/eval` and `/extract` to store results in the bridge.
* browser: await promises in eval and support inline args
- Await JS Promises in `eval` tool with a 30s timeout
- Support inline arguments in multi-line slash commands
- Silence output on successful `save=`
- Add `limit` option to extract schema walker
* eval: return empty text for undefined async IIFE
* extract: support limit on simple string arrays
Treats `["<sel>"]` as sugar for `[{"selector": "<sel>"}]` in the schema
walker. This enables the `"limit"` option on simple string arrays.
Also updates agent documentation to cover cross-call state with `lp.*`.
* refactor: optimize bridge store and schema lookup
- Introduce `bridgeStorePut` to skip redundant JSON validation for
trusted stringified values in `bridgeSync`.
- Store the schema pointer in `BlockOpener` to avoid re-parsing and
looking up the schema in `Iterator.next`.
- Clean up error handling and optional unwrapping in `execEval`.
Add a REPL-only `/save [filename.lp]` command that persists the current
interactive session as PandaScript without requiring the user to start the
agent with `-i <script>`. The command records the same replayable actions as
the existing script recorder, but keeps them in memory until the user chooses
to save.
Functional behavior:
- During a REPL session, record replayable browser actions into an in-memory
script buffer.
- Manual slash commands are recorded through the same PandaScript formatting
and filtering rules used by file recording.
- Natural-language turns record their prompt as a `# ...` comment only when
the LLM turn produces at least one successful replayable tool call.
- Failed LLM tool calls are skipped, and repeated successful `/extract` calls
keep only the last successful extract, matching the existing recorder logic.
- `/save filename.lp` writes the current in-memory recording to that file.
- Bare `/save` creates a random `session-<hex>.lp` file on first save.
- If the first save targets an existing file, prompt with the existing numbered
TTY picker and ask whether to replace or append.
- After the first successful save, the REPL session is locked to that filename:
later `/save` or `/save same-file.lp` appends to the same file without
prompting, while `/save other-file.lp` is rejected.
- After each successful save, reset the in-memory recorder so future saves only
append actions entered since the previous save.
- On any `/save` error or cancellation, keep the in-memory recorder intact so
the user can retry without losing captured actions.
- Restrict `/save` filenames to local file names, not paths, to keep behavior
scoped to the current directory.
Code changes:
- Add `Recorder.Memory`, an in-memory recorder that shares the existing
`Command.isRecorded`, `Command.format`, comment formatting, and `LP_*`
reverse-substitution behavior with file recording.
- Add `Recorder.Memory.reset()` so `/save` can clear only successfully saved
deltas.
- Add `/save` to the REPL meta command table and help/completion surface.
- Add `save_buffer` and `save_path` state to `Agent`.
- Feed manual REPL tool calls into `save_buffer` alongside the existing optional
file recorder.
- Extend LLM turn recording with a `capture_for_save` flag so natural-language
REPL turns can be captured without affecting non-REPL script/self-heal paths.
- Implement `/save` handling in `Agent`:
- parse and validate the optional filename,
- choose replace/append for existing first-save targets,
- remember the first successful save path,
- enforce the single-destination rule for the rest of the session,
- append later deltas by default,
- commit remembered path state only after a successful file write.
- Add focused coverage for the memory recorder’s filtering and reset behavior.
fix: address various stability and reliability issues
- Cache stderr TTY check in Config to optimize log hot path.
- Cap signal handler attempts during no-hard-exit.
- Always duplicate URL segments to prevent invalid frees.
- Write live file before backup in atomic writes.
- Settle microtasks before verifying DOM elements.
- Add diagnostics to command parsing to report invalid field values.
- Fix UTF-8 truncation in spinner to avoid splitting codepoints.
- Fix swapped arguments in log error formatting.
- Distinguish "null" values from missing elements in verifier.
- Handle MCP tool cancellation and timeouts with specific error codes.
- Limit UTF-8 walkback in `capToolOutput` to 3 bytes to prevent
excessive scanning on malformed input.
- Track consecutive backslashes in `tokenize` to correctly handle
even-count backslashes before a closing quote.
Explicitly reject backslash-escaped quotes with a clear error
message, suggesting alternative quote styles or triple quotes.
Bare backslashes (e.g. in Windows paths) remain supported.
Rename the system prompt constant to reflect its broader usage.
Also add instructions to guide the agent on handling follow-up
questions after navigation.
Replaces `printActionResult` and `printToolResult` with a single
`printToolOutcome` function. This unifies the output path and adds
red/green color coding for tool failures and successes.
- Add `/.lp-history` to `.gitignore`.
- Make `SlashCommand.MetaCommand.Tag` private.
- Simplify loop in `tools.zig` using `while ... else`.
- Use `trimStart` instead of `trim` in `Schema.splitNameRest`.
- Merge `formatHealReplacement` and `formatHealReplacementLines` using
a new `HealBody` union.
- Move `interactiveTty` and `promptNumberedChoice` to `Terminal.zig`.
- Relocate and consolidate tests for `canHeal` and `isRecorded`.
- Make internal `Schema` functions private.
- Replace `Action` enum with `Tool` enum using exhaustive switches
- Extract `ScriptIterator` to `Iterator.zig`
- Refactor `schema.zig` into `Schema.zig`
- Move string substitution logic into `tools.zig`
- Clean up `SlashCommand.zig` to only handle REPL meta-commands
Calculate the exact size needed for hint slots in schema.zig to avoid
overallocating. Also inline the single-use helper isDefaultTrueBool in
command.zig.
- Allow recording commands with backendNodeId if they also have a
selector, stripping backendNodeId during formatting.
- Point UnterminatedQuote errors to the opening line instead of EOF.
- Fix buildHints allocation when fields is empty but required is not.
- Update docs to clarify positional argument rules.
Tool calls with null arguments are now only considered recorded if the
tool schema has no required fields. This prevents generating invalid,
unreplayable commands for tools like `goto` or `fill`.
- 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.
- Update `buildToolCall` to use `browser_tools.Action` enum.
- Trim whitespace from REPL input in `Agent.zig`.
- Replace `expectEqualStrings` with `expectString` in tests.
Replaces the string `name` in `ToolCall` with `action: browser_tools.Action`.
This avoids repeated string-to-enum parsing and simplifies schema lookups.
Also updates `zenai` dependency to use its JSON duplication helper.
- Remove `input_schema_raw` from `SchemaInfo` and use `parameters` directly
- Simplify JSON field extraction in `Verifier` to avoid `parseArgs`
- Refactor REPL command splitting and environment substitution
- Clean up and condense comments across the codebase
Remove `tool_schema_arena` from `Agent` and allocate the tools slice
directly using the general allocator.
Remove the pre-calculated `is_multiline_capable` field from
`SchemaInfo` and compute it dynamically in `isMultiLineCapable()`.