WIP: workspace execution refactor + notification routing + setup store updates

This commit is contained in:
Mohamed Boudra
2026-04-01 21:28:07 +07:00
parent d8243bfb72
commit a7d5ab2497
29 changed files with 1064 additions and 197 deletions
@@ -28,6 +28,20 @@ describe("resolveNotificationTarget", () => {
workspaceId: null,
});
});
it("does not treat cwd as a workspace id alias", () => {
expect(
resolveNotificationTarget({
serverId: "srv-1",
agentId: "agent-1",
cwd: "/tmp/repo",
}),
).toEqual({
serverId: "srv-1",
agentId: "agent-1",
workspaceId: null,
});
});
});
describe("buildNotificationRoute", () => {
@@ -23,7 +23,7 @@ export function resolveNotificationTarget(data: NotificationData): {
return {
serverId: readNonEmptyString(data, "serverId"),
agentId: readNonEmptyString(data, "agentId"),
workspaceId: readNonEmptyString(data, "workspaceId") ?? readNonEmptyString(data, "cwd"),
workspaceId: readNonEmptyString(data, "workspaceId"),
};
}
@@ -1,26 +0,0 @@
import type { WorkspaceDescriptor } from "@/stores/session-store";
import { normalizeWorkspaceIdentity } from "@/utils/workspace-identity";
export function resolveHydratedWorkspaceId(input: {
workspaces: Iterable<WorkspaceDescriptor> | null | undefined;
path: string | null | undefined;
}): string | null {
const normalizedPath = normalizeWorkspaceIdentity(input.path);
if (!normalizedPath) {
return null;
}
for (const workspace of input.workspaces ?? []) {
if (normalizeWorkspaceIdentity(workspace.id) === normalizedPath) {
return workspace.id;
}
if (normalizeWorkspaceIdentity(workspace.workspaceDirectory) === normalizedPath) {
return workspace.id;
}
if (normalizeWorkspaceIdentity(workspace.projectRootPath) === normalizedPath) {
return workspace.id;
}
}
return null;
}
@@ -17,7 +17,7 @@ function workspace(
projectKind: input.projectKind ?? "git",
workspaceKind: input.workspaceKind ?? "worktree",
name: input.name ?? input.id,
status: input.status ?? "done",
status: input.status ?? "running",
activityAt: input.activityAt ?? null,
diffStat: input.diffStat ?? null,
};
@@ -38,7 +38,7 @@ describe("resolveWorkspaceArchiveRedirectWorkspaceId", () => {
).toBe("/repo");
});
it("falls back to the project root path when the root checkout is not in the visible workspace list", () => {
it("falls back to the host root route when no sibling workspace target exists", () => {
const workspaces = [
workspace({
id: "/repo/.paseo/worktrees/feature",
@@ -48,11 +48,12 @@ describe("resolveWorkspaceArchiveRedirectWorkspaceId", () => {
];
expect(
resolveWorkspaceArchiveRedirectWorkspaceId({
buildWorkspaceArchiveRedirectRoute({
serverId: "server-1",
archivedWorkspaceId: "/repo/.paseo/worktrees/feature",
workspaces,
}),
).toBe("/repo");
).toBe("/h/server-1");
});
it("falls back to the host root route when no alternate workspace target exists", () => {
@@ -1,20 +1,14 @@
import type { WorkspaceDescriptor } from "@/stores/session-store";
import { buildHostRootRoute, buildHostWorkspaceRoute } from "@/utils/host-routes";
function trimNonEmpty(value: string | null | undefined): string | null {
if (typeof value !== "string") {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}
import { resolveWorkspaceRouteId } from "@/utils/workspace-execution";
export function resolveWorkspaceArchiveRedirectWorkspaceId(input: {
archivedWorkspaceId: string;
workspaces: Iterable<WorkspaceDescriptor>;
}): string | null {
const archivedWorkspaceId = trimNonEmpty(input.archivedWorkspaceId);
const archivedWorkspaceId = resolveWorkspaceRouteId({
routeWorkspaceId: input.archivedWorkspaceId,
});
if (!archivedWorkspaceId) {
return null;
}
@@ -38,11 +32,6 @@ export function resolveWorkspaceArchiveRedirectWorkspaceId(input: {
return rootCheckoutWorkspace.id;
}
const fallbackProjectRootPath = trimNonEmpty(archivedWorkspace.projectRootPath);
if (fallbackProjectRootPath && fallbackProjectRootPath !== archivedWorkspace.id) {
return fallbackProjectRootPath;
}
const siblingWorkspace =
sameProjectWorkspaces.find((workspace) => workspace.id !== archivedWorkspace.id) ?? null;
return siblingWorkspace?.id ?? null;
@@ -0,0 +1,135 @@
import { describe, expect, it } from "vitest";
import type { WorkspaceDescriptor } from "@/stores/session-store";
import {
getWorkspaceExecutionAuthority,
requireWorkspaceExecutionAuthority,
resolveWorkspaceIdByExecutionDirectory,
resolveWorkspaceRouteId,
} from "./workspace-execution";
function createWorkspace(
input: Partial<WorkspaceDescriptor> & Pick<WorkspaceDescriptor, "id">,
): WorkspaceDescriptor {
return {
id: input.id,
projectId: input.projectId ?? "project-1",
projectDisplayName: input.projectDisplayName ?? "Project",
projectRootPath: input.projectRootPath ?? "/repo",
workspaceDirectory: input.workspaceDirectory ?? "/repo",
projectKind: input.projectKind ?? "git",
workspaceKind: input.workspaceKind ?? "checkout",
name: input.name ?? "main",
status: input.status ?? "running",
activityAt: input.activityAt ?? null,
diffStat: input.diffStat ?? null,
};
}
describe("resolveWorkspaceRouteId", () => {
it("normalizes route workspace ids", () => {
expect(resolveWorkspaceRouteId({ routeWorkspaceId: " /tmp/repo/ " })).toBe("/tmp/repo");
});
it("returns null for empty values", () => {
expect(resolveWorkspaceRouteId({ routeWorkspaceId: " " })).toBeNull();
});
});
describe("resolveWorkspaceIdByExecutionDirectory", () => {
it("matches workspace directories", () => {
const workspaces = [
createWorkspace({
id: "workspace-1",
projectRootPath: "/repo",
workspaceDirectory: "/repo/.paseo/worktrees/feature",
}),
];
expect(
resolveWorkspaceIdByExecutionDirectory({
workspaces,
workspaceDirectory: "/repo/.paseo/worktrees/feature",
}),
).toBe("workspace-1");
});
it("does not match project root metadata", () => {
const workspaces = [
createWorkspace({
id: "workspace-1",
projectRootPath: "/repo",
workspaceDirectory: "/repo/.paseo/worktrees/feature",
}),
];
expect(
resolveWorkspaceIdByExecutionDirectory({
workspaces,
workspaceDirectory: "/repo",
}),
).toBeNull();
});
});
describe("workspace execution authority", () => {
it("returns an explicit failure when workspace id is missing", () => {
expect(
getWorkspaceExecutionAuthority({
workspaces: new Map(),
workspaceId: null,
}),
).toEqual({
ok: false,
reason: "workspace_id_missing",
message: "Workspace id is required.",
});
});
it("returns an explicit failure when workspace directory is missing", () => {
const workspaces = new Map<string, WorkspaceDescriptor>([
[
"workspace-1",
createWorkspace({
id: "workspace-1",
workspaceDirectory: " ",
projectRootPath: "/repo",
}),
],
]);
expect(
getWorkspaceExecutionAuthority({
workspaces,
workspaceId: "workspace-1",
}),
).toEqual({
ok: false,
reason: "workspace_directory_missing",
message: "Workspace directory is missing for workspace workspace-1",
});
});
it("never falls back to project root metadata", () => {
const workspaces = new Map<string, WorkspaceDescriptor>([
[
"workspace-1",
createWorkspace({
id: "workspace-1",
projectRootPath: "/repo",
workspaceDirectory: "/repo/.paseo/worktrees/feature",
}),
],
]);
expect(
requireWorkspaceExecutionAuthority({
workspaces,
workspaceId: "workspace-1",
}),
).toEqual({
workspaceId: "workspace-1",
workspaceDirectory: "/repo/.paseo/worktrees/feature",
workspace: workspaces.get("workspace-1"),
});
});
});
@@ -0,0 +1,177 @@
import type { WorkspaceDescriptor } from "@/stores/session-store";
import { normalizeWorkspaceIdentity } from "@/utils/workspace-identity";
export type WorkspaceAuthorityResult = {
workspaceId: string;
workspaceDirectory: string;
workspace: WorkspaceDescriptor;
};
export type WorkspaceExecutionAuthorityFailureReason =
| "workspace_id_missing"
| "workspace_missing"
| "workspace_directory_missing";
export type WorkspaceExecutionAuthorityResult =
| { ok: true; authority: WorkspaceAuthorityResult }
| {
ok: false;
reason: WorkspaceExecutionAuthorityFailureReason;
message: string;
};
export function resolveWorkspaceRouteId(input: {
routeWorkspaceId: string | null | undefined;
}): string | null {
return normalizeWorkspaceIdentity(input.routeWorkspaceId);
}
export function resolveWorkspaceIdByExecutionDirectory(input: {
workspaces: Iterable<WorkspaceDescriptor> | null | undefined;
workspaceDirectory: string | null | undefined;
}): string | null {
const normalizedWorkspaceDirectory = normalizeWorkspaceIdentity(input.workspaceDirectory);
if (!normalizedWorkspaceDirectory) {
return null;
}
for (const workspace of input.workspaces ?? []) {
if (normalizeWorkspaceIdentity(workspace.workspaceDirectory) === normalizedWorkspaceDirectory) {
return workspace.id;
}
}
return null;
}
export function getWorkspaceExecutionAuthority(
input:
| {
workspace: WorkspaceDescriptor | null | undefined;
}
| {
workspaces: Map<string, WorkspaceDescriptor> | undefined;
workspaceId: string | null | undefined;
},
): WorkspaceExecutionAuthorityResult {
const workspace =
"workspace" in input
? input.workspace
: (() => {
const normalizedWorkspaceId = normalizeWorkspaceIdentity(input.workspaceId);
if (!normalizedWorkspaceId) {
return null;
}
return input.workspaces?.get(normalizedWorkspaceId) ?? null;
})();
if ("workspaces" in input) {
const normalizedWorkspaceId = normalizeWorkspaceIdentity(input.workspaceId);
if (!normalizedWorkspaceId) {
return {
ok: false,
reason: "workspace_id_missing",
message: "Workspace id is required.",
};
}
}
if (!workspace) {
return {
ok: false,
reason: "workspace_missing",
message:
"workspaces" in input
? `Workspace not found: ${String(input.workspaceId ?? "")}`
: "Workspace not found.",
};
}
const workspaceDirectory = normalizeWorkspaceIdentity(workspace.workspaceDirectory);
if (!workspaceDirectory) {
return {
ok: false,
reason: "workspace_directory_missing",
message: `Workspace directory is missing for workspace ${workspace.id}`,
};
}
return {
ok: true,
authority: {
workspaceId: workspace.id,
workspaceDirectory,
workspace,
},
};
}
export function requireWorkspaceExecutionAuthority(
input:
| {
workspace: WorkspaceDescriptor | null | undefined;
}
| {
workspaces: Map<string, WorkspaceDescriptor> | undefined;
workspaceId: string | null | undefined;
},
): WorkspaceAuthorityResult {
const result = getWorkspaceExecutionAuthority(input);
if (!result.ok) {
throw new Error(result.message);
}
return result.authority;
}
export function requireWorkspaceRecordId(workspaceId: string): number {
const normalizedWorkspaceId = normalizeWorkspaceIdentity(workspaceId);
if (!normalizedWorkspaceId) {
throw new Error("Workspace ID is required");
}
const parsedWorkspaceId = Number(normalizedWorkspaceId);
if (!Number.isInteger(parsedWorkspaceId)) {
throw new Error(`Workspace ID is not a persisted record ID: ${workspaceId}`);
}
return parsedWorkspaceId;
}
export function resolveWorkspaceExecutionDirectory(input: {
workspaceDirectory: string | null | undefined;
}): string | null {
return normalizeWorkspaceIdentity(input.workspaceDirectory);
}
export function requireWorkspaceExecutionDirectory(input: {
workspaceId?: string;
workspaceDirectory: string | null | undefined;
}): string {
const workspaceDirectory = resolveWorkspaceExecutionDirectory({
workspaceDirectory: input.workspaceDirectory,
});
if (!workspaceDirectory) {
throw new Error(
input.workspaceId
? `Workspace directory is missing for workspace ${input.workspaceId}`
: "Workspace directory is missing.",
);
}
return workspaceDirectory;
}
export function resolveWorkspaceExecutionAuthority(
input:
| {
workspace: WorkspaceDescriptor | null | undefined;
}
| {
workspaces: Map<string, WorkspaceDescriptor> | undefined;
workspaceId: string | null | undefined;
},
): WorkspaceAuthorityResult | null {
const result = getWorkspaceExecutionAuthority(input);
return result.ok ? result.authority : null;
}
export const parseWorkspaceRecordId = requireWorkspaceRecordId;