kanban 0.1.18 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/server/shutdown-coordinator.d.ts.map +1 -1
- package/dist/server/shutdown-coordinator.js +53 -11
- package/dist/server/shutdown-coordinator.js.map +1 -1
- package/dist/web-ui/assets/{index-DC27EU_m.js → index-BW6yopCq.js} +961 -970
- package/dist/web-ui/index.html +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -381,7 +381,7 @@ async function runMainCommand(options) {
|
|
|
381
381
|
}
|
|
382
382
|
};
|
|
383
383
|
closeWithGrace({
|
|
384
|
-
delay:
|
|
384
|
+
delay: 10000,
|
|
385
385
|
skip: ["uncaughtException", "unhandledRejection", "beforeExit"],
|
|
386
386
|
onTimeout: (delayMs) => {
|
|
387
387
|
console.error(`Forced exit after shutdown timeout (${delayMs}ms).`);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { stat } from \"node:fs/promises\";\nimport { createServer as createNetServer } from \"node:net\";\nimport closeWithGrace from \"close-with-grace\";\nimport { Command } from \"commander\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { registerHooksCommand } from \"./commands/hooks.js\";\nimport { registerTaskCommand } from \"./commands/task.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport type { RuntimeAgentId, RuntimeCommandRunResponse } from \"./core/api-contract.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tDEFAULT_KANBAN_RUNTIME_PORT,\n\tgetKanbanRuntimeOrigin,\n\tgetKanbanRuntimePort,\n\tparseRuntimePort,\n\tsetKanbanRuntimePort,\n} from \"./core/runtime-endpoint.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { pickDirectoryPathFromSystemDialog } from \"./server/directory-picker.js\";\nimport { terminateProcessForTimeout } from \"./server/process-termination.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval, createWorkspaceRegistry } from \"./server/workspace-registry.js\";\nimport { installKanbanSkillFiles, resolveKanbanSkillCommandPrefix } from \"./skills/kanban-skill.js\";\nimport { loadWorkspaceContext } from \"./state/workspace-state.js\";\nimport { detectInstalledCommands } from \"./terminal/agent-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup, runPendingAutoUpdateOnShutdown } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\tnoOpen: boolean;\n\tskipShutdownCleanup: boolean;\n\tagent: RuntimeAgentId | null;\n\tport: { mode: \"fixed\"; value: number } | { mode: \"auto\" } | null;\n}\n\nconst CLI_AGENT_IDS: readonly RuntimeAgentId[] = [\"claude\", \"codex\", \"gemini\", \"opencode\", \"droid\", \"cline\"];\nconst KANBAN_VERSION = typeof packageJson.version === \"string\" ? packageJson.version : \"0.1.0\";\n\nfunction parseCliAgentId(value: string): RuntimeAgentId {\n\tconst normalized = value.trim().toLowerCase();\n\tif (\n\t\tnormalized === \"claude\" ||\n\t\tnormalized === \"codex\" ||\n\t\tnormalized === \"gemini\" ||\n\t\tnormalized === \"opencode\" ||\n\t\tnormalized === \"droid\" ||\n\t\tnormalized === \"cline\"\n\t) {\n\t\treturn normalized;\n\t}\n\tthrow new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nfunction parseCliPortValue(rawValue: string): { mode: \"fixed\"; value: number } | { mode: \"auto\" } {\n\tconst normalized = rawValue.trim().toLowerCase();\n\tif (!normalized) {\n\t\tthrow new Error(\"Missing value for --port.\");\n\t}\n\tif (normalized === \"auto\") {\n\t\treturn { mode: \"auto\" };\n\t}\n\ttry {\n\t\treturn { mode: \"fixed\", value: parseRuntimePort(normalized) };\n\t} catch {\n\t\tthrow new Error(`Invalid port value: ${rawValue}. Expected an integer from 1-65535 or \"auto\".`);\n\t}\n}\n\ninterface RootCommandOptions {\n\tagent?: RuntimeAgentId;\n\tport?: { mode: \"fixed\"; value: number } | { mode: \"auto\" };\n\topen?: boolean;\n\tskipShutdownCleanup?: boolean;\n}\n\nasync function isPortAvailable(port: number): Promise<boolean> {\n\treturn await new Promise<boolean>((resolve) => {\n\t\tconst probe = createNetServer();\n\t\tprobe.once(\"error\", () => {\n\t\t\tresolve(false);\n\t\t});\n\t\tprobe.listen(port, \"127.0.0.1\", () => {\n\t\t\tprobe.close(() => {\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function findAvailableRuntimePort(startPort: number): Promise<number> {\n\tfor (let candidate = startPort; candidate <= 65535; candidate += 1) {\n\t\tif (await isPortAvailable(candidate)) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\tthrow new Error(\"No available runtime port found.\");\n}\n\nasync function applyRuntimePortOption(portOption: CliOptions[\"port\"]): Promise<number | null> {\n\tif (!portOption) {\n\t\treturn null;\n\t}\n\tif (portOption.mode === \"fixed\") {\n\t\tsetKanbanRuntimePort(portOption.value);\n\t\treturn portOption.value;\n\t}\n\tconst autoPort = await findAvailableRuntimePort(DEFAULT_KANBAN_RUNTIME_PORT);\n\tsetKanbanRuntimePort(autoPort);\n\treturn autoPort;\n}\n\nasync function persistCliAgentSelection(cwd: string, selectedAgentId: RuntimeAgentId): Promise<boolean> {\n\tconst currentRuntimeConfig = await loadRuntimeConfig(cwd);\n\tif (currentRuntimeConfig.selectedAgentId === selectedAgentId) {\n\t\treturn false;\n\t}\n\tawait updateRuntimeConfig(cwd, { selectedAgentId });\n\treturn true;\n}\n\nasync function assertPathIsDirectory(path: string): Promise<void> {\n\tconst info = await stat(path);\n\tif (!info.isDirectory()) {\n\t\tthrow new Error(`Project path is not a directory: ${path}`);\n\t}\n}\n\nasync function pathIsDirectory(path: string): Promise<boolean> {\n\ttry {\n\t\tconst info = await stat(path);\n\t\treturn info.isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction hasGitRepository(path: string): boolean {\n\tconst result = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n\t\tcwd: path,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\treturn result.status === 0 && result.stdout.trim() === \"true\";\n}\n\nfunction isAddressInUseError(error: unknown): error is NodeJS.ErrnoException {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as NodeJS.ErrnoException).code === \"EADDRINUSE\"\n\t);\n}\n\nasync function canReachKanbanServer(workspaceId: string | null): Promise<boolean> {\n\ttry {\n\t\tconst headers: Record<string, string> = {};\n\t\tif (workspaceId) {\n\t\t\theaders[\"x-kanban-workspace-id\"] = workspaceId;\n\t\t}\n\t\tconst response = await fetch(buildKanbanRuntimeUrl(\"/api/trpc/projects.list\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders,\n\t\t\tsignal: AbortSignal.timeout(1_500),\n\t\t});\n\t\tif (response.status === 404) {\n\t\t\treturn false;\n\t\t}\n\t\tconst payload = (await response.json().catch(() => null)) as {\n\t\t\tresult?: { data?: unknown };\n\t\t\terror?: unknown;\n\t\t} | null;\n\t\treturn Boolean(payload && (payload.result || payload.error));\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function tryOpenExistingServer(noOpen: boolean): Promise<boolean> {\n\tlet workspaceId: string | null = null;\n\tif (hasGitRepository(process.cwd())) {\n\t\tconst context = await loadWorkspaceContext(process.cwd());\n\t\tworkspaceId = context.workspaceId;\n\t}\n\tconst running = await canReachKanbanServer(workspaceId);\n\tif (!running) {\n\t\treturn false;\n\t}\n\tconst projectUrl = workspaceId\n\t\t? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)\n\t\t: getKanbanRuntimeOrigin();\n\tconsole.log(`Kanban already running at ${getKanbanRuntimeOrigin()}`);\n\tif (!noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(projectUrl, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(`Project URL: ${projectUrl}`);\n\treturn true;\n}\n\nasync function runScopedCommand(command: string, cwd: string): Promise<RuntimeCommandRunResponse> {\n\tconst startedAt = Date.now();\n\tconst outputLimitBytes = 64 * 1024;\n\n\treturn await new Promise<RuntimeCommandRunResponse>((resolve, reject) => {\n\t\tconst child = spawn(command, {\n\t\t\tcwd,\n\t\t\tshell: true,\n\t\t\tenv: process.env,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tif (!child.stdout || !child.stderr) {\n\t\t\treject(new Error(\"Shortcut process did not expose stdout/stderr.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tconst appendOutput = (current: string, chunk: string): string => {\n\t\t\tconst next = current + chunk;\n\t\t\tif (next.length <= outputLimitBytes) {\n\t\t\t\treturn next;\n\t\t\t}\n\t\t\treturn next.slice(0, outputLimitBytes);\n\t\t};\n\n\t\tchild.stdout.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstdout = appendOutput(stdout, String(chunk));\n\t\t});\n\n\t\tchild.stderr.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstderr = appendOutput(stderr, String(chunk));\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(error);\n\t\t});\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tterminateProcessForTimeout(child);\n\t\t}, 60_000);\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tconst exitCode = typeof code === \"number\" ? code : 1;\n\t\t\tconst combinedOutput = [stdout.trim(), stderr.trim()].filter(Boolean).join(\"\\n\");\n\t\t\tresolve({\n\t\t\t\texitCode,\n\t\t\t\tstdout: stdout.trim(),\n\t\t\t\tstderr: stderr.trim(),\n\t\t\t\tcombinedOutput,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function startServer(): Promise<{\n\turl: string;\n\tclose: () => Promise<void>;\n\tshutdown: (options?: { skipSessionCleanup?: boolean }) => Promise<void>;\n}> {\n\tlet runtimeStateHub: ReturnType<typeof createRuntimeStateHub> | undefined;\n\tconst workspaceRegistry = await createWorkspaceRegistry({\n\t\tcwd: process.cwd(),\n\t\tloadRuntimeConfig,\n\t\thasGitRepository,\n\t\tpathIsDirectory,\n\t\tonTerminalManagerReady: (workspaceId, manager) => {\n\t\t\truntimeStateHub?.trackTerminalManager(workspaceId, manager);\n\t\t},\n\t});\n\truntimeStateHub = createRuntimeStateHub({\n\t\tworkspaceRegistry,\n\t});\n\tconst runtimeHub = runtimeStateHub;\n\tfor (const { workspaceId, terminalManager } of workspaceRegistry.listManagedWorkspaces()) {\n\t\truntimeHub.trackTerminalManager(workspaceId, terminalManager);\n\t}\n\n\tconst disposeTrackedWorkspace = (\n\t\tworkspaceId: string,\n\t\toptions?: {\n\t\t\tstopTerminalSessions?: boolean;\n\t\t},\n\t): { terminalManager: TerminalSessionManager | null; workspacePath: string | null } => {\n\t\tconst disposed = workspaceRegistry.disposeWorkspace(workspaceId, {\n\t\t\tstopTerminalSessions: options?.stopTerminalSessions,\n\t\t});\n\t\truntimeHub.disposeWorkspace(workspaceId);\n\t\treturn disposed;\n\t};\n\n\tconst runtimeServer = await createRuntimeServer({\n\t\tworkspaceRegistry,\n\t\truntimeStateHub: runtimeHub,\n\t\twarn: (message) => {\n\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t},\n\t\tensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,\n\t\tresolveInteractiveShellCommand,\n\t\trunCommand: runScopedCommand,\n\t\tresolveProjectInputPath,\n\t\tassertPathIsDirectory,\n\t\thasGitRepository,\n\t\tdisposeWorkspace: disposeTrackedWorkspace,\n\t\tcollectProjectWorktreeTaskIdsForRemoval,\n\t\tpickDirectoryPathFromSystemDialog,\n\t});\n\n\tconst close = async () => {\n\t\tawait runtimeServer.close();\n\t};\n\n\tconst shutdown = async (options?: { skipSessionCleanup?: boolean }) => {\n\t\tawait shutdownRuntimeServer({\n\t\t\tworkspaceRegistry,\n\t\t\twarn: (message) => {\n\t\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t\t},\n\t\t\tcloseRuntimeServer: close,\n\t\t\tskipSessionCleanup: options?.skipSessionCleanup ?? false,\n\t\t});\n\t};\n\n\treturn {\n\t\turl: runtimeServer.url,\n\t\tclose,\n\t\tshutdown,\n\t};\n}\n\nasync function startServerWithAutoPortRetry(options: CliOptions): Promise<Awaited<ReturnType<typeof startServer>>> {\n\tif (options.port?.mode !== \"auto\") {\n\t\treturn await startServer();\n\t}\n\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await startServer();\n\t\t} catch (error) {\n\t\t\tif (!isAddressInUseError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst currentPort = getKanbanRuntimePort();\n\t\t\tconst retryPort = await findAvailableRuntimePort(currentPort + 1);\n\t\t\tsetKanbanRuntimePort(retryPort);\n\t\t\tconsole.warn(`Runtime port ${currentPort} became busy during startup, retrying on ${retryPort}.`);\n\t\t}\n\t}\n}\n\nasync function runMainCommand(options: CliOptions): Promise<void> {\n\tconst selectedPort = await applyRuntimePortOption(options.port);\n\tif (selectedPort !== null) {\n\t\tconsole.log(`Using runtime port ${selectedPort}.`);\n\t}\n\n\tautoUpdateOnStartup({\n\t\tcurrentVersion: KANBAN_VERSION,\n\t});\n\n\tif (options.agent) {\n\t\tconst didChange = await persistCliAgentSelection(process.cwd(), options.agent);\n\t\tif (didChange) {\n\t\t\tconsole.log(`Default agent set to ${options.agent}.`);\n\t\t}\n\t}\n\n\ttry {\n\t\tconst detectedCommands = detectInstalledCommands();\n\t\tconst commandPrefix = resolveKanbanSkillCommandPrefix({\n\t\t\tcurrentVersion: KANBAN_VERSION,\n\t\t});\n\t\tawait installKanbanSkillFiles({\n\t\t\tcommandPrefix,\n\t\t\tinstallClaudeSkill: detectedCommands.includes(\"claude\"),\n\t\t});\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(`Could not install Kanban skill files: ${message}`);\n\t}\n\n\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServerWithAutoPortRetry(options);\n\t} catch (error) {\n\t\tif (\n\t\t\toptions.port?.mode !== \"auto\" &&\n\t\t\tisAddressInUseError(error) &&\n\t\t\t(await tryOpenExistingServer(options.noOpen))\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tthrow error;\n\t}\n\tconsole.log(`Kanban running at ${runtime.url}`);\n\tif (!options.noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(runtime.url, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(\"Press Ctrl+C to stop.\");\n\n\tlet isShuttingDown = false;\n\tconst shutdown = async (signal: NodeJS.Signals | null) => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\trunPendingAutoUpdateOnShutdown();\n\t\ttry {\n\t\t\tif (options.skipShutdownCleanup) {\n\t\t\t\tconsole.warn(\"Skipping shutdown task cleanup for this instance.\");\n\t\t\t}\n\t\t\tawait runtime.shutdown({\n\t\t\t\tskipSessionCleanup: options.skipShutdownCleanup,\n\t\t\t});\n\t\t\tprocess.exit(signal ? 130 : 0);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(`Shutdown failed: ${message}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t};\n\n\tcloseWithGrace(\n\t\t{\n\t\t\tdelay: 3000,\n\t\t\tskip: [\"uncaughtException\", \"unhandledRejection\", \"beforeExit\"],\n\t\t\tonTimeout: (delayMs) => {\n\t\t\t\tconsole.error(`Forced exit after shutdown timeout (${delayMs}ms).`);\n\t\t\t},\n\t\t\tonSecondSignal: (signal) => {\n\t\t\t\tconsole.error(`Forced exit on second signal: ${signal}`);\n\t\t\t},\n\t\t},\n\t\tasync ({ signal }) => {\n\t\t\tawait shutdown(signal ?? null);\n\t\t},\n\t);\n}\n\nfunction createProgram(): Command {\n\tconst program = new Command();\n\tprogram\n\t\t.name(\"kanban\")\n\t\t.description(\"Local orchestration board for coding agents.\")\n\t\t.version(KANBAN_VERSION, \"-v, --version\", \"Output the version number\")\n\t\t.option(\"--agent <id>\", `Default agent ID (${CLI_AGENT_IDS.join(\", \")}).`, parseCliAgentId)\n\t\t.option(\"--port <number|auto>\", \"Runtime port (1-65535) or auto.\", parseCliPortValue)\n\t\t.option(\"--no-open\", \"Do not open browser automatically.\")\n\t\t.option(\"--skip-shutdown-cleanup\", \"Do not move sessions to trash or delete task worktrees on shutdown.\")\n\t\t.showHelpAfterError()\n\t\t.addHelpText(\"after\", `\\nRuntime URL: ${getKanbanRuntimeOrigin()}\\nAgent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\n\n\tregisterTaskCommand(program);\n\tregisterHooksCommand(program);\n\n\tprogram\n\t\t.command(\"mcp\")\n\t\t.description(\"Deprecated compatibility command.\")\n\t\t.action(() => {\n\t\t\tconsole.warn(\"Deprecated. Please uninstall Kanban MCP.\");\n\t\t});\n\n\tprogram.action(async (options: RootCommandOptions) => {\n\t\tawait runMainCommand({\n\t\t\tagent: options.agent ?? null,\n\t\t\tport: options.port ?? null,\n\t\t\tnoOpen: options.open === false,\n\t\t\tskipShutdownCleanup: options.skipShutdownCleanup === true,\n\t\t});\n\t});\n\n\treturn program;\n}\n\nasync function run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tconst program = createProgram();\n\tawait program.parseAsync(argv, { from: \"user\" });\n}\n\nrun().catch((error) => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\tconsole.error(`Failed to start Kanban: ${message}`);\n\tprocess.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { stat } from \"node:fs/promises\";\nimport { createServer as createNetServer } from \"node:net\";\nimport closeWithGrace from \"close-with-grace\";\nimport { Command } from \"commander\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { registerHooksCommand } from \"./commands/hooks.js\";\nimport { registerTaskCommand } from \"./commands/task.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport type { RuntimeAgentId, RuntimeCommandRunResponse } from \"./core/api-contract.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tDEFAULT_KANBAN_RUNTIME_PORT,\n\tgetKanbanRuntimeOrigin,\n\tgetKanbanRuntimePort,\n\tparseRuntimePort,\n\tsetKanbanRuntimePort,\n} from \"./core/runtime-endpoint.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { pickDirectoryPathFromSystemDialog } from \"./server/directory-picker.js\";\nimport { terminateProcessForTimeout } from \"./server/process-termination.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval, createWorkspaceRegistry } from \"./server/workspace-registry.js\";\nimport { installKanbanSkillFiles, resolveKanbanSkillCommandPrefix } from \"./skills/kanban-skill.js\";\nimport { loadWorkspaceContext } from \"./state/workspace-state.js\";\nimport { detectInstalledCommands } from \"./terminal/agent-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup, runPendingAutoUpdateOnShutdown } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\tnoOpen: boolean;\n\tskipShutdownCleanup: boolean;\n\tagent: RuntimeAgentId | null;\n\tport: { mode: \"fixed\"; value: number } | { mode: \"auto\" } | null;\n}\n\nconst CLI_AGENT_IDS: readonly RuntimeAgentId[] = [\"claude\", \"codex\", \"gemini\", \"opencode\", \"droid\", \"cline\"];\nconst KANBAN_VERSION = typeof packageJson.version === \"string\" ? packageJson.version : \"0.1.0\";\n\nfunction parseCliAgentId(value: string): RuntimeAgentId {\n\tconst normalized = value.trim().toLowerCase();\n\tif (\n\t\tnormalized === \"claude\" ||\n\t\tnormalized === \"codex\" ||\n\t\tnormalized === \"gemini\" ||\n\t\tnormalized === \"opencode\" ||\n\t\tnormalized === \"droid\" ||\n\t\tnormalized === \"cline\"\n\t) {\n\t\treturn normalized;\n\t}\n\tthrow new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(\", \")}`);\n}\n\nfunction parseCliPortValue(rawValue: string): { mode: \"fixed\"; value: number } | { mode: \"auto\" } {\n\tconst normalized = rawValue.trim().toLowerCase();\n\tif (!normalized) {\n\t\tthrow new Error(\"Missing value for --port.\");\n\t}\n\tif (normalized === \"auto\") {\n\t\treturn { mode: \"auto\" };\n\t}\n\ttry {\n\t\treturn { mode: \"fixed\", value: parseRuntimePort(normalized) };\n\t} catch {\n\t\tthrow new Error(`Invalid port value: ${rawValue}. Expected an integer from 1-65535 or \"auto\".`);\n\t}\n}\n\ninterface RootCommandOptions {\n\tagent?: RuntimeAgentId;\n\tport?: { mode: \"fixed\"; value: number } | { mode: \"auto\" };\n\topen?: boolean;\n\tskipShutdownCleanup?: boolean;\n}\n\nasync function isPortAvailable(port: number): Promise<boolean> {\n\treturn await new Promise<boolean>((resolve) => {\n\t\tconst probe = createNetServer();\n\t\tprobe.once(\"error\", () => {\n\t\t\tresolve(false);\n\t\t});\n\t\tprobe.listen(port, \"127.0.0.1\", () => {\n\t\t\tprobe.close(() => {\n\t\t\t\tresolve(true);\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function findAvailableRuntimePort(startPort: number): Promise<number> {\n\tfor (let candidate = startPort; candidate <= 65535; candidate += 1) {\n\t\tif (await isPortAvailable(candidate)) {\n\t\t\treturn candidate;\n\t\t}\n\t}\n\tthrow new Error(\"No available runtime port found.\");\n}\n\nasync function applyRuntimePortOption(portOption: CliOptions[\"port\"]): Promise<number | null> {\n\tif (!portOption) {\n\t\treturn null;\n\t}\n\tif (portOption.mode === \"fixed\") {\n\t\tsetKanbanRuntimePort(portOption.value);\n\t\treturn portOption.value;\n\t}\n\tconst autoPort = await findAvailableRuntimePort(DEFAULT_KANBAN_RUNTIME_PORT);\n\tsetKanbanRuntimePort(autoPort);\n\treturn autoPort;\n}\n\nasync function persistCliAgentSelection(cwd: string, selectedAgentId: RuntimeAgentId): Promise<boolean> {\n\tconst currentRuntimeConfig = await loadRuntimeConfig(cwd);\n\tif (currentRuntimeConfig.selectedAgentId === selectedAgentId) {\n\t\treturn false;\n\t}\n\tawait updateRuntimeConfig(cwd, { selectedAgentId });\n\treturn true;\n}\n\nasync function assertPathIsDirectory(path: string): Promise<void> {\n\tconst info = await stat(path);\n\tif (!info.isDirectory()) {\n\t\tthrow new Error(`Project path is not a directory: ${path}`);\n\t}\n}\n\nasync function pathIsDirectory(path: string): Promise<boolean> {\n\ttry {\n\t\tconst info = await stat(path);\n\t\treturn info.isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction hasGitRepository(path: string): boolean {\n\tconst result = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n\t\tcwd: path,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\tenv: createGitProcessEnv(),\n\t});\n\treturn result.status === 0 && result.stdout.trim() === \"true\";\n}\n\nfunction isAddressInUseError(error: unknown): error is NodeJS.ErrnoException {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as NodeJS.ErrnoException).code === \"EADDRINUSE\"\n\t);\n}\n\nasync function canReachKanbanServer(workspaceId: string | null): Promise<boolean> {\n\ttry {\n\t\tconst headers: Record<string, string> = {};\n\t\tif (workspaceId) {\n\t\t\theaders[\"x-kanban-workspace-id\"] = workspaceId;\n\t\t}\n\t\tconst response = await fetch(buildKanbanRuntimeUrl(\"/api/trpc/projects.list\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders,\n\t\t\tsignal: AbortSignal.timeout(1_500),\n\t\t});\n\t\tif (response.status === 404) {\n\t\t\treturn false;\n\t\t}\n\t\tconst payload = (await response.json().catch(() => null)) as {\n\t\t\tresult?: { data?: unknown };\n\t\t\terror?: unknown;\n\t\t} | null;\n\t\treturn Boolean(payload && (payload.result || payload.error));\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function tryOpenExistingServer(noOpen: boolean): Promise<boolean> {\n\tlet workspaceId: string | null = null;\n\tif (hasGitRepository(process.cwd())) {\n\t\tconst context = await loadWorkspaceContext(process.cwd());\n\t\tworkspaceId = context.workspaceId;\n\t}\n\tconst running = await canReachKanbanServer(workspaceId);\n\tif (!running) {\n\t\treturn false;\n\t}\n\tconst projectUrl = workspaceId\n\t\t? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)\n\t\t: getKanbanRuntimeOrigin();\n\tconsole.log(`Kanban already running at ${getKanbanRuntimeOrigin()}`);\n\tif (!noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(projectUrl, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(`Project URL: ${projectUrl}`);\n\treturn true;\n}\n\nasync function runScopedCommand(command: string, cwd: string): Promise<RuntimeCommandRunResponse> {\n\tconst startedAt = Date.now();\n\tconst outputLimitBytes = 64 * 1024;\n\n\treturn await new Promise<RuntimeCommandRunResponse>((resolve, reject) => {\n\t\tconst child = spawn(command, {\n\t\t\tcwd,\n\t\t\tshell: true,\n\t\t\tenv: process.env,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tif (!child.stdout || !child.stderr) {\n\t\t\treject(new Error(\"Shortcut process did not expose stdout/stderr.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tconst appendOutput = (current: string, chunk: string): string => {\n\t\t\tconst next = current + chunk;\n\t\t\tif (next.length <= outputLimitBytes) {\n\t\t\t\treturn next;\n\t\t\t}\n\t\t\treturn next.slice(0, outputLimitBytes);\n\t\t};\n\n\t\tchild.stdout.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstdout = appendOutput(stdout, String(chunk));\n\t\t});\n\n\t\tchild.stderr.on(\"data\", (chunk: Buffer | string) => {\n\t\t\tstderr = appendOutput(stderr, String(chunk));\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(error);\n\t\t});\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tterminateProcessForTimeout(child);\n\t\t}, 60_000);\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tclearTimeout(timeout);\n\t\t\tconst exitCode = typeof code === \"number\" ? code : 1;\n\t\t\tconst combinedOutput = [stdout.trim(), stderr.trim()].filter(Boolean).join(\"\\n\");\n\t\t\tresolve({\n\t\t\t\texitCode,\n\t\t\t\tstdout: stdout.trim(),\n\t\t\t\tstderr: stderr.trim(),\n\t\t\t\tcombinedOutput,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function startServer(): Promise<{\n\turl: string;\n\tclose: () => Promise<void>;\n\tshutdown: (options?: { skipSessionCleanup?: boolean }) => Promise<void>;\n}> {\n\tlet runtimeStateHub: ReturnType<typeof createRuntimeStateHub> | undefined;\n\tconst workspaceRegistry = await createWorkspaceRegistry({\n\t\tcwd: process.cwd(),\n\t\tloadRuntimeConfig,\n\t\thasGitRepository,\n\t\tpathIsDirectory,\n\t\tonTerminalManagerReady: (workspaceId, manager) => {\n\t\t\truntimeStateHub?.trackTerminalManager(workspaceId, manager);\n\t\t},\n\t});\n\truntimeStateHub = createRuntimeStateHub({\n\t\tworkspaceRegistry,\n\t});\n\tconst runtimeHub = runtimeStateHub;\n\tfor (const { workspaceId, terminalManager } of workspaceRegistry.listManagedWorkspaces()) {\n\t\truntimeHub.trackTerminalManager(workspaceId, terminalManager);\n\t}\n\n\tconst disposeTrackedWorkspace = (\n\t\tworkspaceId: string,\n\t\toptions?: {\n\t\t\tstopTerminalSessions?: boolean;\n\t\t},\n\t): { terminalManager: TerminalSessionManager | null; workspacePath: string | null } => {\n\t\tconst disposed = workspaceRegistry.disposeWorkspace(workspaceId, {\n\t\t\tstopTerminalSessions: options?.stopTerminalSessions,\n\t\t});\n\t\truntimeHub.disposeWorkspace(workspaceId);\n\t\treturn disposed;\n\t};\n\n\tconst runtimeServer = await createRuntimeServer({\n\t\tworkspaceRegistry,\n\t\truntimeStateHub: runtimeHub,\n\t\twarn: (message) => {\n\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t},\n\t\tensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,\n\t\tresolveInteractiveShellCommand,\n\t\trunCommand: runScopedCommand,\n\t\tresolveProjectInputPath,\n\t\tassertPathIsDirectory,\n\t\thasGitRepository,\n\t\tdisposeWorkspace: disposeTrackedWorkspace,\n\t\tcollectProjectWorktreeTaskIdsForRemoval,\n\t\tpickDirectoryPathFromSystemDialog,\n\t});\n\n\tconst close = async () => {\n\t\tawait runtimeServer.close();\n\t};\n\n\tconst shutdown = async (options?: { skipSessionCleanup?: boolean }) => {\n\t\tawait shutdownRuntimeServer({\n\t\t\tworkspaceRegistry,\n\t\t\twarn: (message) => {\n\t\t\t\tconsole.warn(`[kanban] ${message}`);\n\t\t\t},\n\t\t\tcloseRuntimeServer: close,\n\t\t\tskipSessionCleanup: options?.skipSessionCleanup ?? false,\n\t\t});\n\t};\n\n\treturn {\n\t\turl: runtimeServer.url,\n\t\tclose,\n\t\tshutdown,\n\t};\n}\n\nasync function startServerWithAutoPortRetry(options: CliOptions): Promise<Awaited<ReturnType<typeof startServer>>> {\n\tif (options.port?.mode !== \"auto\") {\n\t\treturn await startServer();\n\t}\n\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await startServer();\n\t\t} catch (error) {\n\t\t\tif (!isAddressInUseError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst currentPort = getKanbanRuntimePort();\n\t\t\tconst retryPort = await findAvailableRuntimePort(currentPort + 1);\n\t\t\tsetKanbanRuntimePort(retryPort);\n\t\t\tconsole.warn(`Runtime port ${currentPort} became busy during startup, retrying on ${retryPort}.`);\n\t\t}\n\t}\n}\n\nasync function runMainCommand(options: CliOptions): Promise<void> {\n\tconst selectedPort = await applyRuntimePortOption(options.port);\n\tif (selectedPort !== null) {\n\t\tconsole.log(`Using runtime port ${selectedPort}.`);\n\t}\n\n\tautoUpdateOnStartup({\n\t\tcurrentVersion: KANBAN_VERSION,\n\t});\n\n\tif (options.agent) {\n\t\tconst didChange = await persistCliAgentSelection(process.cwd(), options.agent);\n\t\tif (didChange) {\n\t\t\tconsole.log(`Default agent set to ${options.agent}.`);\n\t\t}\n\t}\n\n\ttry {\n\t\tconst detectedCommands = detectInstalledCommands();\n\t\tconst commandPrefix = resolveKanbanSkillCommandPrefix({\n\t\t\tcurrentVersion: KANBAN_VERSION,\n\t\t});\n\t\tawait installKanbanSkillFiles({\n\t\t\tcommandPrefix,\n\t\t\tinstallClaudeSkill: detectedCommands.includes(\"claude\"),\n\t\t});\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.warn(`Could not install Kanban skill files: ${message}`);\n\t}\n\n\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServerWithAutoPortRetry(options);\n\t} catch (error) {\n\t\tif (\n\t\t\toptions.port?.mode !== \"auto\" &&\n\t\t\tisAddressInUseError(error) &&\n\t\t\t(await tryOpenExistingServer(options.noOpen))\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tthrow error;\n\t}\n\tconsole.log(`Kanban running at ${runtime.url}`);\n\tif (!options.noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(runtime.url, {\n\t\t\t\twarn: (message) => {\n\t\t\t\t\tconsole.warn(message);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`Could not open browser automatically: ${message}`);\n\t\t}\n\t}\n\tconsole.log(\"Press Ctrl+C to stop.\");\n\n\tlet isShuttingDown = false;\n\tconst shutdown = async (signal: NodeJS.Signals | null) => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\trunPendingAutoUpdateOnShutdown();\n\t\ttry {\n\t\t\tif (options.skipShutdownCleanup) {\n\t\t\t\tconsole.warn(\"Skipping shutdown task cleanup for this instance.\");\n\t\t\t}\n\t\t\tawait runtime.shutdown({\n\t\t\t\tskipSessionCleanup: options.skipShutdownCleanup,\n\t\t\t});\n\t\t\tprocess.exit(signal ? 130 : 0);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(`Shutdown failed: ${message}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t};\n\n\tcloseWithGrace(\n\t\t{\n\t\t\tdelay: 10000,\n\t\t\tskip: [\"uncaughtException\", \"unhandledRejection\", \"beforeExit\"],\n\t\t\tonTimeout: (delayMs) => {\n\t\t\t\tconsole.error(`Forced exit after shutdown timeout (${delayMs}ms).`);\n\t\t\t},\n\t\t\tonSecondSignal: (signal) => {\n\t\t\t\tconsole.error(`Forced exit on second signal: ${signal}`);\n\t\t\t},\n\t\t},\n\t\tasync ({ signal }) => {\n\t\t\tawait shutdown(signal ?? null);\n\t\t},\n\t);\n}\n\nfunction createProgram(): Command {\n\tconst program = new Command();\n\tprogram\n\t\t.name(\"kanban\")\n\t\t.description(\"Local orchestration board for coding agents.\")\n\t\t.version(KANBAN_VERSION, \"-v, --version\", \"Output the version number\")\n\t\t.option(\"--agent <id>\", `Default agent ID (${CLI_AGENT_IDS.join(\", \")}).`, parseCliAgentId)\n\t\t.option(\"--port <number|auto>\", \"Runtime port (1-65535) or auto.\", parseCliPortValue)\n\t\t.option(\"--no-open\", \"Do not open browser automatically.\")\n\t\t.option(\"--skip-shutdown-cleanup\", \"Do not move sessions to trash or delete task worktrees on shutdown.\")\n\t\t.showHelpAfterError()\n\t\t.addHelpText(\"after\", `\\nRuntime URL: ${getKanbanRuntimeOrigin()}\\nAgent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\n\n\tregisterTaskCommand(program);\n\tregisterHooksCommand(program);\n\n\tprogram\n\t\t.command(\"mcp\")\n\t\t.description(\"Deprecated compatibility command.\")\n\t\t.action(() => {\n\t\t\tconsole.warn(\"Deprecated. Please uninstall Kanban MCP.\");\n\t\t});\n\n\tprogram.action(async (options: RootCommandOptions) => {\n\t\tawait runMainCommand({\n\t\t\tagent: options.agent ?? null,\n\t\t\tport: options.port ?? null,\n\t\t\tnoOpen: options.open === false,\n\t\t\tskipShutdownCleanup: options.skipShutdownCleanup === true,\n\t\t});\n\t});\n\n\treturn program;\n}\n\nasync function run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tconst program = createProgram();\n\tawait program.parseAsync(argv, { from: \"user\" });\n}\n\nrun().catch((error) => {\n\tconst message = error instanceof Error ? error.message : String(error);\n\tconsole.error(`Failed to start Kanban: ${message}`);\n\tprocess.exit(1);\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown-coordinator.d.ts","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,MAAM,WAAW,sCAAsC;IACtD,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,uBAAuB,CAAC,CAAC;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"shutdown-coordinator.d.ts","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,MAAM,WAAW,sCAAsC;IACtD,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,uBAAuB,CAAC,CAAC;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAqID,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,sCAAsC,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEvG"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { updateTaskDependencies } from "../core/task-board-mutations.js";
|
|
2
|
-
import { loadWorkspaceState, saveWorkspaceState } from "../state/workspace-state.js";
|
|
2
|
+
import { listWorkspaceIndexEntries, loadWorkspaceState, saveWorkspaceState } from "../state/workspace-state.js";
|
|
3
3
|
import { deleteTaskWorktree } from "../workspace/task-worktree.js";
|
|
4
4
|
import { collectProjectWorktreeTaskIdsForRemoval } from "./workspace-registry.js";
|
|
5
5
|
function moveTaskToTrash(board, taskId) {
|
|
@@ -36,11 +36,11 @@ function moveTaskToTrash(board, taskId) {
|
|
|
36
36
|
columns,
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
|
-
async function persistInterruptedSessions(workspacePath, interruptedTaskIds,
|
|
39
|
+
async function persistInterruptedSessions(workspacePath, interruptedTaskIds, options) {
|
|
40
40
|
if (interruptedTaskIds.length === 0) {
|
|
41
41
|
return [];
|
|
42
42
|
}
|
|
43
|
-
const workspaceState = await loadWorkspaceState(workspacePath);
|
|
43
|
+
const workspaceState = options?.workspaceState ?? (await loadWorkspaceState(workspacePath));
|
|
44
44
|
const worktreeTaskIds = collectProjectWorktreeTaskIdsForRemoval(workspaceState.board);
|
|
45
45
|
const worktreeTaskIdsToCleanup = interruptedTaskIds.filter((taskId) => worktreeTaskIds.has(taskId));
|
|
46
46
|
let nextBoard = workspaceState.board;
|
|
@@ -51,12 +51,13 @@ async function persistInterruptedSessions(workspacePath, interruptedTaskIds, ter
|
|
|
51
51
|
...workspaceState.sessions,
|
|
52
52
|
};
|
|
53
53
|
for (const taskId of interruptedTaskIds) {
|
|
54
|
-
const summary =
|
|
54
|
+
const summary = options?.resolveSummary?.(taskId) ?? workspaceState.sessions[taskId] ?? null;
|
|
55
55
|
if (summary) {
|
|
56
56
|
nextSessions[taskId] = {
|
|
57
57
|
...summary,
|
|
58
58
|
state: "interrupted",
|
|
59
59
|
reviewReason: "interrupted",
|
|
60
|
+
pid: null,
|
|
60
61
|
updatedAt: Date.now(),
|
|
61
62
|
};
|
|
62
63
|
}
|
|
@@ -102,26 +103,67 @@ function collectShutdownInterruptedTaskIds(interruptedSummaries, terminalManager
|
|
|
102
103
|
}
|
|
103
104
|
return Array.from(taskIds);
|
|
104
105
|
}
|
|
106
|
+
function collectWorkColumnTaskIds(workspaceState) {
|
|
107
|
+
return Array.from(collectProjectWorktreeTaskIdsForRemoval(workspaceState.board));
|
|
108
|
+
}
|
|
105
109
|
export async function shutdownRuntimeServer(deps) {
|
|
106
110
|
if (deps.skipSessionCleanup) {
|
|
107
111
|
await deps.closeRuntimeServer();
|
|
108
112
|
return;
|
|
109
113
|
}
|
|
110
114
|
const interruptedByWorkspace = [];
|
|
115
|
+
const managedWorkspacePaths = new Set();
|
|
111
116
|
for (const { workspacePath, terminalManager } of deps.workspaceRegistry.listManagedWorkspaces()) {
|
|
112
117
|
const interrupted = terminalManager.markInterruptedAndStopAll();
|
|
113
|
-
const interruptedTaskIds = collectShutdownInterruptedTaskIds(interrupted, terminalManager);
|
|
118
|
+
const interruptedTaskIds = new Set(collectShutdownInterruptedTaskIds(interrupted, terminalManager));
|
|
114
119
|
if (!workspacePath) {
|
|
115
120
|
continue;
|
|
116
121
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
managedWorkspacePaths.add(workspacePath);
|
|
123
|
+
try {
|
|
124
|
+
const workspaceState = await loadWorkspaceState(workspacePath);
|
|
125
|
+
for (const taskId of collectWorkColumnTaskIds(workspaceState)) {
|
|
126
|
+
interruptedTaskIds.add(taskId);
|
|
127
|
+
}
|
|
128
|
+
interruptedByWorkspace.push({
|
|
129
|
+
workspacePath,
|
|
130
|
+
interruptedTaskIds: Array.from(interruptedTaskIds),
|
|
131
|
+
workspaceState,
|
|
132
|
+
resolveSummary: (taskId) => terminalManager.getSummary(taskId),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
137
|
+
deps.warn(`Could not load workspace state for ${workspacePath} during shutdown cleanup. ${message}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const indexedWorkspaces = await listWorkspaceIndexEntries();
|
|
141
|
+
for (const workspace of indexedWorkspaces) {
|
|
142
|
+
if (managedWorkspacePaths.has(workspace.repoPath)) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const workspaceState = await loadWorkspaceState(workspace.repoPath);
|
|
147
|
+
const interruptedTaskIds = collectWorkColumnTaskIds(workspaceState);
|
|
148
|
+
if (interruptedTaskIds.length === 0) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
interruptedByWorkspace.push({
|
|
152
|
+
workspacePath: workspace.repoPath,
|
|
153
|
+
interruptedTaskIds,
|
|
154
|
+
workspaceState,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
159
|
+
deps.warn(`Could not load workspace state for ${workspace.repoPath} during shutdown cleanup. ${message}`);
|
|
160
|
+
}
|
|
122
161
|
}
|
|
123
162
|
await Promise.all(interruptedByWorkspace.map(async (workspace) => {
|
|
124
|
-
const worktreeTaskIds = await persistInterruptedSessions(workspace.workspacePath, workspace.interruptedTaskIds,
|
|
163
|
+
const worktreeTaskIds = await persistInterruptedSessions(workspace.workspacePath, workspace.interruptedTaskIds, {
|
|
164
|
+
workspaceState: workspace.workspaceState,
|
|
165
|
+
resolveSummary: workspace.resolveSummary,
|
|
166
|
+
});
|
|
125
167
|
await cleanupInterruptedTaskWorktrees(workspace.workspacePath, worktreeTaskIds, deps.warn);
|
|
126
168
|
}));
|
|
127
169
|
await deps.closeRuntimeServer();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown-coordinator.js","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RuntimeTaskSessionSummary, RuntimeWorkspaceStateResponse } from \"../core/api-contract.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\nimport { loadWorkspaceState, saveWorkspaceState } from \"../state/workspace-state.js\";\nimport type { TerminalSessionManager } from \"../terminal/session-manager.js\";\nimport { deleteTaskWorktree } from \"../workspace/task-worktree.js\";\nimport type { WorkspaceRegistry } from \"./workspace-registry.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval } from \"./workspace-registry.js\";\n\nexport interface RuntimeShutdownCoordinatorDependencies {\n\tworkspaceRegistry: Pick<WorkspaceRegistry, \"listManagedWorkspaces\">;\n\twarn: (message: string) => void;\n\tcloseRuntimeServer: () => Promise<void>;\n\tskipSessionCleanup?: boolean;\n}\n\nfunction moveTaskToTrash(\n\tboard: RuntimeWorkspaceStateResponse[\"board\"],\n\ttaskId: string,\n): RuntimeWorkspaceStateResponse[\"board\"] {\n\tconst columns = board.columns.map((column) => ({\n\t\t...column,\n\t\tcards: [...column.cards],\n\t}));\n\tlet removedCard: RuntimeWorkspaceStateResponse[\"board\"][\"columns\"][number][\"cards\"][number] | undefined;\n\n\tfor (const column of columns) {\n\t\tconst cardIndex = column.cards.findIndex((candidate) => candidate.id === taskId);\n\t\tif (cardIndex === -1) {\n\t\t\tcontinue;\n\t\t}\n\t\tremovedCard = column.cards[cardIndex];\n\t\tcolumn.cards.splice(cardIndex, 1);\n\t\tbreak;\n\t}\n\n\tif (!removedCard) {\n\t\treturn board;\n\t}\n\tconst trashColumnIndex = columns.findIndex((column) => column.id === \"trash\");\n\tif (trashColumnIndex === -1) {\n\t\treturn board;\n\t}\n\tconst trashColumn = columns[trashColumnIndex];\n\tif (!trashColumn.cards.some((candidate) => candidate.id === taskId)) {\n\t\ttrashColumn.cards.unshift({\n\t\t\t...removedCard,\n\t\t\tupdatedAt: Date.now(),\n\t\t});\n\t}\n\treturn updateTaskDependencies({\n\t\t...board,\n\t\tcolumns,\n\t});\n}\n\nasync function persistInterruptedSessions(\n\tworkspacePath: string,\n\tinterruptedTaskIds: string[],\n\tterminalManager: TerminalSessionManager,\n): Promise<string[]> {\n\tif (interruptedTaskIds.length === 0) {\n\t\treturn [];\n\t}\n\tconst workspaceState = await loadWorkspaceState(workspacePath);\n\tconst worktreeTaskIds = collectProjectWorktreeTaskIdsForRemoval(workspaceState.board);\n\tconst worktreeTaskIdsToCleanup = interruptedTaskIds.filter((taskId) => worktreeTaskIds.has(taskId));\n\tlet nextBoard = workspaceState.board;\n\tfor (const taskId of interruptedTaskIds) {\n\t\tnextBoard = moveTaskToTrash(nextBoard, taskId);\n\t}\n\tconst nextSessions = {\n\t\t...workspaceState.sessions,\n\t};\n\tfor (const taskId of interruptedTaskIds) {\n\t\tconst summary = terminalManager.getSummary(taskId);\n\t\tif (summary) {\n\t\t\tnextSessions[taskId] = {\n\t\t\t\t...summary,\n\t\t\t\tstate: \"interrupted\",\n\t\t\t\treviewReason: \"interrupted\",\n\t\t\t\tupdatedAt: Date.now(),\n\t\t\t};\n\t\t}\n\t}\n\tawait saveWorkspaceState(workspacePath, {\n\t\tboard: nextBoard,\n\t\tsessions: nextSessions,\n\t});\n\treturn worktreeTaskIdsToCleanup;\n}\n\nasync function cleanupInterruptedTaskWorktrees(\n\trepoPath: string,\n\ttaskIds: string[],\n\twarn: (message: string) => void,\n): Promise<void> {\n\tif (taskIds.length === 0) {\n\t\treturn;\n\t}\n\tconst deletions = await Promise.all(\n\t\ttaskIds.map(async (taskId) => ({\n\t\t\ttaskId,\n\t\t\tdeleted: await deleteTaskWorktree({\n\t\t\t\trepoPath,\n\t\t\t\ttaskId,\n\t\t\t}),\n\t\t})),\n\t);\n\tfor (const { taskId, deleted } of deletions) {\n\t\tif (deleted.ok) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst message = deleted.error ?? `Could not delete task workspace for task \"${taskId}\" during shutdown.`;\n\t\twarn(message);\n\t}\n}\n\nfunction shouldInterruptSessionOnShutdown(summary: RuntimeTaskSessionSummary): boolean {\n\tif (summary.state === \"running\") {\n\t\treturn true;\n\t}\n\treturn summary.state === \"awaiting_review\";\n}\n\nfunction collectShutdownInterruptedTaskIds(\n\tinterruptedSummaries: RuntimeTaskSessionSummary[],\n\tterminalManager: TerminalSessionManager,\n): string[] {\n\tconst taskIds = new Set(interruptedSummaries.map((summary) => summary.taskId));\n\tfor (const summary of terminalManager.listSummaries()) {\n\t\tif (!shouldInterruptSessionOnShutdown(summary)) {\n\t\t\tcontinue;\n\t\t}\n\t\ttaskIds.add(summary.taskId);\n\t}\n\treturn Array.from(taskIds);\n}\n\nexport async function shutdownRuntimeServer(deps: RuntimeShutdownCoordinatorDependencies): Promise<void> {\n\tif (deps.skipSessionCleanup) {\n\t\tawait deps.closeRuntimeServer();\n\t\treturn;\n\t}\n\n\tconst interruptedByWorkspace: Array<{\n\t\tworkspacePath: string;\n\t\tterminalManager: TerminalSessionManager;\n\t\tinterruptedTaskIds: string[];\n\t}> = [];\n\n\tfor (const { workspacePath, terminalManager } of deps.workspaceRegistry.listManagedWorkspaces()) {\n\t\tconst interrupted = terminalManager.markInterruptedAndStopAll();\n\t\tconst interruptedTaskIds = collectShutdownInterruptedTaskIds(interrupted, terminalManager);\n\t\tif (!workspacePath) {\n\t\t\tcontinue;\n\t\t}\n\t\tinterruptedByWorkspace.push({\n\t\t\tworkspacePath,\n\t\t\tterminalManager,\n\t\t\tinterruptedTaskIds,\n\t\t});\n\t}\n\n\tawait Promise.all(\n\t\tinterruptedByWorkspace.map(async (workspace) => {\n\t\t\tconst worktreeTaskIds = await persistInterruptedSessions(\n\t\t\t\tworkspace.workspacePath,\n\t\t\t\tworkspace.interruptedTaskIds,\n\t\t\t\tworkspace.terminalManager,\n\t\t\t);\n\t\t\tawait cleanupInterruptedTaskWorktrees(workspace.workspacePath, worktreeTaskIds, deps.warn);\n\t\t}),\n\t);\n\n\tawait deps.closeRuntimeServer();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shutdown-coordinator.js","sourceRoot":"","sources":["../../src/server/shutdown-coordinator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEhH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,uCAAuC,EAAE,MAAM,yBAAyB,CAAC;AASlF,SAAS,eAAe,CACvB,KAA6C,EAC7C,MAAc;IAEd,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9C,GAAG,MAAM;QACT,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;KACxB,CAAC,CAAC,CAAC;IACJ,IAAI,WAAmG,CAAC;IAExG,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;QACjF,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,SAAS;QACV,CAAC;QACD,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAClC,MAAM;IACP,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC9E,IAAI,gBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9C,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC;QACrE,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC;YACzB,GAAG,WAAW;YACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,sBAAsB,CAAC;QAC7B,GAAG,KAAK;QACR,OAAO;KACP,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,0BAA0B,CACxC,aAAqB,EACrB,kBAA4B,EAC5B,OAGC;IAED,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,CAAC,MAAM,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5F,MAAM,eAAe,GAAG,uCAAuC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACtF,MAAM,wBAAwB,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACpG,IAAI,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC;IACrC,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,CAAC;QACzC,SAAS,GAAG,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,YAAY,GAAG;QACpB,GAAG,cAAc,CAAC,QAAQ;KAC1B,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,kBAAkB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,OAAO,EAAE,cAAc,EAAE,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;QAC7F,IAAI,OAAO,EAAE,CAAC;YACb,YAAY,CAAC,MAAM,CAAC,GAAG;gBACtB,GAAG,OAAO;gBACV,KAAK,EAAE,aAAa;gBACpB,YAAY,EAAE,aAAa;gBAC3B,GAAG,EAAE,IAAI;gBACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,CAAC;QACH,CAAC;IACF,CAAC;IACD,MAAM,kBAAkB,CAAC,aAAa,EAAE;QACvC,KAAK,EAAE,SAAS;QAChB,QAAQ,EAAE,YAAY;KACtB,CAAC,CAAC;IACH,OAAO,wBAAwB,CAAC;AACjC,CAAC;AAED,KAAK,UAAU,+BAA+B,CAC7C,QAAgB,EAChB,OAAiB,EACjB,IAA+B;IAE/B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;IACR,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAClC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9B,MAAM;QACN,OAAO,EAAE,MAAM,kBAAkB,CAAC;YACjC,QAAQ;YACR,MAAM;SACN,CAAC;KACF,CAAC,CAAC,CACH,CAAC;IACF,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,SAAS,EAAE,CAAC;QAC7C,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,SAAS;QACV,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,6CAA6C,MAAM,oBAAoB,CAAC;QACzG,IAAI,CAAC,OAAO,CAAC,CAAC;IACf,CAAC;AACF,CAAC;AAED,SAAS,gCAAgC,CAAC,OAAkC;IAC3E,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,KAAK,iBAAiB,CAAC;AAC5C,CAAC;AAED,SAAS,iCAAiC,CACzC,oBAAiD,EACjD,eAAuC;IAEvC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/E,KAAK,MAAM,OAAO,IAAI,eAAe,CAAC,aAAa,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC,gCAAgC,CAAC,OAAO,CAAC,EAAE,CAAC;YAChD,SAAS;QACV,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,wBAAwB,CAAC,cAA6C;IAC9E,OAAO,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAA4C;IACvF,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC7B,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAChC,OAAO;IACR,CAAC;IAED,MAAM,sBAAsB,GAKvB,EAAE,CAAC;IACR,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhD,KAAK,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,IAAI,IAAI,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,EAAE,CAAC;QACjG,MAAM,WAAW,GAAG,eAAe,CAAC,yBAAyB,EAAE,CAAC;QAChE,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,iCAAiC,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;QACpG,IAAI,CAAC,aAAa,EAAE,CAAC;YACpB,SAAS;QACV,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACzC,IAAI,CAAC;YACJ,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,aAAa,CAAC,CAAC;YAC/D,KAAK,MAAM,MAAM,IAAI,wBAAwB,CAAC,cAAc,CAAC,EAAE,CAAC;gBAC/D,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;YACD,sBAAsB,CAAC,IAAI,CAAC;gBAC3B,aAAa;gBACb,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC;gBAClD,cAAc;gBACd,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,MAAM,CAAC;aAC9D,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,IAAI,CAAC,IAAI,CAAC,sCAAsC,aAAa,6BAA6B,OAAO,EAAE,CAAC,CAAC;QACtG,CAAC;IACF,CAAC;IAED,MAAM,iBAAiB,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAC5D,KAAK,MAAM,SAAS,IAAI,iBAAiB,EAAE,CAAC;QAC3C,IAAI,qBAAqB,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnD,SAAS;QACV,CAAC;QACD,IAAI,CAAC;YACJ,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACpE,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,cAAc,CAAC,CAAC;YACpE,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrC,SAAS;YACV,CAAC;YACD,sBAAsB,CAAC,IAAI,CAAC;gBAC3B,aAAa,EAAE,SAAS,CAAC,QAAQ;gBACjC,kBAAkB;gBAClB,cAAc;aACd,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,IAAI,CAAC,IAAI,CAAC,sCAAsC,SAAS,CAAC,QAAQ,6BAA6B,OAAO,EAAE,CAAC,CAAC;QAC3G,CAAC;IACF,CAAC;IAED,MAAM,OAAO,CAAC,GAAG,CAChB,sBAAsB,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;QAC9C,MAAM,eAAe,GAAG,MAAM,0BAA0B,CAAC,SAAS,CAAC,aAAa,EAAE,SAAS,CAAC,kBAAkB,EAAE;YAC/G,cAAc,EAAE,SAAS,CAAC,cAAc;YACxC,cAAc,EAAE,SAAS,CAAC,cAAc;SACxC,CAAC,CAAC;QACH,MAAM,+BAA+B,CAAC,SAAS,CAAC,aAAa,EAAE,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5F,CAAC,CAAC,CACF,CAAC;IAEF,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;AACjC,CAAC","sourcesContent":["import type { RuntimeTaskSessionSummary, RuntimeWorkspaceStateResponse } from \"../core/api-contract.js\";\nimport { updateTaskDependencies } from \"../core/task-board-mutations.js\";\nimport { listWorkspaceIndexEntries, loadWorkspaceState, saveWorkspaceState } from \"../state/workspace-state.js\";\nimport type { TerminalSessionManager } from \"../terminal/session-manager.js\";\nimport { deleteTaskWorktree } from \"../workspace/task-worktree.js\";\nimport type { WorkspaceRegistry } from \"./workspace-registry.js\";\nimport { collectProjectWorktreeTaskIdsForRemoval } from \"./workspace-registry.js\";\n\nexport interface RuntimeShutdownCoordinatorDependencies {\n\tworkspaceRegistry: Pick<WorkspaceRegistry, \"listManagedWorkspaces\">;\n\twarn: (message: string) => void;\n\tcloseRuntimeServer: () => Promise<void>;\n\tskipSessionCleanup?: boolean;\n}\n\nfunction moveTaskToTrash(\n\tboard: RuntimeWorkspaceStateResponse[\"board\"],\n\ttaskId: string,\n): RuntimeWorkspaceStateResponse[\"board\"] {\n\tconst columns = board.columns.map((column) => ({\n\t\t...column,\n\t\tcards: [...column.cards],\n\t}));\n\tlet removedCard: RuntimeWorkspaceStateResponse[\"board\"][\"columns\"][number][\"cards\"][number] | undefined;\n\n\tfor (const column of columns) {\n\t\tconst cardIndex = column.cards.findIndex((candidate) => candidate.id === taskId);\n\t\tif (cardIndex === -1) {\n\t\t\tcontinue;\n\t\t}\n\t\tremovedCard = column.cards[cardIndex];\n\t\tcolumn.cards.splice(cardIndex, 1);\n\t\tbreak;\n\t}\n\n\tif (!removedCard) {\n\t\treturn board;\n\t}\n\tconst trashColumnIndex = columns.findIndex((column) => column.id === \"trash\");\n\tif (trashColumnIndex === -1) {\n\t\treturn board;\n\t}\n\tconst trashColumn = columns[trashColumnIndex];\n\tif (!trashColumn.cards.some((candidate) => candidate.id === taskId)) {\n\t\ttrashColumn.cards.unshift({\n\t\t\t...removedCard,\n\t\t\tupdatedAt: Date.now(),\n\t\t});\n\t}\n\treturn updateTaskDependencies({\n\t\t...board,\n\t\tcolumns,\n\t});\n}\n\nasync function persistInterruptedSessions(\n\tworkspacePath: string,\n\tinterruptedTaskIds: string[],\n\toptions?: {\n\t\tworkspaceState?: RuntimeWorkspaceStateResponse;\n\t\tresolveSummary?: (taskId: string) => RuntimeTaskSessionSummary | null;\n\t},\n): Promise<string[]> {\n\tif (interruptedTaskIds.length === 0) {\n\t\treturn [];\n\t}\n\tconst workspaceState = options?.workspaceState ?? (await loadWorkspaceState(workspacePath));\n\tconst worktreeTaskIds = collectProjectWorktreeTaskIdsForRemoval(workspaceState.board);\n\tconst worktreeTaskIdsToCleanup = interruptedTaskIds.filter((taskId) => worktreeTaskIds.has(taskId));\n\tlet nextBoard = workspaceState.board;\n\tfor (const taskId of interruptedTaskIds) {\n\t\tnextBoard = moveTaskToTrash(nextBoard, taskId);\n\t}\n\tconst nextSessions = {\n\t\t...workspaceState.sessions,\n\t};\n\tfor (const taskId of interruptedTaskIds) {\n\t\tconst summary = options?.resolveSummary?.(taskId) ?? workspaceState.sessions[taskId] ?? null;\n\t\tif (summary) {\n\t\t\tnextSessions[taskId] = {\n\t\t\t\t...summary,\n\t\t\t\tstate: \"interrupted\",\n\t\t\t\treviewReason: \"interrupted\",\n\t\t\t\tpid: null,\n\t\t\t\tupdatedAt: Date.now(),\n\t\t\t};\n\t\t}\n\t}\n\tawait saveWorkspaceState(workspacePath, {\n\t\tboard: nextBoard,\n\t\tsessions: nextSessions,\n\t});\n\treturn worktreeTaskIdsToCleanup;\n}\n\nasync function cleanupInterruptedTaskWorktrees(\n\trepoPath: string,\n\ttaskIds: string[],\n\twarn: (message: string) => void,\n): Promise<void> {\n\tif (taskIds.length === 0) {\n\t\treturn;\n\t}\n\tconst deletions = await Promise.all(\n\t\ttaskIds.map(async (taskId) => ({\n\t\t\ttaskId,\n\t\t\tdeleted: await deleteTaskWorktree({\n\t\t\t\trepoPath,\n\t\t\t\ttaskId,\n\t\t\t}),\n\t\t})),\n\t);\n\tfor (const { taskId, deleted } of deletions) {\n\t\tif (deleted.ok) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst message = deleted.error ?? `Could not delete task workspace for task \"${taskId}\" during shutdown.`;\n\t\twarn(message);\n\t}\n}\n\nfunction shouldInterruptSessionOnShutdown(summary: RuntimeTaskSessionSummary): boolean {\n\tif (summary.state === \"running\") {\n\t\treturn true;\n\t}\n\treturn summary.state === \"awaiting_review\";\n}\n\nfunction collectShutdownInterruptedTaskIds(\n\tinterruptedSummaries: RuntimeTaskSessionSummary[],\n\tterminalManager: TerminalSessionManager,\n): string[] {\n\tconst taskIds = new Set(interruptedSummaries.map((summary) => summary.taskId));\n\tfor (const summary of terminalManager.listSummaries()) {\n\t\tif (!shouldInterruptSessionOnShutdown(summary)) {\n\t\t\tcontinue;\n\t\t}\n\t\ttaskIds.add(summary.taskId);\n\t}\n\treturn Array.from(taskIds);\n}\n\nfunction collectWorkColumnTaskIds(workspaceState: RuntimeWorkspaceStateResponse): string[] {\n\treturn Array.from(collectProjectWorktreeTaskIdsForRemoval(workspaceState.board));\n}\n\nexport async function shutdownRuntimeServer(deps: RuntimeShutdownCoordinatorDependencies): Promise<void> {\n\tif (deps.skipSessionCleanup) {\n\t\tawait deps.closeRuntimeServer();\n\t\treturn;\n\t}\n\n\tconst interruptedByWorkspace: Array<{\n\t\tworkspacePath: string;\n\t\tinterruptedTaskIds: string[];\n\t\tworkspaceState?: RuntimeWorkspaceStateResponse;\n\t\tresolveSummary?: (taskId: string) => RuntimeTaskSessionSummary | null;\n\t}> = [];\n\tconst managedWorkspacePaths = new Set<string>();\n\n\tfor (const { workspacePath, terminalManager } of deps.workspaceRegistry.listManagedWorkspaces()) {\n\t\tconst interrupted = terminalManager.markInterruptedAndStopAll();\n\t\tconst interruptedTaskIds = new Set(collectShutdownInterruptedTaskIds(interrupted, terminalManager));\n\t\tif (!workspacePath) {\n\t\t\tcontinue;\n\t\t}\n\t\tmanagedWorkspacePaths.add(workspacePath);\n\t\ttry {\n\t\t\tconst workspaceState = await loadWorkspaceState(workspacePath);\n\t\t\tfor (const taskId of collectWorkColumnTaskIds(workspaceState)) {\n\t\t\t\tinterruptedTaskIds.add(taskId);\n\t\t\t}\n\t\t\tinterruptedByWorkspace.push({\n\t\t\t\tworkspacePath,\n\t\t\t\tinterruptedTaskIds: Array.from(interruptedTaskIds),\n\t\t\t\tworkspaceState,\n\t\t\t\tresolveSummary: (taskId) => terminalManager.getSummary(taskId),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdeps.warn(`Could not load workspace state for ${workspacePath} during shutdown cleanup. ${message}`);\n\t\t}\n\t}\n\n\tconst indexedWorkspaces = await listWorkspaceIndexEntries();\n\tfor (const workspace of indexedWorkspaces) {\n\t\tif (managedWorkspacePaths.has(workspace.repoPath)) {\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst workspaceState = await loadWorkspaceState(workspace.repoPath);\n\t\t\tconst interruptedTaskIds = collectWorkColumnTaskIds(workspaceState);\n\t\t\tif (interruptedTaskIds.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tinterruptedByWorkspace.push({\n\t\t\t\tworkspacePath: workspace.repoPath,\n\t\t\t\tinterruptedTaskIds,\n\t\t\t\tworkspaceState,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdeps.warn(`Could not load workspace state for ${workspace.repoPath} during shutdown cleanup. ${message}`);\n\t\t}\n\t}\n\n\tawait Promise.all(\n\t\tinterruptedByWorkspace.map(async (workspace) => {\n\t\t\tconst worktreeTaskIds = await persistInterruptedSessions(workspace.workspacePath, workspace.interruptedTaskIds, {\n\t\t\t\tworkspaceState: workspace.workspaceState,\n\t\t\t\tresolveSummary: workspace.resolveSummary,\n\t\t\t});\n\t\t\tawait cleanupInterruptedTaskWorktrees(workspace.workspacePath, worktreeTaskIds, deps.warn);\n\t\t}),\n\t);\n\n\tawait deps.closeRuntimeServer();\n}\n"]}
|