refactor: rename services to scripts and extract reusable components

This commit is contained in:
Mohamed Boudra
2026-04-09 18:54:25 +07:00
parent 5cf806dc77
commit 397d454de0
48 changed files with 1356 additions and 983 deletions
@@ -1,11 +1,11 @@
import { describe, expect, it } from "vitest";
import type { WorkspaceServicePayload } from "@server/shared/messages";
import type { WorkspaceScriptPayload } from "@server/shared/messages";
import type { WorkspaceDescriptor } from "@/stores/session-store";
import { patchWorkspaceServices } from "./session-workspace-services";
import { patchWorkspaceScripts } from "./session-workspace-scripts";
function workspace(input: {
id: string;
services?: WorkspaceDescriptor["services"];
scripts?: WorkspaceDescriptor["scripts"];
}): WorkspaceDescriptor {
return {
id: input.id,
@@ -19,12 +19,12 @@ function workspace(input: {
status: "running",
activityAt: null,
diffStat: null,
services: input.services ?? [],
scripts: input.scripts ?? [],
};
}
const runningService: WorkspaceServicePayload = {
serviceName: "web",
const runningScript: WorkspaceScriptPayload = {
scriptName: "web",
hostname: "main.web.localhost",
port: 3000,
url: "http://main.web.localhost:6767",
@@ -32,21 +32,21 @@ const runningService: WorkspaceServicePayload = {
health: "healthy",
};
describe("patchWorkspaceServices", () => {
it("patches only the matching workspace services", () => {
const other = workspace({ id: "/repo/other", services: [] });
describe("patchWorkspaceScripts", () => {
it("patches only the matching workspace scripts", () => {
const other = workspace({ id: "/repo/other", scripts: [] });
const current = new Map<string, WorkspaceDescriptor>([
["/repo/main", workspace({ id: "/repo/main", services: [] })],
["/repo/main", workspace({ id: "/repo/main", scripts: [] })],
[other.id, other],
]);
const next = patchWorkspaceServices(current, {
const next = patchWorkspaceScripts(current, {
workspaceId: "/repo/main",
services: [runningService],
scripts: [runningScript],
});
expect(next).not.toBe(current);
expect(next.get("/repo/main")?.services).toEqual([runningService]);
expect(next.get("/repo/main")?.scripts).toEqual([runningScript]);
expect(next.get("/repo/other")).toBe(other);
});
@@ -56,7 +56,7 @@ describe("patchWorkspaceServices", () => {
"42",
workspace({
id: "42",
services: [],
scripts: [],
}),
],
]);
@@ -66,26 +66,26 @@ describe("patchWorkspaceServices", () => {
workspaceDirectory: "C:\\repo\\main\\",
});
const next = patchWorkspaceServices(current, {
const next = patchWorkspaceScripts(current, {
workspaceId: "C:/repo/main",
services: [runningService],
scripts: [runningScript],
});
expect(next).not.toBe(current);
expect(next.get("42")?.services).toEqual([runningService]);
expect(next.get("42")?.scripts).toEqual([runningScript]);
});
it("ignores updates for unknown workspaces", () => {
const current = new Map<string, WorkspaceDescriptor>([
["/repo/main", workspace({ id: "/repo/main", services: [] })],
["/repo/main", workspace({ id: "/repo/main", scripts: [] })],
]);
const next = patchWorkspaceServices(current, {
const next = patchWorkspaceScripts(current, {
workspaceId: "/repo/missing",
services: [runningService],
scripts: [runningScript],
});
expect(next).toBe(current);
expect(next.get("/repo/main")?.services).toEqual([]);
expect(next.get("/repo/main")?.scripts).toEqual([]);
});
});
@@ -53,7 +53,7 @@ import { resolveProjectPlacement } from "@/utils/project-placement";
import { buildDraftStoreKey } from "@/stores/draft-keys";
import type { AttachmentMetadata } from "@/attachments/types";
import { reconcilePreviousAgentStatuses } from "@/contexts/session-status-tracking";
import { patchWorkspaceServices } from "@/contexts/session-workspace-services";
import { patchWorkspaceScripts } from "@/contexts/session-workspace-scripts";
// Re-export types from session-store and draft-store for backward compatibility
export type { DraftInput } from "@/stores/draft-store";
@@ -1168,9 +1168,9 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
mergeWorkspaces(serverId, [normalizeWorkspaceDescriptor(message.payload.workspace)]);
});
const unsubServiceStatusUpdate = client.on("service_status_update", (message) => {
if (message.type !== "service_status_update") return;
setWorkspaces(serverId, (prev) => patchWorkspaceServices(prev, message.payload));
const unsubScriptStatusUpdate = client.on("script_status_update", (message) => {
if (message.type !== "script_status_update") return;
setWorkspaces(serverId, (prev) => patchWorkspaceScripts(prev, message.payload));
});
const unsubWorkspaceSetupProgress = client.on("workspace_setup_progress", (message) => {
@@ -1538,7 +1538,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
unsubAgentStream();
unsubAgentTimeline();
unsubWorkspaceUpdate();
unsubServiceStatusUpdate();
unsubScriptStatusUpdate();
unsubWorkspaceSetupProgress();
unsubWorkspaceSetupStatusResponse();
unsubStatus();
@@ -1,10 +1,10 @@
import type { ServiceStatusUpdateMessage } from "@server/shared/messages";
import type { ScriptStatusUpdateMessage } from "@server/shared/messages";
import type { WorkspaceDescriptor } from "@/stores/session-store";
import { resolveWorkspaceMapKeyByIdentity } from "@/utils/workspace-execution";
export function patchWorkspaceServices(
export function patchWorkspaceScripts(
workspaces: Map<string, WorkspaceDescriptor>,
update: ServiceStatusUpdateMessage["payload"],
update: ScriptStatusUpdateMessage["payload"],
): Map<string, WorkspaceDescriptor> {
const workspaceKey = resolveWorkspaceMapKeyByIdentity({
workspaces,
@@ -22,7 +22,7 @@ export function patchWorkspaceServices(
const next = new Map(workspaces);
next.set(workspaceKey, {
...existing,
services: update.services.map((s) => ({ ...s })),
scripts: update.scripts.map((s) => ({ ...s })),
});
return next;
}