# Conflicts: # .agents/notes/implemented/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.i18n.yaml # .agents/notes/implemented/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.md # .agents/notes/implemented/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.zh.md # apps/web/tests/seeded-history.e2e.ts # apps/web/tests/snapshots/queue-actions/layout.expected.md # docs/core-data-structures/core.i18n.yaml # examples/acp-agent/tests/snapshots/code-mode-workspace-context/session.jsonl # examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl # examples/acp-agent/tests/snapshots/skill-load/session.jsonl # examples/acp-agent/tests/snapshots/workspace-context/session.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/headless-agent/tests/snapshots/pty-tools/session.jsonl # packages/client/runtime/README.i18n.yaml # packages/client/runtime/tests/history-fold.spec.ts # packages/client/ui-conversation/README.i18n.yaml # packages/client/ui-conversation/src/client/chat/MessageItem.tsx # packages/client/ui-conversation/tests/chat-branch-tails.spec.tsx # packages/context/workspace-context/src/index.ts # packages/context/workspace-context/tests/workspace-context.spec.ts # packages/skill/tool-skill/README.i18n.yaml # packages/skill/tool-skill/README.md # packages/skill/tool-skill/README.zh.md # packages/skill/tool-skill/src/index.ts # packages/skill/tool-skill/tests/tool-skill.spec.ts
3.5 KiB
Agent Note: Web UI drops steer entry and interjection chrome
Status: implemented
English | 中文
Problem
Mid-turn steering is a host/agent-loop capability (mode:'steer', a durable user/message). The Web product already locked the composer while a turn runs and never shipped a queue/steer menu, yet the client still threaded 'queue' | 'steer' through the input machine, conversation.send, and locale keys, and rendered consumed steering as a badged 「插话」/「Interjection」 bubble. That left a half-built UI surface: an unused submit mode, a product label for a gesture users cannot perform, and e2e goldens that pinned chrome the product does not own.
Decision
Keep host and runtime steering intact. Remove only the Web UI entry and chrome:
InputMachine/SessionInput/InputActions.submit/ hubdefaultSinkare queue-only; they always callsession.prompt(..., 'queue').ConversationService.send(text)drops its mode argument and always queues.- Durable steer content renders as a plain right-aligned bubble (no badge, no user IconActions) so external/host steers stay visible on replay.
- Delete
message.steeringlocale strings and the unused badge CSS. - The web steering e2e still POSTs
mode:'steer'over/api/session.promptand asserts durable + model-visible obedience; it no longer expects interjection chrome. Update web input machine note fact lines to match.
Alternatives considered
Delete host steering entirely. Out of scope; the user asked only for Web UI display and entry. Agent-loop drain, session events, and the wire mode remain load-bearing for ACP/TUI/automation.
Hide durable steer user/message content from the transcript. Would lie on replay when an external client steers; rejected in favor of a plain bubble.
Keep the mode parameter but only ever pass 'queue'. Leaves dead API surface and tests that invent 'steer' paths the composer cannot reach.
Consequences
- Superseded in part. Decision bullets 1 and 3 through 5 no longer describe master: composer steering shipped later, and the context-source and steer marks decision owns its caption. The current facts follow.
- Host steering ownership is unchanged: agent-loop drain, session events, and the wire mode remain load-bearing for ACP, automation, and non-Web clients.
ConversationService.send(text)still takes no mode and always queues; the composer's Steer gesture usessession.prompt(mode: 'steer')instead.- Durable steer
user/messagecontent still folds into the transcript, so an externally submitted steer stays truthful on replay. It now carries the interjection caption instead of rendering as a bare bubble. - Non-user next-step items (
agent.injectcontext: approval notices, task completion, attached snapshots) broadcast with thecontextplacement and never render as pending steering bubbles; they stay invisible until claimed as durableuser/messagecontext cards.
Testing
packages/client/ui-conversationunit/jsdom coverage: input machine enter/sink, ConversationService routing, the MessageItem steering arm, InputBar submit.apps/web/tests/steering.e2e.tskeyless replay plus its goldens, which pin the caption.packages/host/apiproxysession/queueprojection test asserts user-origin next-step items staysteeringwhile plugin-origin items land ascontext.