Commit Graph
162 Commits
Author SHA1 Message Date
Adrià Arrufat 290e4f81d9 agent: simplify REPL command dispatch and provider bookkeeping
- `available_providers` holds the static enum tag names; drop the dupe
  loop, its errdefer and the per-string frees.
- `reconcileModel` returns `error.ModelNotAvailable` directly instead of
  a `use`/`abort` union the caller only mapped to that same error.
- `runCommand`/`printCommandResult` take `Command.ToolCall`; the caller
  already has it, so the unreachable "no tool mapping" branches go.
- `handleSave` reuses `rememberSavePath`, which now propagates its
  allocation failure so a first save under OOM warns instead of
  unwrapping a null `save_path`.
- `SlashCommand.all_names` is a comptime `++` of the three name lists.
- `buildUserMessageParts` reads the attachment once for both text and
  image, and prepends the text part instead of copying the list.
- `printSeverity`/`formatBulletLine` use `allocPrint` and the shared
  `emitStderr`; drop an unreachable `ends_ws` check in `renderMetaHint`.
2026-09-18 00:45:55 +02:00
Adrià Arrufat 9b7225b580 agent: don't drop REPL tool lines or cut result text mid-codepoint
In a REPL whose stderr isn't a tty the spinner is disabled, so
`agentToolDone`'s `emitAbove` returned false and the `● [tool: …]` line
was discarded. `printToolOutcome` already fell back to a raw stderr write
in that case; share that fallback through `emitStderr`.

The non-REPL result line sliced `text` at a byte offset, which could
split a multi-byte codepoint and emit garbage. Truncate on a UTF-8
boundary instead.
2026-09-18 00:44:49 +02:00
Karl Seguin 2e6999f20b chore: make declarations private if they don't need to be public
This change is 99%  s/pub//   + a handful of dead code removal.
2026-09-10 14:42:09 +08:00
Adrià Arrufat 2899bfef4a agent: route REPL output per tool and align page tables of any size
Every data command went through printAssistant, so /markdown was styled by
accident while /tree, /getUrl and /evaluate strings had `*`/`_` eaten as
emphasis, and /markdown lost table alignment past Stream's 16 KiB buffer.

- printData renders only markdown as markdown; JSON is re-indented and the
  rest prints verbatim.
- render iterates the source directly and aligns tables from the slice;
  Fence holds the fence state shared with Stream.
- Links are OSC 8 hyperlinks around the label only, with the label
  inline-rendered; `![alt](url)` drops the `!`; escapes follow CommonMark
  so what the page dumper escapes is unescaped.
2026-08-28 14:38:27 +02:00
Adrià Arrufat 41e365b3f4 agent: move session banner printing to Terminal 2026-07-29 09:21:02 +02:00
Adrià Arrufat cbce632401 Replace @cImport with build-system translateC
Zig 0.17 removes @cImport in favor of translate-c steps in the build
system. Each library's link function now creates an addTranslateC step
exposed as a module import: curl and isocline translate their headers
straight from the dependency tree, while sqlite3 uses the artifact's
emitted include tree since the amalgamation lives in a sub-dependency.

Terminal.zig and prompt_assist.zig previously instantiated two
independent @cImport namespaces for isocline; they now share one
translated module, so its types are identical across both files.
2026-07-27 12:07:28 +02:00
Karl Seguin 8e42d63c1c zig: Zig 0.16
Built against https://github.com/lightpanda-io/zig-v8-fork/tree/zig-0.16 but
it doesn't require a new v8 build.

Built against https://github.com/lightpanda-io/boringssl-zig/tree/zig-0.16
since the current fork we point to isn't updated.

A global std.Io instance, lp.io. Way easier this way and requires 0 changes to
our libcurl integration / event loop.

Network code uses a new layer that does what Zig 0.15's posix package used to
do. Again, quicker migration that way. But, as long as we have the global IO,
and given the half-baked nature of networking in std.Io 0.16, this just makes
sense. Things can be migrated as needed.

The std.time.* -> std.Io.Timestamp/Clock/Duration resulted in _a lot_ of
changes. ArrayList = .{} -> ArrayList -> .empty also resulted in a lot of
changes, but that's obviously superficial. As is the trimLeft/trimRight ->
trimStart/trimEnd rename.

Locking adopt the `Uncancelable` variants, e.g. mutex.lockUncancelable() to
preserve the error-free signature (and, because cancellation would be something
we'd have to put more thought into).

std.json.ObjectMap is now unmanaged, so the allocator had to be passed along.
However, there's still a deprecated managed variant of MemoryPool, so I switched
to it (we can do a small follow up PR to move to the unmanaged after).

I tried use_llvm = false, but it locks my computer, consuming RAM until MacOS
gives me a popup I've never seen before, begging me to start killing processes.

Agent and the networking stuff saw the most significant changes.
2026-07-22 13:26:03 +08:00
Adrià Arrufat 1d8a0b9fc4 agent: trim narrative comments from the terminal split 2026-07-15 12:20:56 +02:00
Adrià Arrufat f462223277 agent: tighten the seams the terminal split left behind
- attachCompleter now takes the CompletionSource: Agent no longer
  reaches through terminal.assist to configure what it just attached,
  and attach/configure can't be sequenced wrong.
- history_paths flows through one channel: attach() loads the initial
  history from the same State field modeCallback swaps from, instead of
  setupRepl receiving a second copy that had to agree.
- all_names + closestCommand move to SlashCommand.zig, the command
  registry - prompt_assist consumes it like everyone else and
  Terminal's closestCommand re-export disappears.
- picker treats a tty that refuses raw mode as NotInteractive and
  degrades to the line prompt instead of leaking termios errnos to
  callers that can only blanket-catch.
- kitty keyboard flags become named ansi.zig constants shared by
  Terminal.readLine and picker's RawTerminal.
- skipWhitespace was std.mem.indexOfNonePos; single-use style consts
  inline into the style table; drop the dead CompletionSource default
  and doc-comment splice in Spinner.
2026-07-15 12:16:53 +02:00
Adrià Arrufat 673b16528f agent: extract prompt assistance into prompt_assist.zig
Completion, ghost hints, and prompt highlighting (~640 lines) were
cohabiting with Terminal's readline lifecycle and output printing. They
now live in prompt_assist.zig, which owns the isocline callbacks, the
ps-* style palette, and the slash-command name table. The C callbacks
read a small prompt_assist.State (js_mode, completion_source,
history_paths) embedded in Terminal, replacing the three loose fields.
Pure code motion otherwise; the valueAt/renderSchemaHint tests move
with their code and stay in the suite via Terminal's test hook.
2026-07-15 11:50:44 +02:00
Adrià Arrufat f48498073d agent: extract the choice picker into picker.zig
The numbered/interactive picker (ChoiceState, RawTerminal, render loop)
was ~215 self-contained lines inside Terminal.zig. It runs before - or
without - the isocline REPL (provider selection during setup), so
settings.zig no longer imports the isocline-configured Terminal at all.
Pure code motion; the ChoiceState tests move with it and stay in the
suite via Agent.zig's test hook.
2026-07-15 11:40:55 +02:00
Adrià Arrufat 772a3fc7db agent: move terminal width query into its only user, Spinner
Terminal.columns() had exactly one caller (Spinner's line renderer) and
Terminal itself never used it. Moving it breaks the Spinner<->Terminal
import cycle and stops Spinner type-checking against the isocline
@cImport for one ioctl.
2026-07-15 11:36:31 +02:00
Adrià Arrufat 4307509094 agent: improve REPL syntax highlighting and terminal colors
- Add highlighting for JS functions, methods, types, and template
  interpolations.
- Introduce teal color and adjust cyan to bright cyan.
- Import `ansi.zig` directly instead of through `Terminal`.
- Add PandaScript semantics note to the agent's system prompt.
- Refactor markdown table rendering and streaming.
2026-07-15 11:02:46 +02:00
Adrià Arrufat 813cf7f424 agent: clean up terminal rendering and highlighting
- Extract ANSI escape codes to a dedicated `ansi.zig` module.
- Consolidate styled output rendering in `Terminal.zig`.
- Simplify dollar variable highlighting and table measurement.
2026-07-15 09:25:33 +02:00
Adrià Arrufat 8b1686f6fb agent: highlight markdown code blocks as JS
Extracts the JavaScript highlighting logic from `Terminal.zig` into a
reusable `js_highlight.zig` module. Uses this module to syntax-highlight
markdown fenced code blocks in `md_term.zig` using ANSI escape codes.
2026-07-15 09:10:11 +02:00
Adrià Arrufat 53e1dbe8e8 agent: clean up terminal and markdown rendering
- Move ANSI escape definitions to `md_term.zig`.
- Fix table cell width calculation using a scratch buffer.
- Ensure `Stream.close` fully resets markdown stream state.
- Extract helper functions for styled output and fence checks.
2026-07-14 23:13:52 +02:00
Adrià Arrufat d0ce9a02a8 terminal: stream and render markdown incrementally
Introduces an incremental markdown renderer (`md_term.Stream`) to
format streamed assistant responses in real time. Buffers lines,
maintains code fence state across chunks, and temporarily withholds
tables to render them with proper column alignment once complete.
2026-07-14 22:51:43 +02:00
Adrià Arrufat aacddfdbea Merge branch 'main' into agent-repl-markdown-output 2026-07-14 22:32:26 +02:00
Adrià Arrufat 0618515132 terminal: fix nested markdown styles and dim color
- Use a 256-ramp gray for `ansi.dim` to improve readability.
- Track and re-apply active styles in nested markdown spans.
- Collapse extra spaces after list markers.
2026-07-14 21:51:09 +02:00
Adrià Arrufat c67b9f3ad3 terminal: stream markdown rendering to writer
Changes `md_term.render` to write directly to a writer instead of
allocating a string. Also simplifies horizontal rule parsing.
2026-07-14 12:19:26 +02:00
Adrià Arrufat dd1fa4135c agent: render basic markdown in REPL output
Style the assistant's answer in the interactive agent REPL with ANSI
escapes: headings, bullet/numbered lists, bold/italic/inline-code/strike,
and links. Rendering is gated to the REPL on a real terminal, so
`--task`/piped output stays verbatim for programmatic consumption.

Adds src/agent/md_term.zig (markdown -> ANSI renderer) and wires it into
Terminal.printAssistant.
2026-07-13 15:37:01 +02:00
Adrià Arrufat bdb122cdce Merge branch 'main' into agent-streaming 2026-07-12 22:56:54 +02:00
Adrià Arrufat a64ced0ccc fix(agent): stream assistant text only in the REPL
Streaming defaulted on for every mode, so one-shot `--task` and script
runs interleaved intermediate assistant commentary into stdout, which
wrappers treat as the answer. Gate the stream hook on `Terminal.isRepl`
so non-interactive modes keep the buffered final answer.
2026-07-12 22:09:48 +02:00
Adrià Arrufat 049c5f08f2 feat(agent): add assistant text streaming 2026-07-11 00:50:01 +02:00
Adrià Arrufat 03f6577efa agent: continue slash commands across lines inside '''...''' blocks
The docs promise triple-quoted values that span multiple lines, but the
REPL dispatched every physical line immediately, so the multi-line
/extract form died with 'unterminated quote' on its first line. A slash
command that leaves a '''...''' block open now keeps reading lines at a
continuation prompt until the block closes; Ctrl-D abandons it.
2026-07-10 11:55:50 +02:00
Adrià Arrufat 144b3a58a0 terminal: support positional args for single-field schemas
Allows tools like `/getEnv` with a single optional field to accept
positional arguments. Also adds autocompletion and ghost hints for
live `LP_*` environment variables.

Additionally, fixes a memory leak in `settings.zig` when parsing
invalid ZON configurations.
2026-06-17 16:26:43 +02:00
Adrià Arrufat 5eb8e3f8c3 Merge pull request #2705 from lightpanda-io/agent-feedback-fixes
Agent feedback fixes
2026-06-12 15:16:26 +02:00
Adrià Arrufat 538b560676 terminal: highlight JS globals in prompt
Adds syntax highlighting for common JS globals (like window, console,
and lp) in cyan, excluding property accesses.
2026-06-11 19:54:29 +02:00
Adrià Arrufat aeba63427e script: enforce positional arguments come first
Returns a specific `PositionalMustComeFirst` error when a positional
argument is placed after key-value pairs.
2026-06-11 18:24:44 +02:00
Adrià Arrufat d292f2b342 agent: pump session during terminal idle
Updates isocline to support idle callbacks and registers a hook to
pump the session's curl multi while waiting for user input. This
prevents connection timeouts. Also refactors the idle pumping logic
into `Session.idleSlice` to share it with the MCP server.
2026-06-11 18:19:51 +02:00
Adrià Arrufat 4b3e18fda2 agent: extract save helpers to save.zig (#2684)
* 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.
2026-06-09 19:06:09 +02:00
Adrià Arrufat 54f467d1fa agent: enhance /save progress and verification feedback
- Add step-by-step progress reporting during script synthesis.
- Introduce yellow warning bullets for superseded verification runs.
- Refactor bullet emission in Terminal to support multiple statuses.
- Fix spinner formatting when tool arguments are empty.
2026-06-09 17:35:31 +02:00
Adrià Arrufat b141da30ca agent: verify synthesized scripts during /save
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.
2026-06-09 16:53:39 +02:00
Adrià Arrufat 59fb13892e terminal: hint first slash command on single slash
Triggers a ghost hint with the first matching slash command when the
user inputs a single `/` character.
2026-06-09 10:29:57 +02:00
Adrià Arrufat 3baa2726e9 agent: streamline and shorten comments 2026-06-09 09:34:26 +02:00
Adrià Arrufat 6f54c78042 agent: simplify and clean up code comments 2026-06-09 08:43:40 +02:00
Adrià Arrufat 95963e63e8 agent: simplify welcome banner rendering
Statically assert that the banner fits within 80 columns at compile
time. This removes the need to dynamically measure terminal width
and conditionally hide the logo.
2026-06-08 18:50:35 +02:00
Adrià Arrufat c6b1649b93 repl: update isocline and polish hints 2026-06-08 18:26:27 +02:00
Adrià Arrufat 6a35253368 terminal: remove custom status bar
Updates the isocline dependency to use its native hints for Ctrl-D
and Esc. Removes the custom status bar rendering logic, and prints
the active model and effort level at REPL startup instead.
2026-06-08 18:13:49 +02:00
Adrià Arrufat a91eaecb1b build: update isocline and remove top bar
Updates the isocline dependency to a newer commit and removes the
redundant top bar rule configuration in Terminal.zig.
2026-06-08 16:55:29 +02:00
Adrià Arrufat c087229b8a agent: add welcome banner with logo
Prints a Braille-art Lightpanda logo alongside the welcome text and
command hints if the terminal is wide enough. Otherwise, falls back
to a text-only layout.

Also exposes `Terminal.displayWidth` to assist with layout calculations.
2026-06-08 11:28:16 +02:00
Adrià Arrufat 7bcab1d840 terminal: separate normal and JS REPL history
Store normal and JS history in separate files and swap them
dynamically when toggling modes.
2026-06-06 12:44:59 +02:00
Adrià Arrufat c2e2717170 deps: update isocline dependency
Updates the isocline dependency to a newer commit and cleans up
redundant comments in Terminal.zig.
2026-06-06 11:07:05 +02:00
Adrià Arrufat eb118bb1de terminal: highlight $LP_* vars inside strings
Extracts `highlightDollarVarsIn` to support highlighting within a
specific range, then applies it to JavaScript string literals.
2026-06-06 11:02:54 +02:00
Adrià Arrufat 2d574a92b1 terminal: add javascript syntax highlighting in JS mode 2026-06-06 10:53:53 +02:00
Adrià Arrufat b009e416a6 terminal: add Ctrl-D exit confirmation
Updates the isocline dependency and implements a confirmation prompt
when pressing Ctrl-D to exit the terminal.
2026-06-06 10:42:36 +02:00
Adrià Arrufat 828abda838 terminal: support double Esc clear confirmation
Updates isocline and adds a status bar indicator when a clear
is pending after the first Esc press.
2026-06-06 09:47:00 +02:00
Adrià Arrufat a771597caa terminal: support Backspace to exit JS mode
Updates the isocline dependency and the status bar exit hint.
2026-06-06 09:18:20 +02:00
Adrià Arrufat 30725175c1 agent: derive slash command values from enums
Use comptime reflection to generate hints and allowed values for
`/verbosity` and `/effort` commands directly from their config enums.
2026-06-05 17:36:00 +02:00
Adrià Arrufat 3f0c6f6c09 terminal: autocomplete and hint enum values
Parses `enum` constraints from the schema and uses them to provide
tab-completions and ghost hints for enum fields in the REPL.
2026-06-05 16:58:19 +02:00