From f759f149377942c4e04802c45162cda1c9bfb2b3 Mon Sep 17 00:00:00 2001 From: t Date: Sat, 4 Jul 2026 09:50:12 -0600 Subject: big cli/tui gaps project --- docs/cli-tui-gaps.md | 321 --------------------------------------------------- 1 file changed, 321 deletions(-) delete mode 100644 docs/cli-tui-gaps.md (limited to 'docs') diff --git a/docs/cli-tui-gaps.md b/docs/cli-tui-gaps.md deleted file mode 100644 index 6791941..0000000 --- a/docs/cli-tui-gaps.md +++ /dev/null @@ -1,321 +0,0 @@ -# panto CLI/TUI: gaps and proposals - -Survey of the current CLI/TUI surface (2026-07-03) and what to do about it. - -Framing first, because it decides everything below: panto's job is not to -do everything, it's to make everything possible. It is a minimal -interactive shell over libpanto plus a powerful Lua extension API, in the -spirit of pi (https://pi.dev) — users build their own ideal agent on top, -and that agent need not be a coding agent at all (the shipped coding tools -are themselves deny-able Lua extensions). So every "gap" lands in one of -three buckets: - -- **Core** — makes the shell itself usable and scriptable. Baseline, - not coding-specific. Ships in Zig (and should generally also be - reachable from Lua). -- **Extension API** — core shouldn't do the thing; core should make the - thing *buildable*. New API surfaces are co-designed with Travis before - building. -- **Not ours** — coding-agent conveniences. Belongs in `../panto-agent` - or other out-of-tree extensions; listed only so we stop re-proposing it. - -Priorities within a bucket: **P0** = bug or table-stakes, **P1** = next -tranche, **P2** = deliberate deferral. - ---- - -## 1. Bugs (core, P0, all small) - -Fix regardless of anything else below. - -1. **Duplicate short session IDs.** `panto sessions` shows `id[0..8]` - (`src/subcommand.zig:374`), but IDs are UUIDv7 and the first 8 hex chars - are the top 32 bits of the millisecond timestamp — no randomness until - char 15. Two sessions created within ~65 s in one project display - identical short IDs. Fix: shortest-unambiguous prefix per listing - (extend past 8 while any two collide). - -2. **`AmbiguousSessionId` exits silently.** `--resume ` matching - two files propagates the error to a bare `exit(1)` at - `src/main.zig:282-283` — no message. Only `SessionNotFound` gets a tidy - error (`main.zig:724-727`). Fix: print the candidates and exit. - -3. **`--resume` (bare) and `panto sessions` disagree on "most recent".** - `findMostRecentSession` takes the lexicographic filename max = - newest-*created* (`file_system_jsonl_store.zig:981-1010`); the listing - sorts by newest-*modified*. Fix: make `latest()` use `modified`. - -4. **`trimCreated` doesn't trim.** Promises `YYYY-MM-DD HH:MM`, returns - `iso[0..16]` with the `T` intact (`src/subcommand.zig:386-394`). - -5. **`--resume` flag peeking can't rewind.** A `-`-leading token after - `--resume` is warned-and-dropped instead of parsed as its own flag - (`main.zig:676-688`). Becomes real once a second agent flag exists (§2). - -6. **Base config template comment says `[tools]`** where the code reads - `[extensions]` (`luarocks_runtime.zig:460` vs `config_file.zig:201`). - ---- - -## 2. Core: command-line flags - -Today the entire agent-mode flag surface is `--resume []` -(`main.zig:658-697`). For an "interactive agent SDK" the bar is: launch it, -point it at a model, script it, resume it. That's about five flags. - -### P0 - -- **`-p, --print ` — one-shot non-interactive mode.** One agent - turn (tools and all), text to stdout, meaningful exit code; prompt from - the arg or stdin when piped. panto currently *requires* a tty - (`main.zig:494-503`) and cannot be scripted at all — the biggest gap in - the product. Composes with `--resume` for headless continuation. Pairs - with libpanto's "one-shot simple API" todo (`docs/todos.md:12`). -- **`-m, --model `.** Already anticipated: - `selectModel(model_override)` exists and `main.zig:227` passes `null`. - Wire it through; accept a bare alias when unambiguous. -- **`--version`.** Embed at build time; print `panto `. -- **Unknown flags error, don't warn-and-continue** (`main.zig:686,693`). - A typo silently launching a TUI is how scripts hang. - -### P1 - -- **`-c, --continue`** — ergonomic alias for bare `--resume`. -- **`--no-extensions`** — skip the Lua runtime: fast `-p` in CI, and the - escape hatch when an extension breaks startup. Given that even the - shipped tools are extensions, define semantics as "built-ins only, - policy-denied everything else". -- **`--effort `** — same pattern as `--model`. - -### Skip - -- `--config ` — the 4-layer TOML merge already covers it. -- `--output-format json` for `-p` — wait for a real consumer. -- `--cwd` — `cd && panto`. - -### `panto sessions` output (P0) - -Currently `<8-char-id> messages`, while the useful -fields (`last_user_message`, `model`, `modified`) are computed by -`buildFileInfo` and discarded. Proposal: - -``` -ID MODIFIED MSGS MODEL LAST MESSAGE -0197c2a4 2026-07-01 14:32 18 anthropic:sonnet fix the segfault in tui_engine when… -0197b1f0 2026-06-30 09:15 4 openai:gpt add a --version flag -``` - -Sort and *show* by modified; shortest-unique IDs (§1.1); truncate last -message to width; plain aligned columns, no box-drawing. Print the sessions -dir path as the last line so the storage is discoverable. Keep resume as a -flag (it composes with `-p`/`-m`; `sessions` stays list-only) — the real -contract is that listed IDs paste into `--resume` without ambiguity. - ---- - -## 3. Core: slash commands - -Current inventory: **`/compact`** (`src/compaction.zig:13`). The framework -(registry, Lua `panto.ext.register_command`, capture-to-transcript, error -rendering) is complete — and mostly-empty is correct for panto. But a shell -whose product *is* its extension points still has to be self-describing and -steerable. These are baseline and coding-agnostic, so they're core Zig; -each should also be achievable from Lua via `panto.ext.agent` (the -sufficiency audit in §7). - -### P0 - -- **`/help`** — registered commands (`Registry.list()` exists solely for - this and tab completion) plus the key bindings. Today nothing in the - product reveals that `/compact` or Ctrl+G exist. For an - extensions-first tool, discoverability of what's currently loaded is not - a convenience — it's how users see their own extensions. -- **`/quit`** — trivial; the only exit today is Ctrl+C/D. -- **`/model [provider:alias]`**, **`/reasoning [level]`** — no arg opens - the existing selector; with arg sets directly. Makes the selectors - discoverable and terminal-agnostic (see the Ctrl+M problem, §4). -- **`/new`** — fresh session in place; today you quit and relaunch. - -### P1 - -- **`/resume []`** — in-TUI session switcher; no arg opens a fuzzy - `Selector` over sessions (short-id + modified + last message rows). -- **`/status`** — provider, model, reasoning, session id, message count, - context used vs window. All already in `command.Context` or computable. - -### Completion and typeahead (P1) - -The fuzzy machinery already exists and is good — the model selector does -case-insensitive subsequence filtering with Ctrl+N/P + Enter. Extend the -same feel to the input box (`docs/todos.md:22` tracks this): - -- **Leading-`/` typeahead**: when the buffer starts with `/`, surface a - live-filtered command list (from `Registry.list()`, which exists for - exactly this) in the same selector idiom; Tab or Enter-on-selection - completes. Registered Lua commands appear automatically — this is - another discoverability channel for extensions, like `/help`. -- **Tab completes file/dir names from cwd** anywhere in the buffer: - complete the token under the cursor against the filesystem, common-prefix - first, selector on ambiguity. Coding-agnostic (paths are universal). -- Later: **per-command argument completion** declared by the command - (e.g. `/model` completing `provider:alias`, Lua commands supplying a - completion function). That's an extension API surface — §7. - ---- - -## 4. Core: key bindings - -Input box editing is solid (word motion, Ctrl+A/E/U/W, Shift+Enter -multiline, bracketed paste). Gaps: - -### P0 - -- **Input history (Up/Down recall).** Decoded and dropped today - (`tui_components.zig:1207`). Up at buffer-top / Down at buffer-bottom - navigate history so multiline arrow-editing still works; in-memory - per-run is enough to start. -- **Idle Escape clears the input buffer.** Makes Escape uniformly "cancel - the thing in progress" (it already interrupts turns and closes - selectors). -- **Fix Ctrl+M.** Ctrl+M *is* carriage return; the model-selector binding - only exists on Kitty-protocol terminals and silently vanishes on plain - xterm/tmux. With `/model` (§3) as the discoverable path, move the chord - to a legacy-safe key (Ctrl+T is free) or accept slash-only on legacy - terminals — either way `/help` documents reality. - -### P1 - -- **Ctrl+L** — clear/redraw (engine already has full-redraw machinery). -- **Buffer typed input during a turn** and restore it to the input box - after; full mid-turn steering waits on libpanto queueing - (`docs/todos.md:15`). -- **Dedup the chord dispatch**: Ctrl+O/M/R are re-implemented in both - `handleBytes` (`tui_app.zig:1801-1842`) and `pumpTurnKeys` - (`tui_app.zig:2286-2304`). One `appChord(key) -> ?Action` both call. - This is also the seam the keybinding extension API (§7) slots into. - -### Deliberate non-features - -- Kill-ring/yank, undo — already deferred in-code ("plan P2"); agreed. -- In-app transcript scrolling — engine delegates to native terminal - scrollback by design (`tui_engine.zig:36-42`); keep. - ---- - -## 5. Core: config.toml settings - -The `[defaults]`/`[compaction]`/`[extensions]`/`[providers]`/`[auth]` -sections cover the agent; the TUI itself has zero settings. A halfway -decent agent TUI supports at least: - -### P1 - -- **`[defaults] reasoning = ""`** — today reasoning comes only from - models.toml per-alias or the Ctrl+R selector; a session default belongs - next to `defaults.model`. -- **`[tui] editor = "..."`** — Ctrl+G honors only `$EDITOR`; a config - override is the conventional courtesy. -- **`[tui] tools_collapsed = true|false`** — the Ctrl+O collapse state's - starting value. -- **`[tui] theme`** — the palette is deliberately comptime-fixed today - (`tui_theme.zig:5-6` says centralization, not theming). A minimal - version: named color overrides for the existing `StyleName` slots. - P1 only if cheap; a full theming system is P2 at best. - -### Skip - -- Keymap section — subsumed by the keybinding extension API (§7). -- Footer layout config — subsumed by the footer segment API (§7). -- Anything per-command/per-tool — that's extension config, which - extensions can already read themselves (Lua reads files). - ---- - -## 6. Core: the footer - -Today the footer is one dim line: `provider:alias (reasoning)`, latest -context tokens, session tokens, session cost (`tui_components.zig:1533`, -all pushed from Zig via `setModel`/`setContextTokens`/...). Worth adding: - -### P1 - -- **Context as a fraction, not a raw count.** `12.3k ctx` is meaningless - without the window; models.toml already has `context_window`. Show - `12.3k/200k ctx` or a percentage — this is the number that tells you - when compaction looms, arguably the footer's whole job. -- **Session short-id** — pairs with `/status` and `panto sessions`; makes - "which session am I in" free. -- **Transient key-hint slot** — e.g. `esc interrupt` while a turn runs. - One hint at a time, context-dependent; not a permanent hint bar. - -### P2 / skip - -- git branch, cwd — coding/shell-flavored and knowable from the terminal; - an extension can add these once the segment API (§7) exists. Skip in - core. - ---- - -## 7. Extension API gaps (make it possible) - -The survey surfaced these as missing Lua surfaces. Per AGENTS.md, each gets -co-designed before building — this list is scope, not spec. - -- **Keybinding registration.** Wanted: extensions can bind chords to Lua - handlers (and presumably rebind/shadow core ones). Blocked on the - `appChord` central dispatch (§4) existing first. Design questions for - the co-design pass: conflict policy vs core chords, per-context bindings - (idle vs during-turn vs selector), and whether declared bindings - auto-appear in `/help`. -- **Footer segments.** The footer is entirely Zig-fed today; extensions - have no way to add a readout (git branch, active skill, queue depth). - Likely shape: register a segment that returns a short string, repainted - on demand — rhymes with the existing screen-component API. -- **Completion providers.** Per-command argument completion for Lua slash - commands (§3): a command optionally supplies a completion function. -- **Session store access** from Lua (list/resolve/load). Needed for an - extension to build its own `/resume`-like or archival behaviors; today - sessions are invisible to extensions. -- **Selector/prompt UI for extensions.** TUI screen components are done - (`docs/todos.md:31`); a fuzzy-pick-from-list primitive is the missing - interactive piece extensions keep needing (model pickers, skill pickers, - session pickers all rhyme). - -Not a gap (previously misreported here): the current agent and -conversation **are** exposed — `panto.ext.agent` wraps the live session -agent with the full method surface (`lua_runtime.zig:219-242`), and the -conversation hangs off it. What's worth auditing instead is whether that -surface is *sufficient* for §3-parity from Lua: model/config switching, -starting a fresh session, reading usage/config for a `/status`-alike. - ---- - -## 8. Not ours (so we stop re-proposing it) - -- **`/usage`, `/cost`** — buildable today-ish from the Lua usage-metrics - API + models.toml pricing; panto-agent material. -- **`/init`, `/review`, `/pr`, rules/skills injection** — coding-agent - features; panto-agent already owns this space (`agent.rules`, - `agent.skill`). -- **`/undo` / checkpointing** — real design work and coding-flavored; - out-of-tree when someone wants it. -- **User keymap config file** — subsumed by the keybinding extension API - (§7); a TOML keymap section can be revisited if non-extension users ask. - ---- - -## 9. Sequencing - -1. §1 bug fixes + `panto sessions` output + shortest-unique IDs — one PR, - pure fixes. -2. `--model`, `--version`, strict flag parsing — small PR. -3. `-p/--print` — the headline; with libpanto's one-shot todo or a thin - plain-text presenter over the existing loop. -4. Slash commands P0 (`/help`, `/quit`, `/model`, `/reasoning`, `/new`). -5. Keybindings P0 (history, idle-Escape, Ctrl+M move) + `appChord` dedup. -6. Footer P1 (context fraction, session id) + config.toml `[defaults] - reasoning` / `[tui]` basics. -7. `/resume` switcher, `/status`, completion/typeahead (§3). -8. Extension API co-design round: keybindings, footer segments, completion - providers, session store, selector primitive (§7) — then panto-agent - picks up §8. -- cgit v1.3