docs(interactive): record ConPTY library + binding decision from spike
This commit is contained in:
@@ -65,18 +65,40 @@ chosen directory (no task). These also get MCP config + env set up so the
|
||||
`claudedo` tools are available, but no per-level session-skills seeding tied to a
|
||||
task.
|
||||
|
||||
### Terminal host control
|
||||
### Terminal host control — RESOLVED by spike (2026-07-23)
|
||||
|
||||
Embed a ConPTY-capable Avalonia terminal control in the UI. Candidates:
|
||||
**Library: `Iciclecreek.Avalonia.Terminal` 2.0.3** (namespace `Iciclecreek.Terminal`).
|
||||
It needs Avalonia >= 12.0.2; the repo is on 12.0.4 → compatible, no bump.
|
||||
`SvcSystems.UI.Terminal` (latest) needs Avalonia 12.1+ → rejected.
|
||||
|
||||
- **SvcSystems.UI.Terminal** (IvanJosipovic) — explicit ConPTY, full-screen TUI
|
||||
render + resize reflow, selection/mouse reporting.
|
||||
- **Iciclecreek.Avalonia.Terminal** — XTerm.NET + Porta.Pty, clean
|
||||
`TerminalControl` embed API.
|
||||
Visual pass (user, 2026-07-23): the real `claude` TUI renders correctly inside
|
||||
the embedded control — Claude Code opened and was usable.
|
||||
|
||||
Selection is resolved by a **spike** (first plan step): the acceptance criterion
|
||||
is that the real `claude` TUI renders correctly inside the control — colors,
|
||||
resize/reflow, and a live permission prompt are usable.
|
||||
**Binding approach — drive Porta.Pty ourselves, reuse Iciclecreek's VT engine.**
|
||||
The convenience `TerminalControl.LaunchProcess()` spawns the child itself and
|
||||
never sets `PtyOptions.Environment`, and there is no settable pty/env seam on
|
||||
`TerminalControl`/`TerminalView` (env-building lives in the non-virtual
|
||||
`TerminalView.LaunchProcess()` using private fields). But the VT parser/renderer
|
||||
is the public `XTerm.Terminal` object exposed via `TerminalControl.Terminal`, so
|
||||
we reuse it without forking:
|
||||
|
||||
- `Porta.Pty.PtyProvider.SpawnAsync(new PtyOptions { Name, App, Cwd, CommandLine,
|
||||
Environment = <fully populated dict> }, ct)` → `IPtyConnection`.
|
||||
- Do **not** call `TerminalControl.LaunchProcess()` (leaves its `_ptyConnection`
|
||||
null).
|
||||
- Get `TerminalControl.Terminal` (public, `XTerm.Terminal`) after template apply.
|
||||
- Pump `IPtyConnection.ReaderStream` → `Terminal.Write(text)`; subscribe
|
||||
`Terminal.DataReceived` → `IPtyConnection.WriterStream`; mirror
|
||||
`Terminal.Resized` ↔ `IPtyConnection.Resize(cols, rows)`.
|
||||
- Implement our **own** exit-code / kill / wait-for-exit against our
|
||||
`IPtyConnection` — do NOT touch `TerminalControl.ExitCode`/`Pid`/`Kill()`/
|
||||
`WaitForExit()`, they NRE on the null `_ptyConnection`.
|
||||
|
||||
Note on environment: `Porta.Pty.SpawnAsync` already seeds the child from the
|
||||
current (ClaudeDo) process environment (PATH/APPDATA/etc.) and merges
|
||||
`PtyOptions.Environment` on top — so we only need to ADD our custom vars (MCP
|
||||
config path, `MAX_THINKING_TOKENS`, …), not rebuild the whole environment. (The
|
||||
earlier spike's "child gets zero env vars" claim was wrong.)
|
||||
|
||||
### Command Center layout
|
||||
|
||||
@@ -108,10 +130,11 @@ UI:
|
||||
## Open items (implementation time)
|
||||
|
||||
- Whether `LiveSessionRegistry` is referenced outside the interactive path.
|
||||
- Exact env dictionary handed to the ConPTY control (parity with the autonomous
|
||||
run environment).
|
||||
- Session-id availability for a never-run task (no `--resume` → start fresh).
|
||||
|
||||
Resolved: env approach (see Terminal host control — add custom vars on top of the
|
||||
inherited process env via `PtyOptions.Environment`); library + binding seam.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- No screen-scraping of terminal output back into task status/diff/review.
|
||||
|
||||
Reference in New Issue
Block a user