Surface workspace changes from agent panes (#3682)

* feat(app): refine workspace pane actions

Prioritize Changes when available, keep Files useful before a selection, and reserve desktop diff clicks for selection so comments require the explicit affordance. Move the Changes shortcut to Shift+G to avoid consuming a likely copy variant.

* feat(app): improve access to workspace changes
This commit is contained in:
Mohamed Boudra
2026-08-22 12:20:21 +02:00
committed by GitHub
parent b1455fb4b3
commit 3029b5991a
31 changed files with 527 additions and 66 deletions
+27 -6
View File
@@ -1,4 +1,6 @@
import { memo, useCallback, type ReactElement } from "react";
import { WorkspaceDiffStatPill } from "@/composer/diff-stat-pill";
import { useWorkspaceHasDiffStat } from "@/composer/workspace-diff-stat";
import { AgentTaskList } from "@/composer/task-list";
import { ComposerTrackBar } from "@/composer/tracks";
import { supportsDesktopPaneSplits, useIsCompactFormFactor } from "@/constants/layout";
@@ -18,26 +20,29 @@ import { buildWorkspaceTabPersistenceKey } from "@/workspace-tabs/model";
import { openSupportingTab } from "@/workspace-tabs/side-panel";
/**
* The pane's trackers — its subagents and its task list — as a row of pills above the composer.
* The pane's ambient context — workspace changes, subagents, and tasks — as a row of pills above
* the composer.
*
* The row shares the composer's keyboard transform and owns the space between itself and the
* transcript. Its data remains agent state: a subagent row opens a tab and the task list reads
* the agent's stream.
* transcript. Each pill owns its action while tab placement stays behind the workspace boundary.
*/
export const AgentTracks = memo(function AgentTracks({
serverId,
workspaceId,
subagentRows,
tasks,
archiveFinishedStatus,
onArchiveFinished,
}: {
serverId: string;
workspaceId: string;
subagentRows: SubagentRow[];
tasks: TodoEntry[] | undefined;
archiveFinishedStatus: ArchiveFinishedStatus;
onArchiveFinished: () => void;
}): ReactElement | null {
const { workspaceId, tabId, openTab } = usePaneContext();
const { tabId, openTab } = usePaneContext();
const hasWorkspaceDiffStat = useWorkspaceHasDiffStat(serverId, workspaceId);
const isCompact = useIsCompactFormFactor();
const canSplit = supportsDesktopPaneSplits() && !isCompact;
const openInSidePanelByDefault = useSettings(
@@ -87,13 +92,25 @@ export const AgentTracks = memo(function AgentTracks({
},
[canSplit, isCompact, openInSidePanelByDefault, openTab, tabId, workspaceKey],
);
const handleOpenChanges = useCallback(() => {
if (!workspaceKey) {
return;
}
openSupportingTab({
isCompact,
workspaceKey,
target: { kind: "working_diff" },
openInSidePanelByDefault,
});
}, [isCompact, openInSidePanelByDefault, workspaceKey]);
if (!hasAgentTracks({ subagentRows, tasks, archiveFinishedStatus })) {
if (!hasWorkspaceDiffStat && !hasAgentTracks({ subagentRows, tasks, archiveFinishedStatus })) {
return null;
}
return (
<ComposerTrackBar>
<AgentTaskList tasks={tasks} />
<SubagentsTrack
rows={subagentRows}
onOpenSubagent={handleOpenSubagent}
@@ -103,7 +120,11 @@ export const AgentTracks = memo(function AgentTracks({
archiveFinishedStatus={archiveFinishedStatus}
onDetachSubagent={canDetachSubagents ? detachSubagent : undefined}
/>
<AgentTaskList tasks={tasks} />
<WorkspaceDiffStatPill
serverId={serverId}
workspaceId={workspaceId}
onPress={handleOpenChanges}
/>
</ComposerTrackBar>
);
});