Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions docs/developers/daemon-client-adapters/tui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# TUI Daemon Adapter Draft

## Goal

Add a flag-gated TUI transport that talks to `qwen serve` through
`DaemonSessionClient` instead of creating an in-process `Config` + agent
runtime.

This is a dogfood path for Mode B client migration. It must not replace the
default TUI path until output sinks, typed daemon events, session-scoped
permission, and lifecycle diagnostics are stable.

## Proposed Entry Point

```bash
QWEN_DAEMON_URL=http://127.0.0.1:4170 qwen --experimental-daemon-tui
```

Optional:

```bash
QWEN_DAEMON_TOKEN=... QWEN_DAEMON_WORKSPACE=/repo qwen --experimental-daemon-tui
```

The CLI should refuse this mode unless both are true:

- `QWEN_DAEMON_URL` or `--daemon-url` is set.
- `GET /capabilities` advertises `session_create`, `session_prompt`, and
`session_events`.

## Minimal Flow

1. Create `DaemonClient` with daemon URL and token.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Low — capability 校验列表与 Minimal Flow 不对齐

这里只要求 session_create / session_prompt / session_events,但 Minimal Flow 第 6-8 步用了 session.cancel() / setModel() / respondToPermission()
如果 daemon 不广告这些 capability,这些路径会在运行时静默崩。

要么补进必需 capability,要么在 doc 里说明它们可选(并解释为什么)。

2. Fetch `/capabilities`.
3. Create or attach with `DaemonSessionClient.createOrAttach()`.
4. Subscribe to `session.events()`.
5. Submit user prompts through `session.prompt()`.
6. Route cancel through `session.cancel()`.
7. Route model switch through `session.setModel()`.
8. Route permission votes through `session.respondToPermission()`.

## Rendering Contract

The first implementation adds `DaemonTuiAdapter`, a locally verifiable reducer
and transport spike. It maps only these daemon events:

| Daemon event | TUI handling |
| ---------------------------------------- | -------------------------------------------- |
| `session_update` / `agent_message_chunk` | Append assistant text |
| `session_update` / `agent_thought_chunk` | Append thinking text |
| `session_update` / `tool_call` | Show tool call lifecycle |
| `permission_request` | Show existing confirmation UI where possible |
| `permission_resolved` | Close or update confirmation UI |
| `model_switched` | Update footer/model display |
| `session_died` | Show disconnected state and stop streaming |

Unknown events must be ignored, not fatal. Typed event reducers will land in a
later protocol PR.

The adapter is not wired into the default Ink app yet. Existing interactive TUI,
JSONL, stream-json, and dual-output behavior remains unchanged.

## Explicit Non-Goals

- Do not remove the current TUI in-process runtime.
- Do not change JSONL, stream-json, or dual-output behavior in this PR.
- Do not expose file CRUD, MCP management, memory CRUD, or provider/auth
mutation through TUI yet.
- Do not make browser/web direct-to-daemon assumptions; this is terminal only.

## Merge Safety

- Default off.
- Additive code path.
- No existing CLI flags change behavior.
- If the daemon is unavailable, the experimental path fails before starting the
TUI and tells the user to run `qwen serve`.

## Validation Plan

- Unit-test event-to-TUI-state mapping with synthetic daemon events.
- Unit-test prompt, cancel, model switch, and permission vote forwarding.
- Unit-test flag/env parsing when the feature flag is wired.
- Smoke-test against a local `qwen serve`:
- prompt text streams into the TUI
- cancel resolves the active prompt
- permission request can be accepted or rejected
- reconnect sends the tracked `Last-Event-ID`

## Blockers Before Default Migration

- Typed daemon event schema.
- Session-scoped permission route.
- Output sink refactor for JSONL / stream-json / dual-output parity.
- Session lifecycle close/delete semantics.
- Runtime diagnostics for MCP, skills, providers, and workspace env.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Low — Blockers 列表缺 issue 链接

PR description 已经引用了 #4175 / #4201,doc 里都是纯文字。建议把每条 blocker 挂上对应 issue(typed daemon event schema (#XXXX) 等),方便读者跟进进度。

Loading
Loading