Skip to content

Add expandable command and file-change activity boxes#3173

Open
Quicksaver wants to merge 304 commits into
pingdotgg:mainfrom
Quicksaver:split/file-command-activity-boxes
Open

Add expandable command and file-change activity boxes#3173
Quicksaver wants to merge 304 commits into
pingdotgg:mainfrom
Quicksaver:split/file-command-activity-boxes

Conversation

@Quicksaver

@Quicksaver Quicksaver commented Jun 19, 2026

Copy link
Copy Markdown

Summary

This adds richer expandable activity boxes for command and file-change work-log rows in the chat timeline. Command rows can now show the command, raw command, exit code, duration, stdout/stderr or fallback output, and file-change rows can show changed paths plus inline unified diffs when patch data is available.

The implementation keeps this data in the derived work-log model, extracts command result and patch metadata from provider payloads, and renders the richer details without losing the existing compact row behavior.

What Changed

  • Preserved command output metadata in WorkLogEntry, including stdout, stderr, fallback output, exit code, and duration.
  • Added bounded file-change patch extraction from provider payloads, including Codex-style nested file-change records and simple content diffs normalized into unified patches.
  • Kept stable arrival order for unsequenced same-timestamp activity events so streamed output chunks are not scrambled by random event ids.
  • Added expandable command details in MessagesTimeline with command/raw-command sections, status chips, tail-truncated output, and full-output expansion.
  • Added expandable file-change details in MessagesTimeline with changed-file chips and inline diff rendering through the existing diff rendering utilities.
  • Kept generic tool expansion behavior for rows that are neither command nor file-change details.
  • Hardened command-output extraction so blank completed stdout falls back to aggregated output while live incremental whitespace chunks are still preserved exactly.
  • Hardened command-output merging so shorter completed snapshots and shorter line-complete updated snapshots do not corrupt already merged command output, while prefix-like incremental chunks still append exactly.
  • Refined shorter-prefix command-output merging so single-line repeated-prefix snapshots do not duplicate output, while ambiguous multiline prefix chunks still preserve incremental stream data.
  • Addressed follow-up review findings in the merged VS Code extension code by stabilizing subagent activity row hooks, escaping inline webview bootstrap payloads, surfacing malformed desktop readiness responses, preserving readiness retries for transient body-read failures, disposing connected webview resources if render fails, and cleaning MCP socket directories after listen failures.
  • Aligned desktop backend advertisement errors with Effect service conventions by switching to a schema tagged error with a stable message while preserving sanitized structured cause diagnostics in warning annotations.
  • Surfaced source-control thread ref metadata update failures in the chat error banner without hiding unrelated thread errors when later metadata updates succeed, while making source-control metadata errors dismissible, keeping provider session errors non-dismissible, ignoring stale metadata update responses, pruning stale per-thread metadata state, and preserving cached active-thread metadata state across reconnect snapshots.
  • Added focused coverage for command output extraction, output merging, file-change patch extraction, renderable command output helpers, and timeline rendering of command/file-change rows.

Why

Individual command and diff events are mostly opaque currently. We can somewhat see what the agent is doing, but we don't have a clear picture of what each command actually outputs, or what each file change actually produced.

Usually that's fine, most times we inspect the end result and trust the agent. Sometimes it's good to inspect a little deeper. For commands we can help steer by debugging their output, or just compare the results with manual runs. For diffs we can see better follow along the multiple changes an agent makes, or even inspect changes to git-ignored files (which don't appear on the main diff panel).

Validation

  • (cd apps/web && pnpm exec vp test run --passWithNoTests --project unit src/session-logic.test.ts) passed: 1 file, 79 tests.
  • (cd apps/web && pnpm exec vp test run --passWithNoTests --project unit src/components/chat/MessagesTimeline.test.tsx) passed: 1 file, 13 tests.
  • pnpm exec vp run --filter @t3tools/web test -- src/components/chat/MessagesTimeline.test.tsx passed on the final branch state: 145 files, 1318 tests.
  • pnpm exec vp run --filter t3code-vscode test -- src/backendManager.test.ts src/webview.test.ts src/mcpBridge.test.ts src/extension.test.ts passed on the final branch state: 6 files, 55 tests.
  • pnpm exec vp run --filter @t3tools/desktop test -- src/backend/DesktopBackendManager.test.ts passed on the final branch state: 43 files, 241 tests.
  • pnpm exec vp run --filter @t3tools/web test -- src/components/source-control/SourceControlPanel.logic.test.ts src/state/sourceControlPanel.test.ts passed after the source-control metadata error handling fix: 146 files, 1330 tests.
  • pnpm exec vp run --filter @t3tools/web test -- src/components/ChatView.logic.test.ts passed after the source-control metadata error dismissal/race fixes: 146 files, 1335 tests.
  • pnpm exec vp check passed. It reported 20 existing lint warnings outside this branch's changed files.
  • pnpm exec vp run typecheck passed across all packages.
  • $assess-work completed after the review fixes. Earlier CodeRabbit first/final passes reported 0 issues; Codex and blast review follow-ups were addressed in 1558dd029, 26c447183, and the desktop advertisement diagnostic commits through bac9d4907. The Macroscope source-control metadata thread was addressed by aa0adfd93, 1bb7681c, and a02327a7. The latest Cursor source-control metadata dismissal/race threads were addressed by 4ca7cf953, f15d7e34c, ef437d295, cface2863, and documented in 2565d1d90; CodeRabbit/Codex/blast assessment follow-ups were addressed and the final CodeRabbit pass reported 0 issues.

Proof

before:
before

after:
after

expanded command output with tail truncation:
Screenshot 2026-06-09 at 09 32 11

expanded inline file-change diffs:
Screenshot 2026-06-09 at 09 34 06


Note

High Risk
Touches orchestration persistence and auth bootstrap paths plus broad Git/VCS and desktop lifecycle behavior; scope and cross-client impact make regressions costly.

Overview
Chat work-log rows now expose richer expandable detail: command sections (stdout/stderr, exit code, duration, tail truncation), file-change chips with inline unified diffs when patch data exists, and dedicated subagent summary rows that link into child threads instead of treating collab items like generic expandable tools. session-logic carries structured command output, patch extraction, stable ordering for streamed chunks, and safer incremental output merging.

Codex subagent orchestration is wired end-to-end: threads gain persisted parentRelation (projection ingest/query, lifecycle commands), child shells and launch prompts from collab metadata, title generation from the title seed, resume/re-run status updates, and child turn interrupts routed through the root provider session without falling back to the parent’s active turn.

The fork also adds substantial platform surface: Git Version Control right-panel behavior and server RPCs (documented in SOURCE_CONTROL.md), desktop backend advertisements with sanitized failure diagnostics and cleanup on stop, VS Code–style host bootstrap (workspace folders, MCP servers, stdio-to-uds relay), legacy /api/auth/bootstrap/bearer compatibility routes, Electron context-menu separator normalization, and agent skills for multi-worktree update/port/comment flows. Docs and investigation logs (SUBAGENTS.md, POWER_CONSUMPTION.md, fork pointer in AGENTS.md) accompany these behaviors.

Reviewed by Cursor Bugbot for commit 91c1d67. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add expandable command and file-change activity boxes to the chat timeline

  • Work entries in the messages timeline now render as expandable/collapsible rows with aria-expanded and aria-label attributes; commands, file changes, and subagent items each show structured detail panels when expanded.
  • Subagent child threads are rendered as individual navigable buttons beneath a tool work entry, showing live or formatted status/duration labels and routing to the child conversation on click.
  • session-logic.ts is significantly extended to extract stdout, stderr, exitCode, durationMs, and patch from tool payloads; merging across streaming updates now prefers cumulative content and avoids regressing to shorter snapshots.
  • The Codex and Cursor adapters now buffer child subagent deltas and attach them to parent collab completion events; subagent conversations are deterministically routed to stable child thread IDs derived from a SHA-256 hash.
  • Subagent threads are created and updated on-the-fly during provider runtime ingestion, with parentRelation lineage, depth, timing, and status transitions persisted to a new DB migration (033/034).
  • Risk: the DB schema gains 12 new columns on projection_threads and two new indexes; migration 034 backfills root_thread_id for existing rows, which could be slow on large databases.

Macroscope summarized 91c1d67.

Quicksaver added 30 commits June 1, 2026 09:42
- Query peers sequentially until one returns a result
- Avoid sending owner-sensitive commands to later peers
- Cover the interrupt dispatch path with a regression test
- Align VS Code extension deps with the upstream Effect catalog

- Switch local peer HTTP calls and server tests to Effect HTTP

- Tighten orchestration test decoding for thread.turn.start
- Resolve catalog dependencies from the root workspace catalog

- Keep packaged VS Code manifests installable outside the monorepo
- Add forceDesktopLayout to sidebar provider

- Keep thread sidebar open in desktop shells

- Add regression coverage for desktop rendering
- Preserve provider lock in all hosts
- Remove VS Code-only composer unlock path
- Update unit coverage for shared lock behavior
- Buffer and coalesce subagent activity output
- Preserve local behavior for future upstream merges
- Document branch-specific changes in CUSTOMIZED.md
- Let chat surfaces use full available width by default
- Keep the VS Code setting as an explicit opt-in override
- Cover the new default with a focused web test
- Update extension docs to describe empty as no max width
- Label desktop-bootstrap bearer sessions as VS Code
- Shorten their bearer TTL and revoke stale ones
- Add authenticated session revocation on backend stop
- Route thread archive stop commands through peer context
- Update tests for auth, federation, and backend cleanup
- Remove the 12-hour TTL override for backend bearer sessions

- Keep stale desktop-bootstrap cleanup separate from live tokens
- Restrict self-revoke route to bearer sessions

- Make backend revocation timeout portable and resilient

- Preserve peer archive-stop routing fallback
- Stop provider sessions when archive routing lookup fails

- Add regression coverage for lookup failure fallback
- Add bearer-only HTTP authentication for revocation

- Cover revocation when cookie and bearer auth coexist
- Add shared desktop backend advertisement files\n- Issue and refresh bootstrap tickets for desktop backends\n- Let the web UI read VS Code workspace bootstrap data
- Revoke stale VS Code bearer sessions on cancelled startup
- Gate desktop ready state on control advertisement setup
- Replace connected webview disposables on reconnect
- Delete expired desktop bootstrap ticket rows during issuance

- Remove advertisements after closing backend run scope
- Restrict desktop ticket minting to control sessions
- Harden VS Code workspace bootstrap selection and retries
- Tighten host bridge typing and cleanup behavior
- Thread startup abort signals through backend readiness and bootstrap
- Update cancellation coverage to honor abort signals
- Remove stopped desktop backend advertisements after close

- Keep workspace bootstrap tied to active cancellation only
- Document current desktop-control ticket flow
- Note workspace bootstrap fallback and abort behavior
- Keep README unchanged because it still matches shipped UX
- Note the extension work is local customization
- Point implementation detail to apps/vscode-extension/IMPLEMENTATION.md
# Conflicts:
#	.github/workflows/release.yml
#	apps/server/src/auth/Layers/ServerAuth.test.ts
#	apps/server/src/auth/Layers/ServerAuth.ts
#	apps/server/src/auth/PairingGrantStore.test.ts
#	apps/server/src/auth/PairingGrantStore.ts
#	apps/server/src/auth/Services/ServerAuth.ts
#	apps/server/src/auth/SessionStore.ts
#	apps/server/src/auth/http.ts
#	apps/server/src/orchestration/http.ts
#	apps/server/src/server.test.ts
#	apps/server/src/server.ts
#	apps/server/src/ws.ts
#	apps/web/src/authBootstrap.test.ts
#	apps/web/src/environments/primary/auth.ts
#	apps/web/src/environments/primary/bootstrap.test.ts
#	apps/web/src/environments/primary/context.ts
#	apps/web/vite.config.ts
#	bun.lock
#	packages/contracts/src/ipc.ts
- keep the workspace test command on the merged toolchain
- replace stale bun package commands
- refresh verified toolchain and auth wording
- keep mobile builds on the local Expo project
- remove the stale mobile package override
- invoke vsce through pnpm exec
# Conflicts:
#	.gitignore
#	apps/server/src/bin.ts
#	apps/web/src/components/settings/SettingsSidebarNav.tsx
#	apps/web/src/environments/runtime/service.ts
#	apps/web/src/main.tsx
#	apps/web/src/routes/_chat.index.tsx
#	packages/shared/package.json
#	pnpm-lock.yaml
#	pnpm-workspace.yaml
- Switch extension tests to the Effect Vitest package
- Update the extension dev dependency and lockfile
- Refresh customized branch test commands in CUSTOMIZED.md
- Remove desktop-issued VS Code ticket advertising
- Store and reuse the exchanged bearer token in VS Code
- Keep the desktop backend advertisement credential-free
- Preserve latest running child activity rows in parent timelines
- Add per-generation sidebar indentation for visible subagents
- Update subagent dedupe and visibility tests
…tivity-boxes

# Conflicts:
#	apps/web/src/components/chat/MessagesTimeline.test.tsx
#	apps/web/src/components/chat/MessagesTimeline.tsx
#	apps/web/src/session-logic.test.ts
#	apps/web/src/session-logic.ts
@github-actions github-actions Bot added size:XXL 1,000+ changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Jun 21, 2026
Comment thread apps/vscode-extension/src/webview.ts
Comment thread apps/web/src/components/chat/MessagesTimeline.tsx Outdated
Comment thread apps/vscode-extension/src/backendManager.ts
Comment thread apps/vscode-extension/src/extension.ts
- Escape embedded script end tags in bridge data
- Dispose webview resources when rendering fails
- Clean up MCP sockets after listen failures
- Surface malformed desktop readiness responses
- Keep timeline hooks after the early subagent return
- Keep subagent row hooks stable before grouped rendering

- Retry stalled VS Code readiness bodies under abort timeout
- Preserve retries for transient readiness body read failures

- Escape inline webview bootstrap payload parser breakouts

- Share render cleanup for connected VS Code webviews

@macroscopeapp macroscopeapp 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.

Effect service conventions: one error class deviates from the module's pattern and the service error conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/desktop/src/backend/DesktopBackendManager.ts Outdated
- Switch the error to a Schema tagged error\n- Keep the message stable for backend advertisement failures
- Include advertisement failure causes in warning messages
Keep the desktop backend advertisement error message stable while logging the underlying cause as structured metadata.
- Preserve nested advertisement failure causes safely

- Add coverage for malformed advertisement cause values
- Redact fallback advertisement diagnostics for malformed URLs

- Cover invalid-port URL sanitizer behavior
…activity-boxes

# Conflicts:
#	apps/server/src/provider/Layers/CursorProvider.test.ts
#	apps/web/src/components/AppSidebarLayout.tsx
#	apps/web/src/components/NoActiveThreadState.tsx
#	apps/web/src/components/Sidebar.tsx
#	apps/web/src/components/chat/ChatHeader.tsx
#	apps/web/src/components/ui/sidebar.tsx
#	apps/web/src/routes/_chat.index.tsx
#	apps/web/src/routes/settings.tsx
Comment thread apps/web/src/components/ChatView.tsx
- Check updateThreadMetadata failure in server thread updates
- Set thread error when the source control update does not succeed
- Clear stale thread errors after metadata updates

- Preserve string failure messages from squashed causes
- Track source control metadata update errors separately

- Clear only metadata update errors after successful ref changes

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a02327a. Configure here.

Comment thread apps/web/src/components/ChatView.tsx
Comment thread apps/web/src/components/ChatView.tsx
- Add shared helpers for thread error clearing
- Ignore out-of-order metadata responses per thread
- Reuse the dismiss handler for server-thread errors
- Use the active thread key for metadata error state
- Prune stale metadata errors and update sequences
- Cover thread-key record pruning in ChatView tests

@macroscopeapp macroscopeapp 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.

Effect service conventions: one issue found in the newly added SourceControlPanelService. See inline comment.

Posted via Macroscope — Effect Service Conventions

Comment on lines +58 to +119
export interface SourceControlPanelServiceShape {
readonly snapshot: (
input: VcsPanelSnapshotInput,
) => Effect.Effect<VcsPanelSnapshotResult, GitCommandError>;
readonly branchDetails: (
input: VcsPanelBranchDetailsInput,
) => Effect.Effect<VcsPanelBranchDetails, GitCommandError>;
readonly branchCommits: (
input: VcsPanelBranchCommitsInput,
) => Effect.Effect<VcsPanelBranchCommitsResult, GitCommandError>;
readonly stashDetails: (
input: VcsPanelStashDetailsInput,
) => Effect.Effect<VcsPanelStashDetails, GitCommandError>;
readonly stageFiles: (input: VcsPanelFileActionInput) => Effect.Effect<void, GitCommandError>;
readonly unstageFiles: (input: VcsPanelFileActionInput) => Effect.Effect<void, GitCommandError>;
readonly discardFiles: (input: VcsPanelFileActionInput) => Effect.Effect<void, GitCommandError>;
readonly enrichWorkingTreeFiles: (
input: VcsPanelWorkingTreeFileEnrichmentInput,
) => Effect.Effect<VcsPanelWorkingTreeFileEnrichmentResult, GitCommandError>;
readonly readFileDiff: (
input: VcsPanelFileDiffInput,
) => Effect.Effect<VcsPanelFileDiffResult, GitCommandError>;
readonly commitStaged: (input: VcsPanelCommitInput) => Effect.Effect<void, GitCommandError>;
readonly pullBranch: (
input: VcsPanelBranchActionInput,
) => Effect.Effect<VcsPullResult, GitCommandError>;
readonly pushBranch: (input: VcsPanelBranchActionInput) => Effect.Effect<void, GitCommandError>;
readonly deleteBranch: (input: VcsPanelDeleteBranchInput) => Effect.Effect<void, GitCommandError>;
readonly undoLatestCommit: (
input: VcsPanelUndoCommitInput,
) => Effect.Effect<void, GitCommandError>;
readonly revertCommit: (input: VcsPanelCommitActionInput) => Effect.Effect<void, GitCommandError>;
readonly checkoutCommit: (
input: VcsPanelCommitActionInput,
) => Effect.Effect<{ readonly refName: string }, GitCommandError>;
readonly createBranchFromCommit: (
input: VcsPanelCommitActionInput,
) => Effect.Effect<{ readonly refName: string }, GitCommandError>;
readonly mergeBranchIntoCurrent: (
input: VcsPanelRefActionInput,
) => Effect.Effect<void, GitCommandError>;
readonly rebaseCurrentOnto: (
input: VcsPanelRefActionInput,
) => Effect.Effect<void, GitCommandError>;
readonly fetchBranch: (input: VcsPanelBranchActionInput) => Effect.Effect<void, GitCommandError>;
readonly fetchRemote: (input: VcsPanelRemoteInput) => Effect.Effect<void, GitCommandError>;
readonly fetchAllRemotes: (input: VcsPanelSnapshotInput) => Effect.Effect<void, GitCommandError>;
readonly addRemote: (input: VcsPanelAddRemoteInput) => Effect.Effect<void, GitCommandError>;
readonly removeRemote: (input: VcsPanelRemoteInput) => Effect.Effect<void, GitCommandError>;
readonly createStash: (input: VcsPanelStashInput) => Effect.Effect<void, GitCommandError>;
readonly applyStash: (input: VcsPanelStashInput) => Effect.Effect<void, GitCommandError>;
readonly popStash: (input: VcsPanelStashInput) => Effect.Effect<void, GitCommandError>;
readonly dropStash: (input: VcsPanelStashInput) => Effect.Effect<void, GitCommandError>;
readonly compare: (
input: VcsPanelCompareInput,
) => Effect.Effect<VcsPanelCompareResult, GitCommandError>;
}

export class SourceControlPanelService extends Context.Service<
SourceControlPanelService,
SourceControlPanelServiceShape
>()("t3/sourceControl/SourceControlPanelService") {}

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.

This newly added service declares a standalone SourceControlPanelServiceShape interface and passes it into Context.Service, but the convention is to define the service interface inline in the Context.Service declaration and refer to it as SourceControlPanelService["Service"] (no standalone FooShape type).

Suggested change: move the interface body inline into the tag and drop the separate interface:

export class SourceControlPanelService extends Context.Service<
  SourceControlPanelService,
  {
    readonly snapshot: (
      input: VcsPanelSnapshotInput,
    ) => Effect.Effect<VcsPanelSnapshotResult, GitCommandError>;
    // ...rest of the members...
    readonly compare: (
      input: VcsPanelCompareInput,
    ) => Effect.Effect<VcsPanelCompareResult, GitCommandError>;
  }
>()("t3/sourceControl/SourceControlPanelService") {}

Then update the implementation references from SourceControlPanelServiceShape["..."] to SourceControlPanelService["Service"]["..."].

Posted via Macroscope — Effect Service Conventions

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

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant