Bring the coder-lite TUI to inventoried parity with the TypeScript and Rust coder UIs #117
- AtlantisPleb opened this issue 1d ago
-
A Author 1d ago Inventory landed — (3a3f31e8af)
The first half of this issue is done. The porting half stays open, blocked on #116.
Counts: 79 feature rows across three implementations. 32 ported · 10 dropped (each with its reason) · 31 to-port · 2 flagged as boundary violations as scoped · 4 recorded as undetermined rather than guessed.
There are three coder UIs, not two
coder-lite (3,976 app lines + 24,127 vendored markdown),
oa coderin openagents-cli (5,176 TUI-stack lines), andcoder-ui.ts(3,862). All three are live. §5 records which behaviour wins per subsystem so the losers can be retired knowingly.Five premises in the issue did not survive contact (§2)
- The composer arrow points the other way. The TypeScript composer is one flat string (
coder-ui.ts:485) with no cursor index variable anywhere in the file. Verified absent: keyboard newline insertion, cursor movement, word-wise editing, ctrl+w/k/y/a/e, forward delete, prompt history of any kind, and Tab completion of any kind. coder-lite has all of it — 22 chords incomposer/keys.rs, a 500-entry persisted history, path/command/@-mention completion. Multi-line editing, history recall, and kill are ported, not owed. - "Fixed-row template with fleet/composer/spacer constants" describes
coder-ui.ts, nottui.rs. Those constants are atcoder-ui.ts:107-176.tui.rs:273-280is a ratatuiLayoutwith a composer that grows 1..8 rows. - coder-lite is not missing scrollback.
scroll_override/scroll_max/effective_scroll/scroll_byattui.rs:170-390, PageUp/PageDown and Up/Down wired atinteractive.rs:457-472. packages/input-bindingshas zero runtime consumers (1,125 lines) and is DOM-shaped —KeyboardEvent.code, mouse buttons, wheel deltas — written for the Autopilot Desktop app deleted on 2026-08-04. Not a source for a terminal binding table.--offlinedoes not exist in coder-lite. Its parser (main.rs:105-150) takes exactly--help,--version,--dev,--lane,--reasoning. #116 names--offlinein its minimum assertions. This blocks #116, so it is item 1 of the ordered list.
Streaming markdown: 99.8% ported
20,663 upstream
xai-grok-markdown/srclines → 20,699 vendored, 8 of 23 files byte-identical, 596 tests carried. Only three semantic edits exist; everything else is acrate::→crate::markdown::rewrite. Dropped with reasons: mermaid SVG raster (2,170 lines, needs a graphics protocol), benches/fuzz/playgrounds (1,515 lines), footnotes (absent upstream too).Top five to-port, in order
# Item Size Note 1 --offlineon coder-liteS Unblocks #116; the stand-in reply source belongs in openagents-cli ( cli.rs:814-832already has the text)2 Live fleet rows during /delegatefan-outM Highest product value, and cheap — see below 3 Bracketed paste + placeholders + image paste M Today a multi-line paste submits at the first newline: Event::Pasteis dropped atinteractive.rs:166andEnableBracketedPasteappears nowhere incrates/4 /rununder a pseudoterminalL openagents-cli/src/pty.rsis 753 complete lines with 20 tests; this is pane plumbing, not an emulator port5 Status bar: model, lane, repo, branch, reasoning, state, elapsed, hints M Five facts the frame already holds are rendered nowhere. ui.reasoningis assigned atinteractive.rs:73and read by nothing at allOn #2: the machinery already exists and
oa delegatealready renders from it.ChildEvent(delegate.rs:83-97) andDelegationSupervisor::dispatch_streaming(delegate.rs:387) are both there. coder-lite sees nothing only becausefanout_for_toolcalls the blockingdispatch()atdelegate.rs:1604and returns one string at the end. Today a 3-way fan-out is one tool box that stays empty until every child finishes.Boundary violations flagged rather than scheduled (§7)
/goal— a goal store with token budgets is spending policy. The store belongs in openagents-cli; coder-lite renders the row.- Image paste — the placeholder token is presentation; MIME sniffing, base64, and the multimodal content-part shape are runtime.
Two near misses recorded with them (
--offline's reply source,/skills' catalog), plus the reasoning for why fleet rows are not a violation: the test is direction. Logic moving into coder-lite is the violation; a fact moving out to be drawn is the boundary working.Written against the post-0.0.2 shape — one shipped artifact answering two fronts — which makes the boundary a module seam held by review rather than a binary seam held by a linker. §0 says which parts came from the pre-release tree.
Recorded as undetermined (§8), not guessed
Whether coder-lite orphans child processes on exit (settle before the fleet display ships); whether a thread id is reachable by the frame; whether a turn can be cancelled at all (
execute_turnis spawned detached with no handle atinteractive.rs:517); and whetheroa coder's frame has any user after 0.0.2.Not closing this — the porting half is outstanding. Each to-port entry in §6 names the PTY assertion that would prove it, so the port can be executed straight from the document once #116 lands.
- The composer arrow points the other way. The TypeScript composer is one flat string (
-
A Author 1d ago Correction to the heading above — my shell ate the filename in the first line. The inventory is at:
docs/coder/2026-08-26-coder-lite-tui-inventory.md, landed in3a3f31e8af.Everything else in that comment is intact.
-
A Author 1d ago Claiming this from forge main at b166ba0480. I will reconcile the parity inventory against the current native TUI, implement or explicitly disposition every remaining gap, add PTY coverage for behavior we retain, run the completion gate, and close the issue when the acceptance criteria are met.
-
A Author 1d ago Completed on forge main in
dd75e29dc6(WAL receipt 326, link697fe060a4f538b7eda03105c2f38dbfbf2dce49fec22308818ee9788d342120). The inventory now reconciles all 36 historicalto-portrows plus the separately scheduled--offlineitem: 11 capabilities are retained with current implementation and test evidence, and 26 obsolete, duplicative, or contract-free ports are explicitly dropped with reasons. Removed the unreachableCoderUi.reasoning,CoderUi.running, and test-onlyRole::Reasoningpresentation states. Verification:cargo test -p openagents-cli --test coder_rebase_contract(7 passed),cargo test -p openagents-cli --test coder_interactive_pty(17 passed), focused native Coder tests (652 passed), and the fullpnpm run checkgate. The full gate passed 115 TypeScript projects, the Rust workspace including 922 CLI unit tests, 2,427 Vite files / 20,775 tests, and 177 Node tests (one platform skip). - closed this as completed 1d ago
Coder-lite is the coder UI users get (#105 consolidated onto it), and it is deliberately thin:
crates/coder-liteowns the frame, palette, spinner, system prompt, and session loop, takingopenagents-clias the runtime library. The thinness is right for the runtime seam and currently wrong for the terminal experience: the TypeScript coder UI (packages/openagents-cli/src/coder-ui.ts, ~1,700 lines, pluscoder-markdown.ts,coder-plain.ts) and the vendored grok-build engine carry TUI capabilities coder-lite has not absorbed.This is the first improvement target of the autoimprovement loop (
docs/coder/autoimprove.md): make the coder-lite TUI the best terminal surface we have shipped, by porting what earns its place from the Rust and TypeScript versions.Scope
First, an inventory (best practice V3: parity claims quantify). Enumerate the TUI feature set of the TypeScript coder UI and the vendored grok-build markdown engine, mark each feature ported / deliberately dropped / to-port, and commit the inventory under
docs/coder/. Candidates known now:packages/input-bindingswhere applicable) versus coder-lite's current set.src/markdown, from grok-build); diff rendering, tool-call collapse/expand, and transcript scrollback are not confirmed./delegatefan-out.7ad52a0c8d); thread id, lane, and model surface.Then port in dependency order, smallest first, one landing per feature group.
Guardrails
Cargo.tomldraws it: tools, refusal patterns, composer semantics, lanes, catalog, metering stay inopenagents-cli; coder-lite owns presentation and the session loop.Acceptance
to-portfeature either landed with its PTY assertion or re-dispositioned with a reason.pnpm run checkgreen per landing.