Key workspace status and ownership by ID, not directory
Multiple workspaces can share one checkout directory. Agent and terminal status, sidebar tabs, and ownership now attribute strictly by workspace ID, so a running or blocked agent in one workspace no longer shows up on its same-directory siblings. A one-time startup migration backfills workspace IDs onto legacy agents, and every agent and terminal is created with one thereafter. Directory lookups remain only for genuinely folder-derived git facts (branch, diff) and the archive-by-path adapter.
This commit is contained in:
@@ -1,11 +1,7 @@
|
||||
import type { Agent } from "@/stores/session-store";
|
||||
import type { WorkspaceTabSnapshot } from "@/stores/workspace-layout-actions";
|
||||
import { shouldAutoOpenAgentTab } from "@/subagents/policies";
|
||||
import { normalizeWorkspaceOpaqueId, normalizeWorkspacePath } from "@/utils/workspace-identity";
|
||||
|
||||
function normalizeWorkspaceDirectory(value: string | null | undefined): string {
|
||||
return normalizeWorkspacePath(value) ?? "";
|
||||
}
|
||||
import { normalizeWorkspaceOpaqueId } from "@/utils/workspace-identity";
|
||||
|
||||
export interface WorkspaceAgentVisibility {
|
||||
activeAgentIds: Set<string>;
|
||||
@@ -13,31 +9,18 @@ export interface WorkspaceAgentVisibility {
|
||||
knownAgentIds: Set<string>;
|
||||
}
|
||||
|
||||
function agentBelongsToWorkspace(input: {
|
||||
agent: Agent;
|
||||
workspaceId: string | null;
|
||||
normalizedWorkspaceDirectory: string;
|
||||
}): boolean {
|
||||
const agentWorkspaceId = normalizeWorkspaceOpaqueId(input.agent.workspaceId);
|
||||
if (agentWorkspaceId) {
|
||||
return input.workspaceId !== null && agentWorkspaceId === input.workspaceId;
|
||||
}
|
||||
// COMPAT(workspaceOwnership): legacy agents predate workspaceId stamping. Fall
|
||||
// back to the single approved cwd→id inference by comparing the agent's cwd to
|
||||
// this workspace's directory. Drop when the daemon floor always stamps workspaceId.
|
||||
return normalizeWorkspaceDirectory(input.agent.cwd) === input.normalizedWorkspaceDirectory;
|
||||
function agentBelongsToWorkspace(agent: Agent, workspaceId: string): boolean {
|
||||
return normalizeWorkspaceOpaqueId(agent.workspaceId) === workspaceId;
|
||||
}
|
||||
|
||||
export function deriveWorkspaceAgentVisibility(input: {
|
||||
sessionAgents: Map<string, Agent> | undefined;
|
||||
agentDetails?: Map<string, Agent> | undefined;
|
||||
workspaceId?: string | null | undefined;
|
||||
workspaceDirectory: string | null | undefined;
|
||||
workspaceId: string | null | undefined;
|
||||
}): WorkspaceAgentVisibility {
|
||||
const { sessionAgents, agentDetails, workspaceDirectory } = input;
|
||||
const { sessionAgents, agentDetails } = input;
|
||||
const workspaceId = normalizeWorkspaceOpaqueId(input.workspaceId);
|
||||
const normalizedWorkspaceDirectory = normalizeWorkspaceDirectory(workspaceDirectory);
|
||||
if ((!sessionAgents && !agentDetails) || (!workspaceId && !normalizedWorkspaceDirectory)) {
|
||||
if ((!sessionAgents && !agentDetails) || !workspaceId) {
|
||||
return {
|
||||
activeAgentIds: new Set<string>(),
|
||||
autoOpenAgentIds: new Set<string>(),
|
||||
@@ -49,7 +32,7 @@ export function deriveWorkspaceAgentVisibility(input: {
|
||||
const autoOpenAgentIds = new Set<string>();
|
||||
const knownAgentIds = new Set<string>();
|
||||
for (const agent of sessionAgents?.values() ?? []) {
|
||||
if (!agentBelongsToWorkspace({ agent, workspaceId, normalizedWorkspaceDirectory })) {
|
||||
if (!agentBelongsToWorkspace(agent, workspaceId)) {
|
||||
continue;
|
||||
}
|
||||
knownAgentIds.add(agent.id);
|
||||
@@ -61,7 +44,7 @@ export function deriveWorkspaceAgentVisibility(input: {
|
||||
}
|
||||
}
|
||||
for (const agent of agentDetails?.values() ?? []) {
|
||||
if (!agentBelongsToWorkspace({ agent, workspaceId, normalizedWorkspaceDirectory })) {
|
||||
if (!agentBelongsToWorkspace(agent, workspaceId)) {
|
||||
continue;
|
||||
}
|
||||
knownAgentIds.add(agent.id);
|
||||
|
||||
Reference in New Issue
Block a user