test(agent-manager): cover multi-project setup terminals

This commit is contained in:
marius-kilocode
2026-07-30 18:21:48 +02:00
parent 1856f20ba4
commit 59bfcfd385
4 changed files with 85 additions and 5 deletions
@@ -197,6 +197,45 @@ describe("Agent Manager terminal state", () => {
})
})
it("hydrates script terminals into independent project contexts", () => {
createRoot((dispose) => {
const item = scene()
item.dispatch({
type: "agentManager.scriptTerminals",
terminals: [
{
terminalId: "script:setup-a",
projectId: "prj-a",
worktreeId: "wt-1",
kind: "setup",
title: "Setup",
wsUrl: "ws://script:setup-a",
state: "running",
font,
},
{
terminalId: "script:setup-b",
projectId: "prj-b",
worktreeId: "wt-1",
kind: "setup",
title: "Setup",
wsUrl: "ws://script:setup-b",
state: "running",
font,
},
],
} satisfies ExtensionMessage)
expect(item.state.sidesForContext("prj-a:wt-1").map((term) => term.id)).toEqual(["script:setup-a"])
expect(item.state.sidesForContext("prj-b:wt-1").map((term) => term.id)).toEqual(["script:setup-b"])
expect(item.events.running).toEqual([
{ contextKey: "prj-a:wt-1", terminalId: "script:setup-a" },
{ contextKey: "prj-b:wt-1", terminalId: "script:setup-b" },
])
dispose()
})
})
it("activates a Setup terminal that hydrates before its worktree is selected", () => {
createRoot((dispose) => {
const item = scene(LOCAL)
@@ -156,6 +156,32 @@ describe("ScriptTerminalManager", () => {
expect(ctx.snapshots.at(-1)?.[0]?.worktreeId).toBeNull()
})
it("keeps identical worktree script terminals independent across projects", async () => {
let id = 0
const ctx = harness({
create: async () => ({
data: { location: { directory: config.cwd }, data: { ...info(), id: `pty-${++id}` } },
}),
get: async () => ({
data: { location: { directory: config.cwd }, data: { ...info(), id: `pty-${id}` } },
}),
})
await ctx.manager.start("setup", { ...config, projectId: "prj-a" }, () => undefined)
await ctx.manager.start("setup", { ...config, projectId: "prj-b" }, () => undefined)
expect(ctx.snapshots.at(-1)).toEqual([
expect.objectContaining({ projectId: "prj-a", worktreeId: "wt-1", kind: "setup" }),
expect.objectContaining({ projectId: "prj-b", worktreeId: "wt-1", kind: "setup" }),
])
expect(ctx.manager.active("setup", "wt-1", "prj-a")).toBe(true)
expect(ctx.manager.active("setup", "wt-1", "prj-b")).toBe(true)
await ctx.manager.clear("setup", "wt-1", "prj-a")
expect(ctx.manager.active("setup", "wt-1", "prj-a")).toBe(false)
expect(ctx.manager.active("setup", "wt-1", "prj-b")).toBe(true)
})
it("builds canonical authenticated replay URLs", () => {
const value = buildScriptTerminalWsUrl(
{ baseUrl: "http://127.0.0.1:4096", password: "secret" },
@@ -312,7 +312,10 @@ describe("runWorktreeSetupScript", () => {
return dir
}
function flow(script: boolean, opts?: { destination?: "vscode" | "agentManager"; code?: number }) {
function flow(
script: boolean,
opts?: { destination?: "vscode" | "agentManager"; code?: number; projectId?: string },
) {
const posted: AgentManagerOutMessage[] = []
const runs: string[] = []
const ctx = harness()
@@ -323,6 +326,7 @@ describe("runWorktreeSetupScript", () => {
const input = {
service: new SetupScriptService(root(script)),
destination: opts?.destination ?? ("vscode" as const),
projectId: opts?.projectId,
worktreeId: "wt-1",
trusted: () => true,
manager: ctx.manager,
@@ -349,6 +353,17 @@ describe("runWorktreeSetupScript", () => {
expect(scene.runs).toEqual(["/repo/worktree"])
})
it("stamps progress and embedded terminals with the owning project", async () => {
const scene = flow(true, { destination: "agentManager", projectId: "prj-a" })
const result = runWorktreeSetupScript(scene.input, { worktreePath: "/repo/worktree", repoPath: "/repo" })
await new Promise((resolve) => setTimeout(resolve, 0))
expect(scene.posted[0]).toMatchObject({ projectId: "prj-a", worktreeId: "wt-1" })
expect(scene.ctx.starts[0]?.config).toMatchObject({ projectId: "prj-a", worktreeId: "wt-1" })
scene.ctx.starts[0]?.done({ exitCode: 0 })
await result
})
it("stays silent when no setup script is configured", async () => {
const scene = flow(false)
await runWorktreeSetupScript(scene.input, { worktreePath: "/repo/worktree", repoPath: "/repo" })
@@ -2358,10 +2358,10 @@ const AgentManagerContent: Component = () => {
terminalDestination={sideCtl.destination}
terminalDestinationActive={() => sidePanel() === "terminal"}
terminalKeybind={() => kb().showTerminal ?? ""}
onTerminalDestinationOpen={() => {
cancelAmbientSetup()
sideCtl.openPreferred("tab_toolbar")
}}
onTerminalDestinationOpen={() => {
cancelAmbientSetup()
sideCtl.openPreferred("tab_toolbar")
}}
onTerminalDestinationChoose={sideCtl.choose}
track={metrics.click}
/>