Skip to content

Work-tab UI overhaul + ADE Code subagent/render parity#534

Merged
arul28 merged 8 commits into
mainfrom
work-tab-ui-overhaul-21eb87d5
Jun 6, 2026
Merged

Work-tab UI overhaul + ADE Code subagent/render parity#534
arul28 merged 8 commits into
mainfrom
work-tab-ui-overhaul-21eb87d5

Conversation

@arul28

@arul28 arul28 commented Jun 6, 2026

Copy link
Copy Markdown
Owner

What

  • Work-tab UI overhaul (Cursor-style work tab, cleaner panes, animations) — replaces the old WorkViewMode tabs/grid.
  • ADE Code (TUI) subagent parity: capability-gated subagent pane (Codex/OpenCode real-transcript takeover; Cursor/Droid inline detail), per-runtime stat chips, Droid Missions + ^k kill-worker, once-per-session auto-open; killDroidWorker allowlisted.
  • TUI render fixes: identity-aware delta coalescing (interleaved messages no longer scramble), codex-subagent: filtered from the parent transcript, per-message flood coalescing (flicker), chat right gutter, distinct synthetic-transcript line ids, desktop terminal integer fontSize + minimumContrastRatio (fixes WebGL dashed box-drawing / crowded glyphs).

Merge with main

Reconciled origin/main (PRs-tab overhaul, remote-runtime hardening, agent bootstrap, iOS sim): the overhaul wins the work-tab grid; main's remote-runtime hardening is preserved (remote poll intervals, remote-PR handling, remote browser-sidebar guard, projectBinding/selectActiveProjectRoot).

Tests

Lane-blast-radius green locally: ade-cli 571, desktop chat 515 + work-tab/lanes/settings/files/app/main-services 1272; both packages typecheck clean. Chat-test suites aligned to the overhaul's new copy/structure.

🤖 Generated with Claude Code

Open in Capy

Greptile Summary

This PR delivers a Cursor-style work-tab overhaul (single-focused session with DnD grid formation), ADE Code TUI subagent/render parity (identity-aware delta coalescing, real child-transcript takeover, per-runtime stat chips, ^k kill-worker), and Droid AGI mission support. It also cleans up dead code (codexCliLauncher, codexOpenInCli, WorkViewMode), reconciles remote-runtime hardening from main, and fixes TUI render artefacts (integer fontSize, WebGL glyph crowding, chat right gutter).

  • Work-tab UI: replaces the viewMode: "tabs"|"grid" toggle with a WorkGridSet[] model; sessions join grids via DnD and are rendered in WorkGridView/PaneTilingLayout; grid membership normalisation drops sub-2-member sets and deduplicates cross-set membership on load.
  • Subagent parity: new subagentCapabilities.ts single source of truth gates takeover vs. inline drawer; buildSubagentEventHistory expands Anthropic message blocks into typed events; coalesceTextDeltaEnvelopes in assistantTextIdentity.ts is shared by both the buffer-level and render-line coalescers so concurrent parent+child deltas no longer scramble.
  • Droid AGI: toDroidInteractionMode maps the new "agi" permission mode; killWorker exposes ^k worker termination (via the _client shim already noted); droidSdkEventMapper maps mission lifecycle events to mission_state/features/progress envelopes consumed by chatMission.ts and MissionControlPanel.

Confidence Score: 5/5

  • Safe to merge; both findings are narrow edge cases in the subagent transcript coalescer that would not affect normal sessions.
  • The work-tab grid, identity-aware delta coalescing, and Droid AGI mission path are all well-guarded and tested. The two comments flag optional field concatenation in mergeAdjacentSubagentEvents (only reachable for streaming command/file-change events in a subagent view) and a missing try/catch around a JSON.stringify fallback key — both produce visible artefacts only in specific, low-frequency scenarios and neither causes data loss or session corruption.
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx (command/file_change output concatenation) and apps/desktop/src/main/services/chat/agentChatService.ts (JSON.stringify fallback key).

Important Files Changed

Filename Overview
apps/desktop/src/main/services/chat/agentChatService.ts Large addition: Codex subagent thread state tracking, killDroidWorker, mergeSubagentTranscriptMessages, identity-aware delta coalescing, and parent-visible event filtering. Minor: JSON.stringify without try/catch in fallback dedup key.
apps/desktop/src/renderer/components/chat/AgentChatPane.tsx Major expansion: new subagent transcript expansion/coalescing, Droid worker kill, mission control panel integration, and buildSubagentEventHistory. Template literals on optional output/diff fields may emit "undefined" prefix for streaming command/file_change events.
apps/desktop/src/shared/subagentCapabilities.ts New module: per-runtime subagent capability descriptor. Clean single-source-of-truth design; all runtime keys match their provider strings so renderer-vs-service parity holds for current runtimes.
apps/desktop/src/main/services/chat/droidSdkWorker.ts Adds killWorker via private _client._client bypass (already noted in a prior review thread), AGI interaction mode mapping, and mission-proposal permission rendering. The _client coupling concern stands but is unchanged by this review cycle.
apps/ade-cli/src/tuiClient/assistantTextIdentity.ts New module: shared identity logic for coalescing streamed assistant text deltas. Well-structured; eliminates the duplicated merge predicates that caused interleaved messages to scramble.
apps/desktop/src/renderer/lib/workGrid.ts New module: pure helpers for Cursor-style work grids (add/remove sessions, DnD MIME type). The no-op branch in addSessionBesideTarget returns a fabricated gridSetId not present in the output, but all callers guard against sessionId === targetSessionId before calling.
apps/desktop/src/renderer/state/appStore.ts Replaces viewMode with WorkGridSet[]/activeGridSetId, adds userOverrodeChatFontSize flag, and integer terminal fontSize. Normalisation is thorough: deduplicates grid membership, drops sub-2-member sets.
apps/desktop/src/shared/types/chat.ts Adds Droid AGI mission event types, AgentChatKillDroidWorkerArgs, AgentChatDroidPermissionMode "agi" variant, reasoningTokens/contextWindow on done events, and SubagentCapability on session capabilities.
apps/desktop/src/renderer/components/chat/chatMission.ts New module: derives MissionSnapshot from the event stream by taking the latest of each full-replacement mission event type. Clean design; correctly handles full-replace semantics.
apps/desktop/src/renderer/components/terminals/WorkGridView.tsx New component: Cursor-style resizable split-pane grid and single-session DnD drop zone. Drop-edge detection defers to detectDropEdge; overlay rendering with live edge preview looks correct.
apps/desktop/src/renderer/components/chat/usage/contextUsageModel.ts New provider-agnostic context-usage view-model. Clean separation of Codex vs generic occupancy math; returns null when no meaningful data is available, preserving existing hide-when-empty behaviour.

Sequence Diagram

sequenceDiagram
    participant SDK as Codex/Droid/Cursor SDK
    participant SVC as agentChatService
    participant IPC as registerIpc / preload
    participant REND as AgentChatPane (renderer)
    participant TUI as AdeCodeApp (TUI)

    SDK->>SVC: subagent_started / turn events
    SVC->>SVC: registerCodexSubagentThread()
    SVC->>SVC: "recordCodexSubagentTranscriptMessages()<br/>(dedup via transcriptKeys Set)"
    SVC->>SVC: "writeTranscript() → persisted JSONL<br/>provenance.targetKind=codex_subagent"

    REND->>IPC: "getSubagentTranscript({ sessionId, agentId })"
    IPC->>SVC: getSubagentTranscript()
    SVC->>SVC: "merge captured + live transcripts<br/>mergeSubagentTranscriptMessages()"
    SVC-->>REND: AgentChatSubagentTranscriptMessage[]

    REND->>REND: "eventsFromSubagentTranscriptMessage()<br/>expand Anthropic blocks → typed events"
    REND->>REND: "buildSubagentEventHistory()<br/>completedKeys filter + coalesceSubagentEventEnvelopes()"
    REND->>REND: "AgentChatMessageList renders<br/>subagent transcript as takeover view"

    TUI->>IPC: "getSubagentTranscript({ sessionId, agentId })"
    IPC-->>TUI: AgentChatSubagentTranscriptMessage[]
    TUI->>TUI: "subagentTranscriptMessagesToEvents()<br/>→ setRealSubagentTranscript"

    SDK->>SVC: Droid mission_state_changed / features / progress
    SVC->>SVC: droidSdkEventMapper → mission_state/features/progress envelopes
    REND->>REND: "deriveMissionSnapshot(events)<br/>→ MissionControlPanel"

    REND->>IPC: "killDroidWorker({ sessionId, workerSessionId })"
    IPC->>SVC: killDroidWorker()
    SVC->>SVC: "runtime.sdk.killWorker(workerSessionId)<br/>(via _client shim)"
Loading

Comments Outside Diff (1)

  1. apps/desktop/src/main/services/chat/agentChatService.ts, line 6629-6655 (link)

    P2 truncated: true false-positive when subagent envelopes dominate the response cap

    mergedLengthBeforeResponseCap > CHAT_EVENT_HISTORY_RESPONSE_MAX_PER_SESSION counts ALL envelopes (parent + codex-subagent). A session with 1 000 parent events and 8 000 subagent events would have mergedLengthBeforeResponseCap = 9000 > cap, so windowTruncated = true. But windowed is parentVisibleMerged — which contains all 1 000 parent events. The caller receives a complete parent-visible set yet sees truncated: true, so any "load older history" prompt or truncation warning fires spuriously.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/main/services/chat/agentChatService.ts
    Line: 6629-6655
    
    Comment:
    **`truncated: true` false-positive when subagent envelopes dominate the response cap**
    
    `mergedLengthBeforeResponseCap > CHAT_EVENT_HISTORY_RESPONSE_MAX_PER_SESSION` counts ALL envelopes (parent + codex-subagent). A session with 1 000 parent events and 8 000 subagent events would have `mergedLengthBeforeResponseCap = 9000 > cap`, so `windowTruncated = true`. But `windowed` is `parentVisibleMerged` — which contains all 1 000 parent events. The caller receives a complete parent-visible set yet sees `truncated: true`, so any "load older history" prompt or truncation warning fires spuriously.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/desktop/src/renderer/components/chat/AgentChatPane.tsx:469-476
Template literals stringify `undefined` as the literal string `"undefined"`. `AgentChatEvent`'s `command.output` and `file_change.diff` are both optional (`string | undefined`). If either field is absent on a "running" entry, the coalesced output/diff will begin with the four-character prefix `"undefined"`, which renders verbatim in the subagent transcript view.

```suggestion
  if (left.type === "command" && right.type === "command") {
    if (right.status !== "running") return right;
    return { ...right, output: `${left.output ?? ""}${right.output ?? ""}` };
  }
  if (left.type === "file_change" && right.type === "file_change") {
    if (right.status && right.status !== "running") return right;
    return { ...right, diff: `${left.diff ?? ""}${right.diff ?? ""}` };
  }
```

### Issue 2 of 2
apps/desktop/src/main/services/chat/agentChatService.ts:24964
`JSON.stringify` is called in the fallback key path without a try/catch. While IPC-sourced `AgentChatEvent` objects are almost always JSON-safe, SDK data could theoretically carry circular references or non-serialisable values (e.g. `BigInt`). A throw here propagates out of `mergeSubagentTranscriptMessages` and surfaces as a failed `getSubagentTranscript` call, silently leaving the subagent pane empty.

```suggestion
      let jsonFallback = "";
      try { jsonFallback = JSON.stringify(message.message); } catch { /* non-serialisable payload */ }
      const key = message.uuid || `${message.sessionId}:${message.type}:${message.text ?? jsonFallback}`;
```

Reviews (2): Last reviewed commit: "ship: fix react-hooks/rules-of-hooks lin..." | Re-trigger Greptile

arul28 and others added 7 commits June 5, 2026 04:38
Major overhaul of the Work-tab chat surface across all runtimes.

Layout & navigation
- Removed the entire tabs/grid top bar and the viewMode concept app-wide;
  WorkViewArea shrank ~2278→1207 lines (legacy preset grid, tab strip,
  WorkGlassHeader, ArrangeMenu, ViewModeToggle all deleted).
- Per-surface header now owns the sessions toggle (far left) + Tools toggle
  (far right, purple glyph) for both chat and CLI.
- New Cursor-style drag grid: drag a session card from the sidebar onto a
  chat/CLI to split at the hovered edge; resize, rearrange, drag-out to single
  view, right-click remove-from-grid; multiple grid sets; sidebar grid badge
  (active set highlighted). New WorkGridView + lib/workGrid + grid-set state.

Panes
- Chat-actions + PR floating panes: neutral sidebar-colored background (no
  purple), compact, smaller width, chat recenters on normal screens.
- Chat-actions tabs restyled neutral with an animated sliding violet underline
  (GlowMenu neutral mode); Run moved to a 4th tab rendered inline.
- Subagent cards redesigned: compact rows with per-agent geometric glyphs
  (no childish purple boxes). Subagent takeover only when there's content.
- New inline PR creator in the PR pane (no leaving the Work tab).

Transcript & composer
- Unbubbled assistant text, flat lighter canvas (#0f0f11), 14px prose, no
  scrollbar, clean turn dividers (time · worked-for), interrupted text-only.
- Removed composer BorderBeam + white border; relocated clipboard notice.
- Nuked the Codex "Open in CLI" button + its entire cross-process plumbing.

Animations
- Smooth lane-collapse, floating-pane fades, Tools-sidebar fade, iMessage-style
  message send-up, and a blur-dissolve when the new-chat pane becomes the chat.

Gates: typecheck PASS, lint PASS (warnings only), desktop build PASS.
Known: 11 renderer tests assert pre-overhaul UI text (turn-divider rollup,
draft-launch banner wording) — assertion drift to reconcile in a follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chat UI (Work tab):
- CLI ended-session view: chat-canvas bg, one-line green Resume header, model
  pill, round send button, thinner auto-grow continuation composer
- PR floating pane: header/X removed, 2-line locked lane+branch source +
  LaneCombobox target dropdown, bold accent, "Open in PRs tab"; AI draft now
  runs on the chat's model via the pr_descriptions background job and surfaces
  real errors (requireAi)
- Context-usage circular dial across all runtimes (registry context-window
  fallback) with force-enabled hover breakdown; replaces the Codex-only strip
- Floating panes fade in place; chat reserves to make room (no overlap)
- User-message minimap bounded to the chat column; chat column widened to 52rem

Also includes in-progress Codex subagent transcript metadata work
(agentChatService, adeActions registry, ade-cli bootstrap, docs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Subagent pane parity for the 4 shared runtimes (Codex/Cursor/Droid/OpenCode):
- Capability-gated subagent rows (resolveSubagentCapability): Codex/OpenCode
  take over with the real daemon transcript (getSubagentTranscript, fallback to
  local reconstruction); Cursor/Droid show inline detail (no takeover).
- Per-runtime stat chips (tokens/tool-uses/cost), Droid Missions section +
  ^k kill-worker, once-per-session auto-open on first subagent.
- Backend: allowlist killDroidWorker; widen SubagentSnapshot (toolUses/costUsd).

Render fixes:
- Identity-aware coalesceLines + shared assistantTextIdentity predicate so
  interleaved concurrent messages don't scramble; filter codex-subagent: text
  from the parent transcript (mirror desktop).
- Coalesce streamed text deltas before React state + flush interval 24->48ms to
  cut the per-token re-aggregate/re-wrap flood (flicker/layout-shift).
- Distinct itemId per synthetic takeover-transcript line so they don't fuse into
  one separator-less blob.
- Chat right gutter so prose doesn't hug the right pane.
- Desktop terminal: integer fontSize (12.5->13) + minimumContrastRatio so the
  xterm.js WebGL renderer stops crowding glyphs / dashing box-drawing borders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… remote-runtime hardening

- Old work-tab grid (WorkViewMode/viewMode) dropped — replaced by this lane's
  work-tab overhaul (WorkGridView/workGrid).
- Kept main's remote-runtime hardening: remote session polling intervals
  (useWorkSessions), remote-PR handling (ChatGitToolbar), remote delta-skip
  (SessionCard), remote browser-sidebar guard (TerminalsPage), projectBinding/
  selectActiveProjectRoot.
- Deduped getSubagentTranscript in the chat action allowlist; restored
  selectActiveProjectRoot imports the auto-merged bodies needed; restored lane
  test versions where they assert the overhaul's API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ruth)

The overhaul intentionally changed UI copy/structure; these tests still asserted
pre-overhaul behavior. Aligned the tests to the overhaul (kept the new impl):
- Draft-launch notice: 'Message sent: "<prompt>"', 'View' button, 'Dismiss
  launch status' (AgentChatPane.test, 7 tests).
- Composer clipboard hint moved + reworded to 'Prompt copies to clipboard on
  send.' (AgentChatComposer.test, 2 tests).
- End-of-turn divider restructured: 'Task list' rollup (was 'Response'), calmer
  completed footer (model attribution now on interrupted/failed turns), agents
  moved to the subagent pane (AgentChatMessageList.test, 4 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- TerminalView: fontSize now rounded to integer (12.5→13) for the WebGL
  box-drawing/glyph fix.
- App.workKeepAlive: revealWorkBrowser no longer sets the removed work-tab
  viewMode; just opens the browser sidebar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mintlify

mintlify Bot commented Jun 6, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
ade-ac1c6011 🟢 Ready View Preview Jun 6, 2026, 11:07 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@arul28, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 20 minutes and 27 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 50a44fa4-a933-4ee5-beb3-17dca4782159

📥 Commits

Reviewing files that changed from the base of the PR and between f860825 and bbc5922.

⛔ Files ignored due to path filters (3)
  • CONTRIBUTING.md is excluded by !*.md
  • README.md is excluded by !*.md
  • docs/features/chat/README.md is excluded by !docs/**
📒 Files selected for processing (105)
  • apps/ade-cli/src/bootstrap.ts
  • apps/ade-cli/src/tuiClient/__tests__/RightPane.test.tsx
  • apps/ade-cli/src/tuiClient/__tests__/appInput.test.ts
  • apps/ade-cli/src/tuiClient/__tests__/assistantTextIdentity.test.ts
  • apps/ade-cli/src/tuiClient/__tests__/format.test.ts
  • apps/ade-cli/src/tuiClient/__tests__/subagentPane.test.ts
  • apps/ade-cli/src/tuiClient/adeApi.ts
  • apps/ade-cli/src/tuiClient/aggregate.ts
  • apps/ade-cli/src/tuiClient/app.tsx
  • apps/ade-cli/src/tuiClient/assistantTextIdentity.ts
  • apps/ade-cli/src/tuiClient/chatInfo.ts
  • apps/ade-cli/src/tuiClient/components/RightPane.tsx
  • apps/ade-cli/src/tuiClient/format.ts
  • apps/ade-cli/src/tuiClient/subagentPane.ts
  • apps/ade-cli/src/tuiClient/types.ts
  • apps/desktop/README.md
  • apps/desktop/src/main/services/adeActions/registry.test.ts
  • apps/desktop/src/main/services/adeActions/registry.ts
  • apps/desktop/src/main/services/chat/agentChatService.test.ts
  • apps/desktop/src/main/services/chat/agentChatService.ts
  • apps/desktop/src/main/services/chat/codexCliLauncher.test.ts
  • apps/desktop/src/main/services/chat/codexCliLauncher.ts
  • apps/desktop/src/main/services/chat/cursorSdkEventMapper.ts
  • apps/desktop/src/main/services/chat/droidSdkEventMapper.test.ts
  • apps/desktop/src/main/services/chat/droidSdkEventMapper.ts
  • apps/desktop/src/main/services/chat/droidSdkPool.ts
  • apps/desktop/src/main/services/chat/droidSdkProtocol.ts
  • apps/desktop/src/main/services/chat/droidSdkWorker.ts
  • apps/desktop/src/main/services/ipc/registerIpc.ts
  • apps/desktop/src/main/services/ipc/runtimeBridge.test.ts
  • apps/desktop/src/main/services/prs/prService.ts
  • apps/desktop/src/main/services/remoteRuntime/remoteConnectionPool.test.ts
  • apps/desktop/src/preload/global.d.ts
  • apps/desktop/src/preload/preload.test.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/browserMock.ts
  • apps/desktop/src/renderer/components/app/App.tsx
  • apps/desktop/src/renderer/components/app/App.workKeepAlive.test.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatComposer.test.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatComposer.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatMessageList.test.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatMessageList.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatPane.test.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx
  • apps/desktop/src/renderer/components/chat/ChatActionsDrawerPanel.tsx
  • apps/desktop/src/renderer/components/chat/ChatComposerShell.tsx
  • apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx
  • apps/desktop/src/renderer/components/chat/ChatPrInlineCreator.tsx
  • apps/desktop/src/renderer/components/chat/ChatPrPane.tsx
  • apps/desktop/src/renderer/components/chat/ChatSubagentsPanel.test.tsx
  • apps/desktop/src/renderer/components/chat/ChatSubagentsPanel.tsx
  • apps/desktop/src/renderer/components/chat/ChatSurfaceShell.tsx
  • apps/desktop/src/renderer/components/chat/CodeHighlighter.tsx
  • apps/desktop/src/renderer/components/chat/MissionControlPanel.tsx
  • apps/desktop/src/renderer/components/chat/chatAppearance.ts
  • apps/desktop/src/renderer/components/chat/chatExecutionSummary.ts
  • apps/desktop/src/renderer/components/chat/chatMarkdown.tsx
  • apps/desktop/src/renderer/components/chat/chatMission.test.ts
  • apps/desktop/src/renderer/components/chat/chatMission.ts
  • apps/desktop/src/renderer/components/chat/chatSurfaceTheme.ts
  • apps/desktop/src/renderer/components/chat/codex/CodexOpenInCliButton.tsx
  • apps/desktop/src/renderer/components/chat/codex/CodexTokenInline.tsx
  • apps/desktop/src/renderer/components/chat/usage/ContextUsageDial.test.tsx
  • apps/desktop/src/renderer/components/chat/usage/ContextUsageDial.tsx
  • apps/desktop/src/renderer/components/chat/usage/contextUsageModel.test.ts
  • apps/desktop/src/renderer/components/chat/usage/contextUsageModel.ts
  • apps/desktop/src/renderer/components/files/v2/FilesWorkbench.tsx
  • apps/desktop/src/renderer/components/lanes/LaneWorkPane.tsx
  • apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.test.ts
  • apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts
  • apps/desktop/src/renderer/components/run/QuickRunMenu.tsx
  • apps/desktop/src/renderer/components/settings/AppearanceSection.tsx
  • apps/desktop/src/renderer/components/settings/ChatAppearancePreview.test.tsx
  • apps/desktop/src/renderer/components/settings/ChatAppearancePreview.tsx
  • apps/desktop/src/renderer/components/terminals/CliSessionWorkSurfaceHeader.tsx
  • apps/desktop/src/renderer/components/terminals/SessionCard.test.tsx
  • apps/desktop/src/renderer/components/terminals/SessionCard.tsx
  • apps/desktop/src/renderer/components/terminals/SessionContextMenu.tsx
  • apps/desktop/src/renderer/components/terminals/SessionListPane.test.tsx
  • apps/desktop/src/renderer/components/terminals/SessionListPane.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalView.test.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalView.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalsPage.test.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalsPage.tsx
  • apps/desktop/src/renderer/components/terminals/WorkGridView.tsx
  • apps/desktop/src/renderer/components/terminals/WorkStartSurface.tsx
  • apps/desktop/src/renderer/components/terminals/WorkViewArea.test.tsx
  • apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.ts
  • apps/desktop/src/renderer/components/ui/FloatingPane.tsx
  • apps/desktop/src/renderer/components/ui/GlowMenu.tsx
  • apps/desktop/src/renderer/components/ui/PaneTilingLayout.tsx
  • apps/desktop/src/renderer/components/work/WorkSurfaceHeader.tsx
  • apps/desktop/src/renderer/index.css
  • apps/desktop/src/renderer/lib/workGrid.ts
  • apps/desktop/src/renderer/main.tsx
  • apps/desktop/src/renderer/state/appStore.test.ts
  • apps/desktop/src/renderer/state/appStore.ts
  • apps/desktop/src/shared/chatSubagents.ts
  • apps/desktop/src/shared/ipc.ts
  • apps/desktop/src/shared/subagentCapabilities.test.ts
  • apps/desktop/src/shared/subagentCapabilities.ts
  • apps/desktop/src/shared/types/chat.ts
  • apps/desktop/src/shared/types/prs.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch work-tab-ui-overhaul-21eb87d5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel

vercel Bot commented Jun 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview Jun 6, 2026 11:34pm

Comment on lines 341 to +357
}
}

// Terminate a single AGI mission worker. killWorkerSession lives only on the
// low-level DroidClient — DroidSession (what createSession/resumeSession return)
// exposes no public getter at @factory/droid-sdk 0.2.0 — so reach the underlying
// client via its (TS-private, runtime-present) `_client` field.
async function killWorker(workerSessionId: string): Promise<void> {
if (!session) throw new Error("Droid SDK worker is not initialized.");
const id = workerSessionId?.trim();
if (!id) return;
const client = (session as unknown as {
_client?: { killWorkerSession?: (params: { workerSessionId: string }) => Promise<unknown> };
})._client;
if (!client || typeof client.killWorkerSession !== "function") {
throw new Error("This Droid SDK build does not expose killWorkerSession.");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Fragile _client private-field bypass

session._client is a TypeScript-private implementation detail of DroidSession. At @factory/droid-sdk 0.2.0 the field is present at runtime, but nothing prevents a future release from renaming it, hoisting it, or removing it. When that happens, client is undefined and every ^k kill-worker attempt throws "This Droid SDK build does not expose killWorkerSession" — an error message that implies an SDK-version problem rather than a structural one, making it hard to triage.

If the SDK team can expose killWorkerSession publicly (or expose the underlying client), that would remove the coupling entirely. If not, consider adding a version guard or a clearly-marked adapter module so the fragile cast is a single-source-of-truth shim rather than inline in the worker dispatch.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/main/services/chat/droidSdkWorker.ts
Line: 341-357

Comment:
**Fragile `_client` private-field bypass**

`session._client` is a TypeScript-private implementation detail of `DroidSession`. At `@factory/droid-sdk` 0.2.0 the field is present at runtime, but nothing prevents a future release from renaming it, hoisting it, or removing it. When that happens, `client` is `undefined` and every `^k` kill-worker attempt throws "This Droid SDK build does not expose killWorkerSession" — an error message that implies an SDK-version problem rather than a structural one, making it hard to triage.

If the SDK team can expose `killWorkerSession` publicly (or expose the underlying client), that would remove the coupling entirely. If not, consider adding a version guard or a clearly-marked adapter module so the fragile cast is a single-source-of-truth shim rather than inline in the worker dispatch.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Comment on lines +531 to +532
const timestampFor = (index: number): string =>
new Date(Date.UTC(2026, 0, 1, 0, 0, 0, Math.min(index, 999))).toISOString();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Hardcoded 2026-01-01 timestamp base is already in the past

Today is 2026-06-06, so every synthetic envelope generated by buildSubagentEventHistory carries a January 2026 timestamp. Any relative-time display ("5 months ago") in the subagent takeover view will be visibly wrong. The parallel subagentTranscriptMessagesToEvents in chatSubagents.ts uses snapshot.startedAt — this function should do the same. Since startedAt isn't currently threaded into buildSubagentEventHistory's args, the easiest safe fallback is Date.now().

Suggested change
const timestampFor = (index: number): string =>
new Date(Date.UTC(2026, 0, 1, 0, 0, 0, Math.min(index, 999))).toISOString();
const baseTs = Date.now();
const timestampFor = (index: number): string =>
new Date(baseTs + index).toISOString();
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/components/chat/AgentChatPane.tsx
Line: 531-532

Comment:
**Hardcoded `2026-01-01` timestamp base is already in the past**

Today is 2026-06-06, so every synthetic envelope generated by `buildSubagentEventHistory` carries a January 2026 timestamp. Any relative-time display ("5 months ago") in the subagent takeover view will be visibly wrong. The parallel `subagentTranscriptMessagesToEvents` in `chatSubagents.ts` uses `snapshot.startedAt` — this function should do the same. Since `startedAt` isn't currently threaded into `buildSubagentEventHistory`'s args, the easiest safe fallback is `Date.now()`.

```suggestion
  const baseTs = Date.now();
  const timestampFor = (index: number): string =>
    new Date(baseTs + index).toISOString();
```

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

subagentEventsForDisplay useMemo (+ its view-model consts) ran after the
`if (!laneId) return` guard, making the hook conditional. Relocated the block
up to the subagent state cluster (identical logic + deps) so the hook is
unconditional. Lint 0 errors, typecheck clean, AgentChatPane.test 127/127.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28 arul28 merged commit 19a373f into main Jun 6, 2026
28 checks passed
@arul28 arul28 deleted the work-tab-ui-overhaul-21eb87d5 branch June 6, 2026 23:57
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.

1 participant