Skip to content

feat(web): adapt Web UI for Wire 1.6 subagent and approval changes - #1555

Merged
RealKai42 merged 3 commits into
mainfrom
kaiyi/warsaw
Mar 23, 2026
Merged

feat(web): adapt Web UI for Wire 1.6 subagent and approval changes#1555
RealKai42 merged 3 commits into
mainfrom
kaiyi/warsaw

Conversation

@RealKai42

@RealKai42 RealKai42 commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adapts the Web UI to support the Wire protocol 1.6 changes introduced by #1552 (unified subagent execution, approvals, and tracing).

Wire protocol alignment

  • SubagentEvent: Rename task_tool_call_idparent_tool_call_id, add agent_id and subagent_type fields with backward-compatible fallback for legacy wire.jsonl replay
  • ApprovalRequest: Add source_kind, source_id, agent_id, subagent_type, source_description, and display fields
  • ApprovalResponse: Send feedback field when rejecting; read it back on replay via ApprovalRequestResolved

New capabilities

  • Reject with feedback: Add a 4th approval option "Decline with feedback" with inline textarea, IME-safe Enter handling, and keyboard shortcut (4). Feedback flows through the full chain to the backend feedback wire field.
  • Approval display blocks: Thread ApprovalRequest.display (diffs, shell commands) onto toolCall.display so users can preview what they are approving instead of acting blind.
  • Subagent type labels: Show the built-in type (Coder agent, Explore agent, Plan agent) in SubagentActivity headers and in sub-agent origin tool cards.

Sub-agent approval rendering fix

  • When sub-agent tools need approval, the backend forwards ApprovalRequest directly to the root wire (not wrapped in SubagentEvent). Previously, the Web UI created phantom tool-call cards in the main timeline indistinguishable from the root agent's own tool calls.
  • Now, phantom messages from sub-agent approvals are marked with isSubagentOrigin and rendered with a left-border indent + source label (e.g. coder agent) to visually separate them from the root agent's tool calls.

Source badge in approval dialog

  • Build source labels from subagent_type + agent_id with fallback chain: source_description → type + ID (e.g. Background · coder (a1f3e8b2)) → generic label.

Changed files

  • web/src/hooks/wireTypes.ts — Wire 1.6 type definitions
  • web/src/hooks/types.ts — LiveMessage type extensions
  • web/src/hooks/useSessionStream.ts — Event handling for SubagentEvent, ApprovalRequest, ApprovalRequestResolved, respondToApproval
  • web/src/features/chat/components/approval-dialog.tsx — Feedback input, source badge, IME guard
  • web/src/features/chat/chat.tsx — Thread reason param through approval action handlers
  • web/src/components/ai-elements/subagent-steps.tsx — Subagent type label in activity header
  • web/src/features/chat/components/assistant-message.tsx — Sub-agent origin visual treatment, pass subagentType to SubagentActivity

Test plan

  • Verify subagent steps render inside parent Agent tool card (not as top-level phantom cards)
  • Verify sub-agent approval cards show left-border indent + source label
  • Test "Decline with feedback" flow: click button 4 → type feedback → Enter submits → feedback appears in wire response
  • Test IME input in feedback textarea (Chinese input should not trigger early submit)
  • Verify approval display blocks (diffs/commands) appear in approval dialog
  • Reload page and verify rejection feedback text persists (not lost on replay)
  • Test keyboard shortcuts 1/2/3/4 and Escape in approval dialog

Open with Devin

Copilot AI review requested due to automatic review settings March 23, 2026 15:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates the Web UI to align with Wire protocol 1.6 changes (subagent tracing + approvals), and improves the approval UX by adding “decline with feedback”, source labeling, and approval preview display blocks.

Changes:

  • Extend wire and UI message types to support Wire 1.6 fields (subagent metadata, approval sources, approval feedback, display blocks).
  • Update session stream event handling for SubagentEvent, ApprovalRequest, and ApprovalRequestResolved, including legacy replay fallbacks.
  • Enhance approval and tool rendering: feedback textarea + shortcuts, source badge/indent for sub-agent-origin approvals, and subagent type labels in activity headers.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
web/src/hooks/wireTypes.ts Adds Wire 1.6 fields for approvals and subagent events; extends tool approval state.
web/src/hooks/types.ts Extends LiveMessage/tool call shape with feedback, approval source metadata, and subagent identity/origin flags.
web/src/hooks/useSessionStream.ts Implements Wire 1.6 event processing and fallback behavior; threads approval display blocks and rejection feedback through the pipeline.
web/src/features/chat/components/approval-dialog.tsx Adds “Decline with feedback” flow (textarea, IME-safe Enter, shortcuts) and source badge rendering.
web/src/features/chat/chat.tsx Threads optional rejection reason/feedback through approval action handlers to the stream hook.
web/src/components/ai-elements/subagent-steps.tsx Displays subagent type label (“Coder agent”, etc.) in subagent activity header text.
web/src/features/chat/components/assistant-message.tsx Visually demotes sub-agent-origin approval/tool cards and passes subagentType down to activity rendering.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 2233 to 2239
result: {
request_id: pending.requestId ?? requestId,
response,
...(response === "reject" && trimmedReason
? { feedback: trimmedReason }
: {}),
},

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

respondToApproval conditionally sends feedback in the JSON-RPC response, but the local optimistic updatedApproval state update below still only updates reason/response. To keep the UI state consistent with what’s sent over the wire (and with the new feedback field), also populate updatedApproval.feedback when rejecting with feedback so the value is available immediately without waiting for ApprovalRequestResolved.

Copilot uses AI. Check for mistakes.
Comment on lines +1706 to +1708
const parentToolCallId =
subPayload.parent_tool_call_id ??
(subPayload as Record<string, unknown>).task_tool_call_id as string | undefined;

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

The legacy fallback for task_tool_call_id relies on a chained as cast in the nullish coalescing expression. For readability and to avoid any TS precedence confusion, wrap the cast in parentheses and consider validating that the legacy value is actually a string before using it (e.g., typeof legacy === 'string').

Suggested change
const parentToolCallId =
subPayload.parent_tool_call_id ??
(subPayload as Record<string, unknown>).task_tool_call_id as string | undefined;
const legacyTaskToolCallId = (subPayload as Record<string, unknown>).task_tool_call_id;
const parentToolCallId =
subPayload.parent_tool_call_id ??
(typeof legacyTaskToolCallId === "string" ? legacyTaskToolCallId : undefined);

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +59
if (prevApprovalIdRef.current !== currentApprovalId) {
prevApprovalIdRef.current = currentApprovalId;
// Always clear stale feedback text, not just when feedbackMode is active.
// Otherwise old text leaks into the next approval's feedback input.
if (feedbackMode || feedbackText) {
setFeedbackMode(false);
setFeedbackText("");
}
}

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

State is being updated during render (if (prevApprovalIdRef.current !== currentApprovalId) { ... setFeedbackMode/setFeedbackText ... }). Updating state while rendering can trigger React warnings and render loops (especially under StrictMode). Move this reset logic into a useEffect that runs when currentApprovalId changes (and clear feedback state there).

Suggested change
if (prevApprovalIdRef.current !== currentApprovalId) {
prevApprovalIdRef.current = currentApprovalId;
// Always clear stale feedback text, not just when feedbackMode is active.
// Otherwise old text leaks into the next approval's feedback input.
if (feedbackMode || feedbackText) {
setFeedbackMode(false);
setFeedbackText("");
}
}
useEffect(() => {
if (prevApprovalIdRef.current !== currentApprovalId) {
prevApprovalIdRef.current = currentApprovalId;
// Always clear stale feedback text, not just when feedbackMode is active.
// Otherwise old text leaks into the next approval's feedback input.
setFeedbackMode(false);
setFeedbackText("");
}
}, [currentApprovalId]);

Copilot uses AI. Check for mistakes.
submitted: true,
approved,
reason: reason ?? approval.reason,
reason: effectiveReason,

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

ApprovalRequestResolved now includes a feedback field, but the updated approval state only folds it into reason and never stores it in updatedApproval.feedback. Since ToolApprovalState/LiveMessage now include feedback, consider persisting it separately (e.g., feedback: feedback ?? approval.feedback) so replay and future UI can distinguish structured feedback from generic reasons.

Suggested change
reason: effectiveReason,
reason: effectiveReason,
feedback: feedback ?? approval.feedback,

Copilot uses AI. Check for mistakes.
@RealKai42
RealKai42 merged commit 934b704 into main Mar 23, 2026
14 checks passed
@RealKai42
RealKai42 deleted the kaiyi/warsaw branch March 23, 2026 15:21

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 5 potential issues.

View 4 additional findings in Devin Review.

Open in Devin Review

Comment thread CHANGELOG.md
- Web: Improve Switch toggle proportions and alignment — the toggle track is now larger (36×20) with a consistent 16px thumb and smoother 16px travel animation
- Web: Show subagent type labels in activity panels — subagent activities now display their type (e.g. "Coder agent working") instead of the generic "Agent" label
- Web: Add feedback mode to approval dialog — press `4` to reject with written feedback text that guides the model's next attempt; approval requests from subagents show a source label and preview content (diffs, commands)
- Web: Visually distinguish sub-agent origin tool calls — tool messages originating from a subagent are rendered with a left border and a source type label for clearer attribution

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 CHANGELOG uses "sub-agent" instead of "subagent" violating docs/AGENTS.md term mapping

The docs/AGENTS.md term mapping table specifies that the English term for 子 Agent is "subagent" (no hyphen). This line uses "sub-agent" (hyphenated) in the title while correctly using "subagent" in the body, creating an inconsistency. The root CHANGELOG.md is auto-synced to docs/en/release-notes/changelog.md:24, so both files are affected.

Suggested change
- Web: Visually distinguish sub-agent origin tool calls — tool messages originating from a subagent are rendered with a left border and a source type label for clearer attribution
- Web: Visually distinguish subagent origin tool calls — tool messages originating from a subagent are rendered with a left border and a source type label for clearer attribution
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

### 数字键快速选择

在审批面板中,按 `1`–`3` 可以直接选中并提交对应的审批选项,无需先用方向键选择再按 `Enter`。
在审批面板中,按 `1`–`3` 可以直接选中并提交对应的审批选项,无需先用方向键选择再按 `Enter`。按 `4` 进入反馈模式,输入拒绝原因后按 Enter 提交,反馈文本会传递给 Agent 以指导下一次尝试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Missing backticks around "Enter" keyboard shortcut in Chinese keyboard reference

The docs/AGENTS.md naming conventions require backticks for keyboard shortcuts. The second occurrence of "Enter" on this line is not backtick-formatted (按 Enter 提交), while the first occurrence (按 \Enter`) and all existing references in the file (e.g. docs/zh/reference/keyboard.md:64`) correctly use backticks.

Suggested change
在审批面板中,按 `1``3` 可以直接选中并提交对应的审批选项,无需先用方向键选择再按 `Enter`。按 `4` 进入反馈模式,输入拒绝原因后按 Enter 提交,反馈文本会传递给 Agent 以指导下一次尝试。
在审批面板中,按 `1``3` 可以直接选中并提交对应的审批选项,无需先用方向键选择再按 `Enter`。按 `4` 进入反馈模式,输入拒绝原因后按 `Enter` 提交,反馈文本会传递给 Agent 以指导下一次尝试。
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

### Number key quick selection

In the approval panel, press `1`–`3` to directly select and submit the corresponding approval option without navigating with arrow keys first.
In the approval panel, press `1`–`3` to directly select and submit the corresponding approval option without navigating with arrow keys first. Press `4` to enter feedback mode, where you can type a reason for declining and press Enter to submit; the feedback text is passed to the agent to guide its next attempt.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Missing backticks around "Enter" keyboard shortcut in English keyboard reference

The docs/AGENTS.md naming conventions require backticks for keyboard shortcuts. "Enter" in press Enter to submit is not backtick-formatted, while all existing references in the file (e.g. docs/en/reference/keyboard.md:64) correctly use backticks.

Suggested change
In the approval panel, press `1``3` to directly select and submit the corresponding approval option without navigating with arrow keys first. Press `4` to enter feedback mode, where you can type a reason for declining and press Enter to submit; the feedback text is passed to the agent to guide its next attempt.
In the approval panel, press `1``3` to directly select and submit the corresponding approval option without navigating with arrow keys first. Press `4` to enter feedback mode, where you can type a reason for declining and press `Enter` to submit; the feedback text is passed to the agent to guide its next attempt.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

| `3` | Decline |
| `4` | Decline with feedback |

Press `4` to enter feedback mode, where you can type a reason for declining or instructions on how the agent should adjust, then press Enter to submit. The feedback text is passed to the agent to guide its next attempt.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Missing backticks around "Enter" keyboard shortcut in English Web UI reference

The docs/AGENTS.md naming conventions require backticks for keyboard shortcuts. "Enter" in then press Enter to submit is not backtick-formatted. Existing text elsewhere in the docs (e.g. docs/en/guides/interaction.md:110: press \Enter``) consistently uses backticks for this shortcut.

Suggested change
Press `4` to enter feedback mode, where you can type a reason for declining or instructions on how the agent should adjust, then press Enter to submit. The feedback text is passed to the agent to guide its next attempt.
Press `4` to enter feedback mode, where you can type a reason for declining or instructions on how the agent should adjust, then press `Enter` to submit. The feedback text is passed to the agent to guide its next attempt.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

| `3` | 拒绝 |
| `4` | 附带反馈拒绝 |

按 `4` 进入反馈模式后,可以输入文字说明拒绝的原因或期望 Agent 如何调整,然后按 Enter 提交。反馈文本会传递给 Agent 以指导下一次尝试。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Missing backticks around "Enter" keyboard shortcut in Chinese Web UI reference

The docs/AGENTS.md naming conventions require backticks for keyboard shortcuts. "Enter" in 按 Enter 提交 is not backtick-formatted, inconsistent with the same file's existing convention (e.g. docs/zh/reference/keyboard.md:64: 按 \Enter``).

Suggested change
`4` 进入反馈模式后,可以输入文字说明拒绝的原因或期望 Agent 如何调整,然后按 Enter 提交。反馈文本会传递给 Agent 以指导下一次尝试。
`4` 进入反馈模式后,可以输入文字说明拒绝的原因或期望 Agent 如何调整,然后按 `Enter` 提交。反馈文本会传递给 Agent 以指导下一次尝试。
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants