Support PowerShell and resolve workspaces by directory path

This commit is contained in:
Mohamed Boudra
2026-04-04 15:37:26 +07:00
parent 5d5a79a2a8
commit 449a4b48d2
10 changed files with 323 additions and 17 deletions
@@ -49,6 +49,31 @@ describe("patchWorkspaceServices", () => {
expect(next.get("/repo/other")).toBe(other);
});
it("patches the matching workspace when the update uses workspace directory identity", () => {
const current = new Map<string, WorkspaceDescriptor>([
[
"42",
workspace({
id: "42",
services: [],
}),
],
]);
current.set("42", {
...current.get("42")!,
workspaceDirectory: "C:\\repo\\main\\",
});
const next = patchWorkspaceServices(current, {
workspaceId: "C:/repo/main",
services: [runningService],
});
expect(next).not.toBe(current);
expect(next.get("42")?.services).toEqual([runningService]);
});
it("ignores updates for unknown workspaces", () => {
const current = new Map<string, WorkspaceDescriptor>([
["/repo/main", workspace({ id: "/repo/main", services: [] })],
@@ -1,17 +1,26 @@
import type { ServiceStatusUpdateMessage } from "@server/shared/messages";
import type { WorkspaceDescriptor } from "@/stores/session-store";
import { resolveWorkspaceMapKeyByIdentity } from "@/utils/workspace-execution";
export function patchWorkspaceServices(
workspaces: Map<string, WorkspaceDescriptor>,
update: ServiceStatusUpdateMessage["payload"],
): Map<string, WorkspaceDescriptor> {
const existing = workspaces.get(update.workspaceId);
const workspaceKey = resolveWorkspaceMapKeyByIdentity({
workspaces,
workspaceIdentity: update.workspaceId,
});
if (!workspaceKey) {
return workspaces;
}
const existing = workspaces.get(workspaceKey);
if (!existing) {
return workspaces;
}
const next = new Map(workspaces);
next.set(update.workspaceId, {
next.set(workspaceKey, {
...existing,
services: update.services.map((s) => ({ ...s })),
});
@@ -3,6 +3,7 @@ import type { WorkspaceDescriptor } from "@/stores/session-store";
import {
getWorkspaceExecutionAuthority,
requireWorkspaceExecutionAuthority,
resolveWorkspaceMapKeyByIdentity,
resolveWorkspaceIdByExecutionDirectory,
resolveWorkspaceRouteId,
} from "./workspace-execution";
@@ -72,6 +73,46 @@ describe("resolveWorkspaceIdByExecutionDirectory", () => {
});
});
describe("resolveWorkspaceMapKeyByIdentity", () => {
it("returns the existing map key when the identity already matches a key", () => {
const workspaces = new Map<string, WorkspaceDescriptor>([
[
"workspace-1",
createWorkspace({
id: "workspace-1",
workspaceDirectory: "/repo/.paseo/worktrees/feature",
}),
],
]);
expect(
resolveWorkspaceMapKeyByIdentity({
workspaces,
workspaceIdentity: "workspace-1",
}),
).toBe("workspace-1");
});
it("resolves a workspace directory identity to the canonical map key", () => {
const workspaces = new Map<string, WorkspaceDescriptor>([
[
"workspace-1",
createWorkspace({
id: "workspace-1",
workspaceDirectory: "C:\\repo\\feature\\",
}),
],
]);
expect(
resolveWorkspaceMapKeyByIdentity({
workspaces,
workspaceIdentity: "C:/repo/feature",
}),
).toBe("workspace-1");
});
});
describe("workspace execution authority", () => {
it("returns an explicit failure when workspace id is missing", () => {
expect(
+36 -3
View File
@@ -44,6 +44,36 @@ export function resolveWorkspaceIdByExecutionDirectory(input: {
return null;
}
export function resolveWorkspaceMapKeyByIdentity(input: {
workspaces: Map<string, WorkspaceDescriptor> | null | undefined;
workspaceIdentity: string | null | undefined;
}): string | null {
const normalizedWorkspaceIdentity = normalizeWorkspaceIdentity(input.workspaceIdentity);
if (!normalizedWorkspaceIdentity) {
return null;
}
const workspaces = input.workspaces;
if (!workspaces) {
return null;
}
if (workspaces.has(normalizedWorkspaceIdentity)) {
return normalizedWorkspaceIdentity;
}
for (const [workspaceKey, workspace] of workspaces) {
if (
normalizeWorkspaceIdentity(workspace.id) === normalizedWorkspaceIdentity ||
normalizeWorkspaceIdentity(workspace.workspaceDirectory) === normalizedWorkspaceIdentity
) {
return workspaceKey;
}
}
return null;
}
export function getWorkspaceExecutionAuthority(
input:
| {
@@ -58,11 +88,14 @@ export function getWorkspaceExecutionAuthority(
"workspace" in input
? input.workspace
: (() => {
const normalizedWorkspaceId = normalizeWorkspaceIdentity(input.workspaceId);
if (!normalizedWorkspaceId) {
const workspaceKey = resolveWorkspaceMapKeyByIdentity({
workspaces: input.workspaces,
workspaceIdentity: input.workspaceId,
});
if (!workspaceKey) {
return null;
}
return input.workspaces?.get(normalizedWorkspaceId) ?? null;
return input.workspaces?.get(workspaceKey) ?? null;
})();
if ("workspaces" in input) {