mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 01:09:43 +02:00
fix(opencode): read opencode's composer bar and footer spinner so a turn can end
An opencode session that ran a tool stayed "working" for good. The running
tool row draws a braille spinner (`⠋ Sleep for 12 seconds...`), which trips
the generic SPINNER_PATTERN and marks the pane working, but only a composer
glyph arms the idle confirmation and opencode declared none, so it fell back
to Claude's `❯`, which opencode never draws. Measured on an isolated
instance: a 16 s turn latched busy/isWorking for the rest of the session.
A text-only turn had the opposite problem and never showed as working.
Measured on live opencode 1.3.0 panes (capture-pane every 250-300 ms through
real turns at 40, 60, 120 and 200 columns, plus the raw PTY stream):
- Every composer row starts with a `┃` bar, and the submitted prompt lands in
the transcript with the same bar, so a turn's first repaint arms the idle
check, and tmux's reattach repaint does the same for a restored pane.
- While a turn runs the footer row starts with an 8-cell knight-rider
spinner, `⬝■■■■■■⬝ esc interrupt`, redrawn about every 40 ms (largest
gap mid-turn: 121 ms). At rest the TUI is silent and nothing on screen
draws a `⬝`/`■` run, the 200-column sidebar included.
- The working line is the spinner run, `[⬝■]{8}`, not the label: tmux ships
`esc` and `interrupt` as separate words joined by cursor moves, so the
label never reaches the stream detector, and at 40 columns the footer
wraps it to `esc` / `interr` / `upt`. All 344 spinner chunks of a turn
match the run after Codeman's ANSI strip.
- A pending permission prompt replaces the composer and stops the spinner,
so it reads as idle (waiting on the user).
- The last `┃` row on screen is the composer's agent/model row, or the
permission box's closing bar, never the prompt text, so the submit
verifier stands down and can never press Enter into a dialog.
Verified on an isolated instance from this branch: a 15 s tool turn emitted
exactly one session:working (+271 ms) and one session:idle (3 s after the
spinner stopped); a permission prompt read idle and the allowed turn went
working -> idle; after a server restart both restored opencode panes (one
at rest, one on a permission prompt) went busy -> idle in about 4 s; a
fresh launch reached an open page as idle in 3 s.
The launch-settle tests that used opencode as their example of a CLI
without work detection now use gemini and antigravity.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -493,6 +493,27 @@ const OPENCODE: CliEntry = {
|
||||
...agentDefaults(),
|
||||
altScreen: 'strip-mux-only',
|
||||
echo: { policy: 'buffer', anchor: { kind: 'cursor' }, predictProfile: undefined },
|
||||
// Measured on a live opencode 1.3.0 pane (capture-pane every 250-300 ms through real
|
||||
// turns at 40, 60, 120 and 200 columns, plus the raw PTY stream, 2026-10-09). Every
|
||||
// composer row starts with a `┃` bar, and the submitted prompt lands in the transcript
|
||||
// with the same bar, so a turn's first repaint arms the idle confirmation and tmux's
|
||||
// reattach repaint does the same for a restored pane. While a turn runs the footer row
|
||||
// starts with an 8-cell knight-rider spinner, `⬝■■■■■■⬝ esc interrupt`, redrawn about
|
||||
// every 40 ms (never a 2.5 s gap mid-turn, so silence cannot end one early); at rest the
|
||||
// row holds only the key hints and nothing on screen draws a `⬝`/`■` run, the wide
|
||||
// layout's sidebar included. The working line is the spinner run, not the label: tmux
|
||||
// ships `esc` and `interrupt` as separate words joined by cursor moves, and below about
|
||||
// 45 columns the footer wraps the label itself. A pending permission prompt replaces
|
||||
// the composer and stops the spinner, so it reads as idle (waiting on the user).
|
||||
// ⚠️ Without this entry an opencode session latched `busy` after any turn that ran a
|
||||
// tool: the braille spinner on a running tool row trips SPINNER_PATTERN, and opencode
|
||||
// never draws Claude's `❯`, the fallback that would have armed the idle check. The
|
||||
// last `┃` row on screen is the composer's agent/model row (or the permission box's
|
||||
// closing bar), never the prompt text, so the submit verifier stands down.
|
||||
workDetect: {
|
||||
promptGlyph: '┃',
|
||||
workingLine: '[⬝■]{8}',
|
||||
},
|
||||
// opencode's global config dir is xdg-basedir's `$XDG_CONFIG_HOME/opencode`.
|
||||
mcpConfig: {
|
||||
path: '.config/opencode/opencode.json',
|
||||
|
||||
+1
-1
@@ -4485,7 +4485,7 @@ export class Session extends EventEmitter {
|
||||
: this._mux.capturePaneText?.(this._muxSession.muxName),
|
||||
sendEnter: () => this._mux?.sendInput(this.id, '\r'),
|
||||
// ⚠ NO fallback glyph here, unlike the screen-reading probe elsewhere in this file.
|
||||
// Only claude, codex and pi declare a promptGlyph; the other modes would fall back
|
||||
// Only claude, codex, pi and opencode declare a promptGlyph; the other modes would fall back
|
||||
// to claude's `❯`, which is ALSO starship's default shell prompt (and pure's, and
|
||||
// spaceship's, and p10k lean's). On a shell session the line `❯ npm run build` sits
|
||||
// on screen for as long as the command runs, promptStillInComposer() reads that as
|
||||
|
||||
Reference in New Issue
Block a user