Commit Graph

19 Commits

Author SHA1 Message Date
Francis Bouvier
142c940b21 agent: add REPL /save command for recorded sessions
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.
2026-05-29 13:32:53 +02:00
Adrià Arrufat
f7a4d1f6e2 terminal: unify tool and action result printing
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.
2026-05-22 19:05:46 +02:00
Adrià Arrufat
8fb3c7baed tools: restructure browser tools and script schemas
- 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
2026-05-22 13:41:04 +02:00
Adrià Arrufat
e9943a3976 command: use Action enum for ToolCall name
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.
2026-05-21 22:51:52 +02:00
Adrià Arrufat
13ebb9e802 agent: simplify command, schema, and repl logic
- 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
2026-05-21 22:39:58 +02:00
Adrià Arrufat
d16f8a032e script: support triple-quoted strings and optimize lookups
- Add support for triple-quoted strings (''' and """) in the tokenizer
  and quote stripper.
- Avoid allocations in `stripQuotes` by returning slices.
- Optimize schema lookups using O(1) enum-based canonical resolution.
- Skip env var substitution if "$LP_" is not present in the string.
2026-05-21 21:33:05 +02:00
Adrià Arrufat
459893f414 script: unify PandaScript to slash commands
Unifies PandaScript syntax by replacing uppercase keywords with slash
commands (e.g., `/goto`, `/click`, `/fill`). Refactors the `Command`
representation to use a generic tool call structure backed by schemas.

BREAKING CHANGE: Uppercase PandaScript keywords (GOTO, CLICK, TYPE, etc.)
are no longer supported. All scripts must use slash commands.
2026-05-21 20:38:21 +02:00
Adrià Arrufat
31e20ae261 Recorder: pass directory to init and reuse arena
Update `Recorder.init` to accept a `std.fs.Dir` and relative path,
decoupling it from the current working directory.

Also add a persistent arena allocator to `Recorder` to reuse
allocations when scrubbing environment variables on each write.
2026-05-21 17:45:54 +02:00
Adrià Arrufat
55a50746fa script: move helper functions into Command union
Renames `Command.zig` to `command.zig` and moves associated functions
like `parse`, `toToolCall`, and `canHeal` directly into the `Command`
union. This simplifies usage from `Command.Command` to just `Command`.
2026-05-21 17:13:19 +02:00
Adrià Arrufat
92733763d8 refactor: use explicit type names and encapsulate spinner state
- Replace `Self` with `Recorder` and `Verifier` for improved clarity.
- Add `Spinner.isEnabled()` to encapsulate atomic state access.
- Shorten and refine various comments across the codebase.
2026-05-19 11:13:15 +02:00
Adrià Arrufat
66e7b1aafd script: improve verifier and recorder robustness
- Make `VerifyResult.failed` reason non-optional with an OOM fallback.
- Use `ElementProperty` enum for safer JS property injection.
- Ensure `Recorder` disables on all errors to prevent silent data loss.
- Add `CHECK` command round-trip test.
2026-05-19 10:51:13 +02:00
Adrià Arrufat
061a740dbb script: improve reliability, CRLF support, and formatting
- Prevent UB in `applyReplacements` with pointer assertions.
- Reorder `writeAtomic` to build content before writing backup.
- Strip trailing `\r` in `ScriptIterator` for CRLF compatibility.
- Use shorter representation for `SCROLL` commands.
2026-05-19 10:43:20 +02:00
Adrià Arrufat
2862feb7c4 agent: improve recording quality and tool guidance
- Filter redundant `extract` calls in recordings to reduce noise.
- Scrub literal `LP_*` secrets from recorded commands for portability.
- Throw a descriptive error in `extract` when no selectors match.
- Update tool descriptions and guidance to favor a `tree` ->
  `nodeDetails` -> `extract` workflow for more robust selectors.
2026-05-14 13:36:36 +02:00
Adrià Arrufat
001fbb97d0 Recorder: make init fallible and Agent.recorder optional 2026-05-14 08:59:47 +02:00
Adrià Arrufat
635546bf85 Recorder: simplify initialization and file opening 2026-05-13 14:03:18 +02:00
Adrià Arrufat
b2454a9190 chore: add license headers to source files 2026-05-13 13:20:36 +02:00
Adrià Arrufat
f35c4219c9 refactor: improve error handling and rename Self to Agent
- Replace `unreachable` with explicit error returns in Agent and Executor.
- Add `EvalResult.err` helper in `tools.zig` to simplify error paths.
- Improve error propagation in `SlashCommand` and `Recorder`.
- Rename `Self` to `Agent` for better clarity in function signatures.
2026-05-13 13:15:44 +02:00
Adrià Arrufat
884b9cccfd agent: implement schema-driven EXTRACT command
Replaces simple selector extraction with JSON schema-driven extraction.
Supports multi-line triple-quoted blocks for complex schemas.
2026-05-12 19:38:40 +02:00
Adrià Arrufat
c41955ade3 script: move script module to root src directory 2026-05-11 19:56:36 +02:00