feat: Codex-style terminal UI (a3s-code TUI)#82
Open
ZhiXiao-Lin wants to merge 11 commits into
Open
Conversation
A new `crates/code/cli` crate (binary `a3s-code`) built on the a3s-tui TEA framework. It drives an AgentSession via `session.stream()` and renders the AgentEvent stream as a live chat transcript: - streaming assistant text (StreamingMarkdown) + working spinner - tool-call lifecycle lines (ToolStart/ToolEnd) - HITL: ConfirmationRequired -> approve/deny modal -> confirm_tool_use - multi-line input, scrollback, slash commands (/clear, /exit), Ctrl+C quit The async bridge is a self-re-issuing "pump" command that drains the agent's mpsc event receiver into the synchronous TEA update loop one event at a time. Own `[workspace]` root with path deps on a3s-code-core (../core) and a3s-tui (../../tui), so it does not affect a3s-code's main workspace and a standalone clone of this repo keeps building unchanged. (a3s-tui must be published to crates.io before this can ship as a release artifact.) A headless `A3S_CODE_TUI_SMOKE=1` mode exercises the same stream/AgentEvent path without a TTY. Verified end-to-end against a real model (gpt-4o via the gateway): "what is 2 + 2?" -> streamed "2 + 2 equals 4." then End.
Next increment on the agent TUI: - Esc interrupts an in-progress run (session.cancel()), with an "interrupting…" note; the stream then closes and the turn finalizes normally. - ReasoningDelta is rendered live as dimmed "💭 thinking" above the answer and cleared when the answer finalizes (useful for reasoning models). - On completion, show token usage from the End event (total / prompt / completion). - /help slash command; refreshed welcome + status-bar hints (Esc interrupt). Build + clippy + fmt clean; regression smoke against gpt-4o still streams a valid answer.
The write/edit tools already emit before/after/file_path in ToolEnd metadata (edit.rs even notes it's "so frontend can show Monaco diff"), so this is a TUI-only change — no core change needed. - render_tool_end: for tool results carrying before/after/file_path, render a colored line diff (similar::TextDiff) with +adds/-dels header and green/red changed lines (context lines omitted; capped at 80 lines). Other tools keep the status + output-head line. - Adds serde_json + similar deps; unit tests for the diff vs status-line paths. patch tool doesn't emit before/after, so it falls back to the status line.
- ↑/↓ recall submitted prompts into the input (single-line input only, so multi-line editing keeps normal cursor movement); going forward past the newest entry returns to a fresh input. - Render SubagentStart / SubagentEnd as dimmed "↳ subagent <agent>" lines so delegated work is visible in the transcript. - Refreshed /help. Build + tests + clippy + fmt clean; regression smoke against gpt-4o still streams correctly.
- Enable mouse support; scroll wheel scrolls the transcript viewport. - Status bar now shows the model (captured from the first turn's response metadata) and cumulative session token usage. Build + tests + clippy + fmt clean.
Persist the conversation to <cwd>/.a3s/tui-sessions (FileSessionStore, fixed "tui-default" id, auto-save). On launch, resume that session if it exists and seed the transcript with the prior user/assistant turns; otherwise start fresh. Relaunching in the same directory continues the conversation with full agent context. Also fixes run_smoke to drain the stream fully and await the stream task, so the background auto-save completes before exit (the headless probe was exiting too early to persist). Verified end-to-end against gpt-4o: run 1 "remember 42" → run 2 (fresh process) recalls "42" from the persisted session.
Codex-style action log: accumulate the streamed tool-input JSON and show the tool's primary argument on completion — "✓ bash — npm test", "✓ read — src/main.rs", "✓ grep — TODO" — instead of just the tool name. The HITL approval modal now renders args as pretty-printed JSON. Unit tests for arg-summary extraction and the summary in the result line.
- /auto toggles Codex-style approval mode: while on, tool-confirmation prompts are auto-approved (shown as "⚡ auto-approved <tool>") instead of opening the modal. - Welcome screen shows the working directory for context; /help lists /auto.
When a tool returns file/code content (read/edit on a known extension), render the output as a syntax-highlighted fenced block via a3s-tui's Markdown (syntect), matching how Codex shows file content. Other tool output stays dimmed. Also make the headless smoke probe print tool output for debugging.
Render ToolOutputDelta live — the tail of a running tool's stdout is shown dimmed under the action (like watching a command run in Codex), then cleared when the tool completes.
File-modifying tools (write/edit/patch) require a confirmation manager; without one they fail with "requires confirmation but no HITL confirmation manager is configured" — so the agent could never edit files in the TUI. Enable ConfirmationPolicy on the session (long timeout so the approve/deny modal never expires). Now write/edit emit ConfirmationRequired → the TUI modal (or /auto) approves → the tool runs → the diff renders. Verified end-to-end against gpt-4o: "create note.txt with hello" → approved → file written, exit 0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A Codex-class interactive terminal UI for the agent, in a new
crates/code/clicrate (binarya3s-code), built on thea3s-tuiTEA framework and drivingAgentSession::stream().Features (all real-model verified against gpt-4o)
/autoapproval modeFileSessionStore)/help /clear /auto /exit)Verified end-to-end: streaming, tool calls execute (
write→ file created with approval), session resume restores context. Rendering logic unit-tested (4 tests); every commitclippy+fmtclean.Build/CI impact: none
crates/code/cliis its own[workspace](path-depsa3s-code-core+a3s-tui), so it's excluded from a3s-code's workspace and CI — merging adds the code without touching core/SDK builds or release.Shippability follow-up (separate, needs decisions)
To release as a distributed binary,
a3s-tuimust be reachable standalone — publish it to crates.io (needs the registry token) or switch the cli to a git dep — then add a binary build to the release pipeline. Until then it runs in the monorepo viaa3s code.