Skip to content

feat(web): complete preview annotation artifacts - #64

Merged
ronak-guliani merged 2 commits into
mainfrom
followup/browser-annotation-artifacts
Jul 29, 2026
Merged

ronak-guliani merged 2 commits into
mainfrom
followup/browser-annotation-artifacts

Conversation

@ronak-guliani

@ronak-guliani ronak-guliani commented Jul 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Rebased the browser UI parity and preview annotation work onto current main; this replaces the obsolete followup/browser-ui-parity base.
  • Add structured preview annotations to composer drafts and timeline rendering, including associated screenshot artifacts.
  • Add multi-surface right-panel browser tabs, file previews, terminal/port/file-to-preview actions, and the workspace-scoped RPC/assets required by those surfaces.
  • Preserve current preview automation host routing and MCP lifecycle work from main; no older server/provider implementation was restored.

Validation

  • pnpm fmt:check
  • pnpm lint
  • pnpm typecheck
  • cd apps/web && pnpm exec vp test run src/rightPanelStore.test.ts src/components/chat/ComposerPreviewAnnotationCards.test.tsx src/components/chat/MessagesTimeline.test.tsx src/components/preview/PreviewView.test.tsx src/components/preview/PreviewPanelShell.test.ts
  • cd packages/contracts && pnpm exec vp test run src/preview.test.ts
  • cd apps/server && pnpm exec vp test run src/mcp/McpHttpServer.test.ts src/mcp/McpPreviewAutomationEndToEnd.test.ts src/mcp/McpSessionRegistry.test.ts src/mcp/PreviewAutomationBroker.test.ts src/mcp/toolkits/preview/tools.test.ts

@github-actions github-actions Bot added size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Jul 27, 2026
@github-actions github-actions Bot added size:XXL and removed size:L labels Jul 27, 2026
@ronak-guliani
ronak-guliani requested a review from Copilot July 29, 2026 00:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Completes preview annotation artifacts and expands browser/right-panel functionality across web, server, and mobile clients.

Changes:

  • Adds annotation cards, prompt restoration, timeline rendering, and artifact actions.
  • Adds right-panel tabs for previews, terminals, files, and diffs.
  • Introduces authorized workspace reads, signed asset URLs, preview shortcuts, and Windows spawn compatibility.

Reviewed changes

Copilot reviewed 73 out of 74 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pnpm-lock.yaml Updates workspace dependency links.
packages/effect-codex-app-server/src/client.test.ts Uses Windows-safe process spawning.
packages/effect-codex-app-server/package.json Adds shared shell dependency.
packages/effect-acp/src/protocol.test.ts Uses Windows-safe process spawning.
packages/effect-acp/src/client.test.ts Uses Windows-safe process spawning.
packages/effect-acp/package.json Adds shared shell dependency.
packages/contracts/src/project.ts Scopes workspace search/read contracts.
packages/contracts/src/keybindings.ts Adds preview commands.
packages/contracts/src/keybindings.test.ts Tests preview commands.
packages/contracts/src/ipc.ts Exposes read-file and asset APIs.
packages/client-runtime/src/state/composerPathSearch.ts Uses thread-scoped search targets.
packages/client-runtime/src/composerPathSearchState.ts Implements thread-scoped searches.
packages/client-runtime/src/composerPathSearchState.test.ts Updates search tests.
oxlint-plugin-t3code/test/utils.ts Uses Windows-safe oxlint spawning.
oxlint-plugin-t3code/package.json Adds shared shell dependency.
KEYBINDINGS.md Documents preview shortcuts.
apps/web/test/wsRpcHarness.ts Registers discovered-server streaming.
apps/web/src/terminalLabels.ts Generates stable terminal labels.
apps/web/src/terminalLabels.test.ts Tests terminal labels.
apps/web/src/rpc/wsRpcClient.ts Adds file and asset RPC methods.
apps/web/src/rightPanelStore.ts Stabilizes and expands panel state.
apps/web/src/rightPanelStore.test.ts Tests surface operations.
apps/web/src/localApi.test.ts Tests asset API forwarding.
apps/web/src/lib/projectReactQuery.ts Uses authorized search scopes.
apps/web/src/keybindings.ts Adds preview contexts.
apps/web/src/keybindings.test.ts Tests preview shortcut resolution.
apps/web/src/environmentApi.ts Exposes file and asset methods.
apps/web/src/composerDraftStore.ts Atomically removes annotation artifacts.
apps/web/src/composerDraftStore.test.ts Tests paired artifact removal.
apps/web/src/components/ui/toast.tsx Adds icons and action slots.
apps/web/src/components/ui/toast.logic.test.ts Tests additional toast actions.
apps/web/src/components/ThreadTerminalDrawer.tsx Supports external terminal labels.
apps/web/src/components/ThreadTerminalDrawer.browser.tsx Extends environment API mocking.
apps/web/src/components/Sidebar.tsx Opens discovered localhost previews.
apps/web/src/components/RightPanelTabs.tsx Adds tab menus and panel controls.
apps/web/src/components/RightPanelTabs.browser.tsx Tests tab interactions.
apps/web/src/components/preview/PreviewView.tsx Adds artifact and server actions.
apps/web/src/components/preview/PreviewView.test.tsx Tests screenshot actions.
apps/web/src/components/preview/PreviewPanelShell.tsx Supports maximized panels.
apps/web/src/components/preview/PreviewPanelShell.test.ts Tests maximized layout.
apps/web/src/components/preview/PreviewPanel.tsx Propagates maximized state.
apps/web/src/components/preview/PreviewEmptyState.tsx Opens discovered server objects.
apps/web/src/components/files/FilePreviewPanel.tsx Adds workspace file surfaces.
apps/web/src/components/files/FilePreviewPanel.browser.tsx Tests file surfaces.
apps/web/src/components/ChatView.tsx Integrates annotations and panel surfaces.
apps/web/src/components/ChatView.browser.tsx Adds panel acceptance coverage.
apps/web/src/components/ChatMarkdown.tsx Opens HTML/PDF links in preview.
apps/web/src/components/ChatMarkdown.browser.tsx Tests previewable links.
apps/web/src/components/chat/MessagesTimeline.tsx Renders annotation context cards.
apps/web/src/components/chat/MessagesTimeline.test.tsx Tests annotation rendering.
apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx Adds composer annotation cards.
apps/web/src/components/chat/ComposerPreviewAnnotationCards.test.tsx Tests annotation cards.
apps/web/src/components/chat/ChatComposer.tsx Integrates annotation drafts and search scopes.
apps/web/src/browser/openFileInPreview.ts Opens signed workspace assets.
apps/server/src/ws.ts Adds scoped reads and asset issuance.
apps/server/src/workspace/Services/WorkspaceFileSystem.ts Defines workspace reads.
apps/server/src/workspace/Services/WorkspaceEntries.ts Separates internal search input.
apps/server/src/workspace/Layers/WorkspaceFileSystem.ts Implements protected file reads.
apps/server/src/workspace/Layers/WorkspaceFileSystem.test.ts Tests reads and symlink rejection.
apps/server/src/server.ts Registers the asset route.
apps/server/src/server.test.ts Tests scoped workspace search.
apps/server/src/keybindings.ts Adds default preview bindings.
apps/server/src/keybindings.test.ts Tests preview defaults.
apps/server/src/http.ts Serves signed asset bytes.
apps/server/src/cli.ts Uses project-scoped search.
apps/server/src/assets/AssetAccess.ts Implements signed asset capabilities.
apps/server/src/assets/AssetAccess.test.ts Tests assets and symlink containment.
apps/mobile-react/src/state/use-composer-path-search.ts Re-exports mobile search types.
apps/mobile-react/src/state/queries.ts Uses thread-scoped path search.
apps/mobile-react/src/features/threads/ThreadRouteScreen.tsx Passes thread identity to files.
apps/mobile-react/src/features/threads/ThreadComposer.tsx Searches by thread.
apps/mobile-react/src/features/files/ThreadFilesRouteScreen.tsx Reads files by thread.
apps/mobile-react/src/features/files/thread-file-navigator-pane.tsx Threads authorization through navigation.
apps/mobile-react/src/features/files/preload-workspace-file.ts Preloads thread-scoped files.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

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

Comment on lines +86 to +98
const contents = yield* fileSystem.readFileString(target.absolutePath).pipe(
Effect.mapError(
(cause) =>
new WorkspaceFileSystemError({
cwd: input.cwd,
relativePath: input.relativePath,
operation: "workspaceFileSystem.readFile",
detail: cause.message,
cause,
}),
),
);
return { relativePath: target.relativePath, contents };

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 11ee5016d. Workspace reads now cap previews at 1 MB, report truncation, and avoid materializing the full file.

Comment thread apps/server/src/ws.ts Outdated
Comment on lines +1399 to +1400
if (input.resource._tag !== "workspace-file") {
return yield* issueAssetUrl({ resource: input.resource });

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 11ee5016d. Project favicon asset requests now carry a project ID, and the server resolves the workspace root from the project snapshot before signing.

Comment on lines +150 to +153
<Menu key={surface.id}>
<MenuTrigger
render={
<button

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 11ee5016d. Primary tab clicks only activate the tab; context actions moved to a dedicated overflow button.

Comment thread apps/web/src/components/ChatView.tsx Outdated
Comment on lines +4677 to +4681
<PersistentThreadTerminalDrawer
threadRef={activeThreadRef}
threadId={activeThreadRef.threadId}
visible
terminalId={activeBrowserSurface.resourceId}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 11ee5016d. Right-panel terminals no longer depend on the drawer-open flag, and the legacy drawer is not mounted while a terminal surface is active.

Comment on lines +2806 to +2810
const nextDraft: ComposerThreadDraftState = {
...current,
images: current.images.filter((image) => image.id !== annotationId),
nonPersistedImageIds: current.nonPersistedImageIds.filter(
(imageId) => imageId !== annotationId,

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 11ee5016d. Removing an annotation now revokes its paired blob preview URL before removing the image.

Reconcile browser UI parity, preview annotations, file surfaces, and workspace-scoped access on current main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ronak-guliani
ronak-guliani force-pushed the followup/browser-annotation-artifacts branch from 11ee501 to c1a727d Compare July 29, 2026 16:22
@ronak-guliani
ronak-guliani changed the base branch from followup/browser-ui-parity to main July 29, 2026 16:22
@ronak-guliani
ronak-guliani requested a review from Copilot July 29, 2026 16:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 80 out of 80 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (4)

apps/web/src/components/ChatView.tsx:4837

  • The legacy drawer is suppressed only while a terminal surface is active. Starting a right-panel terminal sets the shared terminalOpen flag via the terminal started event; when the user switches that panel to Files/Diff/Preview, this condition becomes false and the same terminal reappears in the bottom drawer while its right-panel tab is still open. Suppress the legacy drawer whenever the active thread owns any terminal surface, not only when one is selected.
        mountedThreadKey === activeThreadKey && activeBrowserSurface?.kind === "terminal" ? null : (

apps/web/src/components/RightPanelTabs.tsx:107

  • Once a favicon request fails, failed remains true for the lifetime of this tab component. Navigating the same preview tab to another origin with a valid favicon therefore keeps showing the generic globe forever. Key the icon by URL (or reset the failure state when url changes) so each navigation can retry.
    apps/server/src/http.ts:229
  • This materializes the entire asset before responding. Workspace PDFs/images/HTML have no size limit, so each preview request can allocate the whole file in server memory and prevents efficient range/streamed delivery. Use HttpServerResponse.file, as the attachment route does at apps/server/src/http.ts:170-187, while retaining these cache and nosniff headers.
    const fileSystem = yield* FileSystem.FileSystem;
    const data = yield* fileSystem
      .readFile(asset.path)
      .pipe(Effect.catch(() => Effect.succeed(null)));
    if (!data) {
      return HttpServerResponse.text("Internal Server Error", { status: 500 });
    }
    return HttpServerResponse.uint8Array(data, {
      status: 200,
      contentType: Mime.getType(asset.path) ?? "application/octet-stream",

apps/web/src/components/files/FilePreviewPanel.tsx:65

  • The server intentionally returns only the first 1 MB and sets result.truncated, but this panel discards that flag and renders the prefix as though it were the complete file. Large source files are therefore silently misrepresented. Track truncated with the loaded contents and show a partial-file notice, matching the existing mobile file preview behavior in ThreadFilesRouteScreen.tsx:140-147.

Comment thread apps/web/src/composerDraftStore.ts
Comment thread apps/web/src/rightPanelStore.ts Outdated
Clear preview annotations with sent composer content and preserve the new-browser surface until a preview session is created.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ronak-guliani
ronak-guliani merged commit 3af1769 into main Jul 29, 2026
5 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants