kanban 0.1.4 → 0.1.5
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/README.md +19 -0
- package/dist/cli.js +102 -11
- package/dist/cli.js.map +1 -1
- package/dist/config/runtime-config.d.ts +3 -3
- package/dist/config/runtime-config.d.ts.map +1 -1
- package/dist/config/runtime-config.js +17 -18
- package/dist/config/runtime-config.js.map +1 -1
- package/dist/config/shortcut-utils.d.ts.map +1 -1
- package/dist/config/shortcut-utils.js +1 -2
- package/dist/config/shortcut-utils.js.map +1 -1
- package/dist/core/agent-catalog.d.ts.map +1 -1
- package/dist/core/agent-catalog.js +8 -0
- package/dist/core/agent-catalog.js.map +1 -1
- package/dist/core/api-contract.d.ts +27 -50
- package/dist/core/api-contract.d.ts.map +1 -1
- package/dist/core/api-contract.js +5 -23
- package/dist/core/api-contract.js.map +1 -1
- package/dist/core/api-validation.d.ts +2 -2
- package/dist/core/api-validation.d.ts.map +1 -1
- package/dist/core/api-validation.js +4 -4
- package/dist/core/api-validation.js.map +1 -1
- package/dist/core/runtime-endpoint.d.ts +6 -3
- package/dist/core/runtime-endpoint.d.ts.map +1 -1
- package/dist/core/runtime-endpoint.js +19 -7
- package/dist/core/runtime-endpoint.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +2 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/server/runtime-server.d.ts +2 -2
- package/dist/server/runtime-server.d.ts.map +1 -1
- package/dist/server/runtime-server.js +7 -6
- package/dist/server/runtime-server.js.map +1 -1
- package/dist/server/runtime-state-hub.d.ts.map +1 -1
- package/dist/server/runtime-state-hub.js +0 -68
- package/dist/server/runtime-state-hub.js.map +1 -1
- package/dist/terminal/agent-registry.js +5 -5
- package/dist/terminal/agent-registry.js.map +1 -1
- package/dist/terminal/agent-session-adapters.d.ts +3 -0
- package/dist/terminal/agent-session-adapters.d.ts.map +1 -1
- package/dist/terminal/agent-session-adapters.js +63 -1
- package/dist/terminal/agent-session-adapters.js.map +1 -1
- package/dist/terminal/claude-workspace-trust.d.ts +0 -2
- package/dist/terminal/claude-workspace-trust.d.ts.map +1 -1
- package/dist/terminal/claude-workspace-trust.js +0 -5
- package/dist/terminal/claude-workspace-trust.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +35 -0
- package/dist/terminal/pty-session.d.ts.map +1 -0
- package/dist/terminal/pty-session.js +88 -0
- package/dist/terminal/pty-session.js.map +1 -0
- package/dist/terminal/session-manager.d.ts +5 -8
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +182 -275
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/slash-commands.d.ts.map +1 -1
- package/dist/terminal/slash-commands.js +17 -0
- package/dist/terminal/slash-commands.js.map +1 -1
- package/dist/terminal/terminal-session-service.d.ts +15 -0
- package/dist/terminal/terminal-session-service.d.ts.map +1 -0
- package/dist/terminal/terminal-session-service.js +2 -0
- package/dist/terminal/terminal-session-service.js.map +1 -0
- package/dist/terminal/ws-server.d.ts +5 -4
- package/dist/terminal/ws-server.d.ts.map +1 -1
- package/dist/terminal/ws-server.js +171 -44
- package/dist/terminal/ws-server.js.map +1 -1
- package/dist/trpc/app-router.d.ts +19 -29
- package/dist/trpc/app-router.d.ts.map +1 -1
- package/dist/trpc/app-router.js +5 -5
- package/dist/trpc/app-router.js.map +1 -1
- package/dist/trpc/runtime-api.d.ts +2 -2
- package/dist/trpc/runtime-api.d.ts.map +1 -1
- package/dist/trpc/runtime-api.js +5 -4
- package/dist/trpc/runtime-api.js.map +1 -1
- package/dist/trpc/workspace-api.js +2 -2
- package/dist/trpc/workspace-api.js.map +1 -1
- package/dist/web-ui/assets/{allPaths-hQZnjS_p.js → allPaths-CdLm57A0.js} +1 -1
- package/dist/web-ui/assets/allPathsLoader-FKnSZCTb.js +2 -0
- package/dist/web-ui/assets/index-BDb_xXnu.css +32 -0
- package/dist/web-ui/assets/index-CL-DaDRu.js +296 -0
- package/dist/web-ui/assets/{splitPathsBySizeLoader-CWXI7LLN.js → splitPathsBySizeLoader-BBFjPIdp.js} +1 -1
- package/dist/web-ui/index.html +2 -2
- package/dist/workspace/task-worktree.d.ts +1 -1
- package/dist/workspace/task-worktree.d.ts.map +1 -1
- package/dist/workspace/task-worktree.js +112 -13
- package/dist/workspace/task-worktree.js.map +1 -1
- package/package.json +2 -1
- package/dist/terminal/activity-preview.d.ts +0 -8
- package/dist/terminal/activity-preview.d.ts.map +0 -1
- package/dist/terminal/activity-preview.js +0 -495
- package/dist/terminal/activity-preview.js.map +0 -1
- package/dist/web-ui/assets/allPathsLoader-BZV0v7Fb.js +0 -2
- package/dist/web-ui/assets/index-Cb9WHKOt.css +0 -32
- package/dist/web-ui/assets/index-CwJtdBqQ.js +0 -159
package/README.md
CHANGED
|
@@ -48,6 +48,25 @@ Use MCP to let the agent add and start tasks on the kanban board itself, decompo
|
|
|
48
48
|
claude mcp add --transport stdio --scope user kanban -- kanban mcp
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
<details>
|
|
52
|
+
<summary>Using Cline?</summary>
|
|
53
|
+
|
|
54
|
+
Add this to your `~/.cline/data/settings/cline_mcp_settings.json`:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"mcpServers": {
|
|
59
|
+
"kanban": {
|
|
60
|
+
"command": "kanban",
|
|
61
|
+
"args": ["mcp"],
|
|
62
|
+
"transportType": "stdio"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
</details>
|
|
69
|
+
|
|
51
70
|
With the MCP tools, your agent can:
|
|
52
71
|
|
|
53
72
|
- `list_tasks`: see what's on the board, including task links and auto-review settings
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn, spawnSync } from "node:child_process";
|
|
3
3
|
import { stat } from "node:fs/promises";
|
|
4
|
+
import { createServer as createNetServer } from "node:net";
|
|
4
5
|
import packageJson from "../package.json" with { type: "json" };
|
|
5
6
|
import { isHooksSubcommand, runHooksSubcommand } from "./commands/hooks.js";
|
|
6
7
|
import { isMcpSubcommand, runMcpSubcommand } from "./commands/mcp.js";
|
|
7
8
|
import { loadRuntimeConfig, updateRuntimeConfig } from "./config/runtime-config.js";
|
|
8
9
|
import { createGitProcessEnv } from "./core/git-process-env.js";
|
|
9
10
|
import { resolveProjectInputPath } from "./projects/project-path.js";
|
|
10
|
-
import { buildKanbanRuntimeUrl,
|
|
11
|
+
import { buildKanbanRuntimeUrl, DEFAULT_KANBAN_RUNTIME_PORT, getKanbanRuntimePort, getKanbanRuntimeOrigin, parseRuntimePort, setKanbanRuntimePort, } from "./core/runtime-endpoint.js";
|
|
11
12
|
import { openInBrowser } from "./server/browser.js";
|
|
12
13
|
import { createRuntimeStateHub } from "./server/runtime-state-hub.js";
|
|
13
14
|
import { createRuntimeServer } from "./server/runtime-server.js";
|
|
@@ -16,7 +17,7 @@ import { resolveInteractiveShellCommand } from "./server/shell.js";
|
|
|
16
17
|
import { loadWorkspaceContext, } from "./state/workspace-state.js";
|
|
17
18
|
import { collectProjectWorktreeTaskIdsForRemoval, createWorkspaceRegistry, } from "./server/workspace-registry.js";
|
|
18
19
|
import { autoUpdateOnStartup } from "./update/auto-update.js";
|
|
19
|
-
const CLI_AGENT_IDS = ["claude", "codex", "gemini", "opencode", "cline"];
|
|
20
|
+
const CLI_AGENT_IDS = ["claude", "codex", "gemini", "opencode", "droid", "cline"];
|
|
20
21
|
const KANBAN_VERSION = typeof packageJson.version === "string" ? packageJson.version : "0.1.0";
|
|
21
22
|
function parseCliAgentId(value) {
|
|
22
23
|
const normalized = value.trim().toLowerCase();
|
|
@@ -24,16 +25,33 @@ function parseCliAgentId(value) {
|
|
|
24
25
|
normalized === "codex" ||
|
|
25
26
|
normalized === "gemini" ||
|
|
26
27
|
normalized === "opencode" ||
|
|
28
|
+
normalized === "droid" ||
|
|
27
29
|
normalized === "cline") {
|
|
28
30
|
return normalized;
|
|
29
31
|
}
|
|
30
32
|
throw new Error(`Invalid agent: ${value}. Expected one of: ${CLI_AGENT_IDS.join(", ")}`);
|
|
31
33
|
}
|
|
34
|
+
function parseCliPortValue(rawValue) {
|
|
35
|
+
const normalized = rawValue.trim().toLowerCase();
|
|
36
|
+
if (!normalized) {
|
|
37
|
+
throw new Error("Missing value for --port.");
|
|
38
|
+
}
|
|
39
|
+
if (normalized === "auto") {
|
|
40
|
+
return { mode: "auto" };
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return { mode: "fixed", value: parseRuntimePort(normalized) };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error(`Invalid port value: ${rawValue}. Expected an integer from 1-65535 or "auto".`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
32
49
|
function parseCliOptions(argv) {
|
|
33
50
|
let help = false;
|
|
34
51
|
let version = false;
|
|
35
52
|
let noOpen = false;
|
|
36
53
|
let agent = null;
|
|
54
|
+
let port = null;
|
|
37
55
|
for (let index = 0; index < argv.length; index += 1) {
|
|
38
56
|
const arg = argv[index];
|
|
39
57
|
if (arg === "--help" || arg === "-h") {
|
|
@@ -63,21 +81,71 @@ function parseCliOptions(argv) {
|
|
|
63
81
|
throw new Error("Missing value for --agent.");
|
|
64
82
|
}
|
|
65
83
|
agent = parseCliAgentId(value);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (arg === "--port") {
|
|
87
|
+
const value = argv[index + 1];
|
|
88
|
+
if (!value) {
|
|
89
|
+
throw new Error("Missing value for --port.");
|
|
90
|
+
}
|
|
91
|
+
port = parseCliPortValue(value);
|
|
92
|
+
index += 1;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (arg.startsWith("--port=")) {
|
|
96
|
+
const value = arg.slice("--port=".length);
|
|
97
|
+
if (!value) {
|
|
98
|
+
throw new Error("Missing value for --port.");
|
|
99
|
+
}
|
|
100
|
+
port = parseCliPortValue(value);
|
|
66
101
|
}
|
|
67
102
|
}
|
|
68
|
-
return { help, version, noOpen, agent };
|
|
103
|
+
return { help, version, noOpen, agent, port };
|
|
69
104
|
}
|
|
70
105
|
function printHelp() {
|
|
71
106
|
console.log("kanban");
|
|
72
107
|
console.log("Local orchestration board for coding agents.");
|
|
73
108
|
console.log("");
|
|
74
109
|
console.log("Usage:");
|
|
75
|
-
console.log(" kanban [--agent <id>] [--no-open] [--help] [--version]");
|
|
110
|
+
console.log(" kanban [--agent <id>] [--port <number|auto>] [--no-open] [--help] [--version]");
|
|
76
111
|
console.log(" kanban mcp");
|
|
77
112
|
console.log("");
|
|
78
|
-
console.log(`Runtime URL: ${
|
|
113
|
+
console.log(`Runtime URL: ${getKanbanRuntimeOrigin()}`);
|
|
79
114
|
console.log(`Agent IDs: ${CLI_AGENT_IDS.join(", ")}`);
|
|
80
115
|
}
|
|
116
|
+
async function isPortAvailable(port) {
|
|
117
|
+
return await new Promise((resolve) => {
|
|
118
|
+
const probe = createNetServer();
|
|
119
|
+
probe.once("error", () => {
|
|
120
|
+
resolve(false);
|
|
121
|
+
});
|
|
122
|
+
probe.listen(port, "127.0.0.1", () => {
|
|
123
|
+
probe.close(() => {
|
|
124
|
+
resolve(true);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async function findAvailableRuntimePort(startPort) {
|
|
130
|
+
for (let candidate = startPort; candidate <= 65535; candidate += 1) {
|
|
131
|
+
if (await isPortAvailable(candidate)) {
|
|
132
|
+
return candidate;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
throw new Error("No available runtime port found.");
|
|
136
|
+
}
|
|
137
|
+
async function applyRuntimePortOption(portOption) {
|
|
138
|
+
if (!portOption) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
if (portOption.mode === "fixed") {
|
|
142
|
+
setKanbanRuntimePort(portOption.value);
|
|
143
|
+
return portOption.value;
|
|
144
|
+
}
|
|
145
|
+
const autoPort = await findAvailableRuntimePort(DEFAULT_KANBAN_RUNTIME_PORT);
|
|
146
|
+
setKanbanRuntimePort(autoPort);
|
|
147
|
+
return autoPort;
|
|
148
|
+
}
|
|
81
149
|
async function persistCliAgentSelection(cwd, selectedAgentId) {
|
|
82
150
|
const currentRuntimeConfig = await loadRuntimeConfig(cwd);
|
|
83
151
|
if (currentRuntimeConfig.selectedAgentId === selectedAgentId) {
|
|
@@ -174,8 +242,8 @@ async function tryOpenExistingServer(noOpen) {
|
|
|
174
242
|
}
|
|
175
243
|
const projectUrl = workspaceId
|
|
176
244
|
? buildKanbanRuntimeUrl(`/${encodeURIComponent(workspaceId)}`)
|
|
177
|
-
:
|
|
178
|
-
console.log(`Kanban already running at ${
|
|
245
|
+
: getKanbanRuntimeOrigin();
|
|
246
|
+
console.log(`Kanban already running at ${getKanbanRuntimeOrigin()}`);
|
|
179
247
|
if (!noOpen) {
|
|
180
248
|
try {
|
|
181
249
|
openInBrowser(projectUrl);
|
|
@@ -188,7 +256,7 @@ async function tryOpenExistingServer(noOpen) {
|
|
|
188
256
|
console.log(`Project URL: ${projectUrl}`);
|
|
189
257
|
return true;
|
|
190
258
|
}
|
|
191
|
-
async function
|
|
259
|
+
async function runScopedCommand(command, cwd) {
|
|
192
260
|
const startedAt = Date.now();
|
|
193
261
|
const outputLimitBytes = 64 * 1024;
|
|
194
262
|
return await new Promise((resolve, reject) => {
|
|
@@ -270,7 +338,7 @@ async function startServer() {
|
|
|
270
338
|
},
|
|
271
339
|
ensureTerminalManagerForWorkspace: workspaceRegistry.ensureTerminalManagerForWorkspace,
|
|
272
340
|
resolveInteractiveShellCommand,
|
|
273
|
-
|
|
341
|
+
runCommand: runScopedCommand,
|
|
274
342
|
resolveProjectInputPath,
|
|
275
343
|
assertPathIsDirectory,
|
|
276
344
|
hasGitRepository,
|
|
@@ -296,6 +364,25 @@ async function startServer() {
|
|
|
296
364
|
shutdown,
|
|
297
365
|
};
|
|
298
366
|
}
|
|
367
|
+
async function startServerWithAutoPortRetry(options) {
|
|
368
|
+
if (options.port?.mode !== "auto") {
|
|
369
|
+
return await startServer();
|
|
370
|
+
}
|
|
371
|
+
while (true) {
|
|
372
|
+
try {
|
|
373
|
+
return await startServer();
|
|
374
|
+
}
|
|
375
|
+
catch (error) {
|
|
376
|
+
if (!isAddressInUseError(error)) {
|
|
377
|
+
throw error;
|
|
378
|
+
}
|
|
379
|
+
const currentPort = getKanbanRuntimePort();
|
|
380
|
+
const retryPort = await findAvailableRuntimePort(currentPort + 1);
|
|
381
|
+
setKanbanRuntimePort(retryPort);
|
|
382
|
+
console.warn(`Runtime port ${currentPort} became busy during startup, retrying on ${retryPort}.`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
299
386
|
async function run() {
|
|
300
387
|
const argv = process.argv.slice(2);
|
|
301
388
|
if (isMcpSubcommand(argv)) {
|
|
@@ -315,6 +402,10 @@ async function run() {
|
|
|
315
402
|
console.log(KANBAN_VERSION);
|
|
316
403
|
return;
|
|
317
404
|
}
|
|
405
|
+
const selectedPort = await applyRuntimePortOption(options.port);
|
|
406
|
+
if (selectedPort !== null) {
|
|
407
|
+
console.log(`Using runtime port ${selectedPort}.`);
|
|
408
|
+
}
|
|
318
409
|
autoUpdateOnStartup({
|
|
319
410
|
currentVersion: KANBAN_VERSION,
|
|
320
411
|
});
|
|
@@ -326,10 +417,10 @@ async function run() {
|
|
|
326
417
|
}
|
|
327
418
|
let runtime;
|
|
328
419
|
try {
|
|
329
|
-
runtime = await
|
|
420
|
+
runtime = await startServerWithAutoPortRetry(options);
|
|
330
421
|
}
|
|
331
422
|
catch (error) {
|
|
332
|
-
if (isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {
|
|
423
|
+
if (options.port?.mode !== "auto" && isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {
|
|
333
424
|
return;
|
|
334
425
|
}
|
|
335
426
|
throw error;
|
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 packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { isHooksSubcommand, runHooksSubcommand } from \"./commands/hooks.js\";\nimport { isMcpSubcommand, runMcpSubcommand } from \"./commands/mcp.js\";\nimport type {\n\tRuntimeAgentId,\n\tRuntimeShortcutRunResponse,\n} from \"./core/api-contract.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tKANBAN_RUNTIME_ORIGIN,\n} from \"./core/runtime-endpoint.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport {\n\tloadWorkspaceContext,\n} from \"./state/workspace-state.js\";\nimport {\n\tcollectProjectWorktreeTaskIdsForRemoval,\n\tcreateWorkspaceRegistry,\n} from \"./server/workspace-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\thelp: boolean;\n\tversion: boolean;\n\tnoOpen: boolean;\n\tagent: RuntimeAgentId | null;\n}\n\nconst CLI_AGENT_IDS: readonly RuntimeAgentId[] = [\"claude\", \"codex\", \"gemini\", \"opencode\", \"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 === \"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 parseCliOptions(argv: string[]): CliOptions {\n\tlet help = false;\n\tlet version = false;\n\tlet noOpen = false;\n\tlet agent: RuntimeAgentId | null = null;\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index];\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\thelp = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--version\" || arg === \"-v\") {\n\t\t\tversion = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--no-open\") {\n\t\t\tnoOpen = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--agent\") {\n\t\t\tconst value = argv[index + 1];\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--agent=\")) {\n\t\t\tconst value = arg.slice(\"--agent=\".length);\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t}\n\t}\n\n\treturn { help, version, noOpen, agent };\n}\n\nfunction printHelp(): void {\n\tconsole.log(\"kanban\");\n\tconsole.log(\"Local orchestration board for coding agents.\");\n\tconsole.log(\"\");\n\tconsole.log(\"Usage:\");\n\tconsole.log(\" kanban [--agent <id>] [--no-open] [--help] [--version]\");\n\tconsole.log(\" kanban mcp\");\n\tconsole.log(\"\");\n\tconsole.log(`Runtime URL: ${KANBAN_RUNTIME_ORIGIN}`);\n\tconsole.log(`Agent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\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 pickDirectoryPathFromSystemDialog(): string | null {\n\tif (process.platform === \"darwin\") {\n\t\tconst result = spawnSync(\n\t\t\t\"osascript\",\n\t\t\t[\"-e\", 'POSIX path of (choose folder with prompt \"Select a project folder\")'],\n\t\t\t{\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t},\n\t\t);\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\tif (process.platform === \"linux\") {\n\t\tconst result = spawnSync(\"zenity\", [\"--file-selection\", \"--directory\", \"--title=Select project folder\"], {\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\treturn null;\n}\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: KANBAN_RUNTIME_ORIGIN;\n\tconsole.log(`Kanban already running at ${KANBAN_RUNTIME_ORIGIN}`);\n\tif (!noOpen) {\n\t\ttry {\n\t\t\topenInBrowser(projectUrl);\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 runShortcutCommand(command: string, cwd: string): Promise<RuntimeShortcutRunResponse> {\n\tconst startedAt = Date.now();\n\tconst outputLimitBytes = 64 * 1024;\n\n\treturn await new Promise<RuntimeShortcutRunResponse>((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\tchild.kill(\"SIGTERM\");\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<{ url: string; close: () => Promise<void>; shutdown: () => Promise<void> }> {\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\trunShortcutCommand,\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 () => {\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});\n\t};\n\n\treturn {\n\t\turl: runtimeServer.url,\n\t\tclose,\n\t\tshutdown,\n\t};\n}\n\nasync function run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tif (isMcpSubcommand(argv)) {\n\t\tawait runMcpSubcommand(argv);\n\t\treturn;\n\t}\n\tif (isHooksSubcommand(argv)) {\n\t\tawait runHooksSubcommand(argv);\n\t\treturn;\n\t}\n\n\tconst options = parseCliOptions(argv);\n\n\tif (options.help) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\tif (options.version) {\n\t\tconsole.log(KANBAN_VERSION);\n\t\treturn;\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\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServer();\n\t} catch (error) {\n\t\tif (isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {\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} 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: \"SIGINT\" | \"SIGTERM\") => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\tconst forceExitTimer = setTimeout(() => {\n\t\t\tconsole.error(`Forced exit after ${signal} timeout.`);\n\t\t\tprocess.exit(130);\n\t\t}, 3000);\n\t\tforceExitTimer.unref();\n\t\ttry {\n\t\t\tawait runtime.shutdown();\n\t\t\tclearTimeout(forceExitTimer);\n\t\t\tprocess.exit(130);\n\t\t} catch (error) {\n\t\t\tclearTimeout(forceExitTimer);\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\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown(\"SIGINT\");\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown(\"SIGTERM\");\n\t});\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 packageJson from \"../package.json\" with { type: \"json\" };\n\nimport { isHooksSubcommand, runHooksSubcommand } from \"./commands/hooks.js\";\nimport { isMcpSubcommand, runMcpSubcommand } from \"./commands/mcp.js\";\nimport type {\n\tRuntimeAgentId,\n\tRuntimeCommandRunResponse,\n} from \"./core/api-contract.js\";\nimport { loadRuntimeConfig, updateRuntimeConfig } from \"./config/runtime-config.js\";\nimport { createGitProcessEnv } from \"./core/git-process-env.js\";\nimport { resolveProjectInputPath } from \"./projects/project-path.js\";\nimport {\n\tbuildKanbanRuntimeUrl,\n\tDEFAULT_KANBAN_RUNTIME_PORT,\n\tgetKanbanRuntimePort,\n\tgetKanbanRuntimeOrigin,\n\tparseRuntimePort,\n\tsetKanbanRuntimePort,\n} from \"./core/runtime-endpoint.js\";\nimport { openInBrowser } from \"./server/browser.js\";\nimport { createRuntimeStateHub } from \"./server/runtime-state-hub.js\";\nimport { createRuntimeServer } from \"./server/runtime-server.js\";\nimport { shutdownRuntimeServer } from \"./server/shutdown-coordinator.js\";\nimport { resolveInteractiveShellCommand } from \"./server/shell.js\";\nimport {\n\tloadWorkspaceContext,\n} from \"./state/workspace-state.js\";\nimport {\n\tcollectProjectWorktreeTaskIdsForRemoval,\n\tcreateWorkspaceRegistry,\n} from \"./server/workspace-registry.js\";\nimport type { TerminalSessionManager } from \"./terminal/session-manager.js\";\nimport { autoUpdateOnStartup } from \"./update/auto-update.js\";\n\ninterface CliOptions {\n\thelp: boolean;\n\tversion: boolean;\n\tnoOpen: 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\nfunction parseCliOptions(argv: string[]): CliOptions {\n\tlet help = false;\n\tlet version = false;\n\tlet noOpen = false;\n\tlet agent: RuntimeAgentId | null = null;\n\tlet port: { mode: \"fixed\"; value: number } | { mode: \"auto\" } | null = null;\n\n\tfor (let index = 0; index < argv.length; index += 1) {\n\t\tconst arg = argv[index];\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\thelp = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--version\" || arg === \"-v\") {\n\t\t\tversion = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--no-open\") {\n\t\t\tnoOpen = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--agent\") {\n\t\t\tconst value = argv[index + 1];\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--agent=\")) {\n\t\t\tconst value = arg.slice(\"--agent=\".length);\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --agent.\");\n\t\t\t}\n\t\t\tagent = parseCliAgentId(value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--port\") {\n\t\t\tconst value = argv[index + 1];\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --port.\");\n\t\t\t}\n\t\t\tport = parseCliPortValue(value);\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--port=\")) {\n\t\t\tconst value = arg.slice(\"--port=\".length);\n\t\t\tif (!value) {\n\t\t\t\tthrow new Error(\"Missing value for --port.\");\n\t\t\t}\n\t\t\tport = parseCliPortValue(value);\n\t\t}\n\t}\n\n\treturn { help, version, noOpen, agent, port };\n}\n\nfunction printHelp(): void {\n\tconsole.log(\"kanban\");\n\tconsole.log(\"Local orchestration board for coding agents.\");\n\tconsole.log(\"\");\n\tconsole.log(\"Usage:\");\n\tconsole.log(\" kanban [--agent <id>] [--port <number|auto>] [--no-open] [--help] [--version]\");\n\tconsole.log(\" kanban mcp\");\n\tconsole.log(\"\");\n\tconsole.log(`Runtime URL: ${getKanbanRuntimeOrigin()}`);\n\tconsole.log(`Agent IDs: ${CLI_AGENT_IDS.join(\", \")}`);\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 pickDirectoryPathFromSystemDialog(): string | null {\n\tif (process.platform === \"darwin\") {\n\t\tconst result = spawnSync(\n\t\t\t\"osascript\",\n\t\t\t[\"-e\", 'POSIX path of (choose folder with prompt \"Select a project folder\")'],\n\t\t\t{\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t},\n\t\t);\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\tif (process.platform === \"linux\") {\n\t\tconst result = spawnSync(\"zenity\", [\"--file-selection\", \"--directory\", \"--title=Select project folder\"], {\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tif (result.status !== 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst selected = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n\t\treturn selected || null;\n\t}\n\n\treturn null;\n}\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} 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\tchild.kill(\"SIGTERM\");\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<{ url: string; close: () => Promise<void>; shutdown: () => Promise<void> }> {\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 () => {\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});\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 run(): Promise<void> {\n\tconst argv = process.argv.slice(2);\n\tif (isMcpSubcommand(argv)) {\n\t\tawait runMcpSubcommand(argv);\n\t\treturn;\n\t}\n\tif (isHooksSubcommand(argv)) {\n\t\tawait runHooksSubcommand(argv);\n\t\treturn;\n\t}\n\n\tconst options = parseCliOptions(argv);\n\n\tif (options.help) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\tif (options.version) {\n\t\tconsole.log(KANBAN_VERSION);\n\t\treturn;\n\t}\n\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\tlet runtime: Awaited<ReturnType<typeof startServer>>;\n\ttry {\n\t\truntime = await startServerWithAutoPortRetry(options);\n\t} catch (error) {\n\t\tif (options.port?.mode !== \"auto\" && isAddressInUseError(error) && (await tryOpenExistingServer(options.noOpen))) {\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} 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: \"SIGINT\" | \"SIGTERM\") => {\n\t\tif (isShuttingDown) {\n\t\t\tprocess.exit(130);\n\t\t\treturn;\n\t\t}\n\t\tisShuttingDown = true;\n\t\tconst forceExitTimer = setTimeout(() => {\n\t\t\tconsole.error(`Forced exit after ${signal} timeout.`);\n\t\t\tprocess.exit(130);\n\t\t}, 3000);\n\t\tforceExitTimer.unref();\n\t\ttry {\n\t\t\tawait runtime.shutdown();\n\t\t\tclearTimeout(forceExitTimer);\n\t\t\tprocess.exit(130);\n\t\t} catch (error) {\n\t\t\tclearTimeout(forceExitTimer);\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\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown(\"SIGINT\");\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown(\"SIGTERM\");\n\t});\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"]}
|
|
@@ -3,7 +3,7 @@ export interface RuntimeConfigState {
|
|
|
3
3
|
globalConfigPath: string;
|
|
4
4
|
projectConfigPath: string;
|
|
5
5
|
selectedAgentId: RuntimeAgentId;
|
|
6
|
-
|
|
6
|
+
selectedShortcutLabel: string | null;
|
|
7
7
|
agentAutonomousModeEnabled: boolean;
|
|
8
8
|
readyForReviewNotificationsEnabled: boolean;
|
|
9
9
|
shortcuts: RuntimeProjectShortcut[];
|
|
@@ -14,7 +14,7 @@ export interface RuntimeConfigState {
|
|
|
14
14
|
}
|
|
15
15
|
export interface RuntimeConfigUpdateInput {
|
|
16
16
|
selectedAgentId?: RuntimeAgentId;
|
|
17
|
-
|
|
17
|
+
selectedShortcutLabel?: string | null;
|
|
18
18
|
agentAutonomousModeEnabled?: boolean;
|
|
19
19
|
readyForReviewNotificationsEnabled?: boolean;
|
|
20
20
|
shortcuts?: RuntimeProjectShortcut[];
|
|
@@ -27,7 +27,7 @@ export declare function getRuntimeProjectConfigPath(cwd: string): string;
|
|
|
27
27
|
export declare function loadRuntimeConfig(cwd: string): Promise<RuntimeConfigState>;
|
|
28
28
|
export declare function saveRuntimeConfig(cwd: string, config: {
|
|
29
29
|
selectedAgentId: RuntimeAgentId;
|
|
30
|
-
|
|
30
|
+
selectedShortcutLabel: string | null;
|
|
31
31
|
agentAutonomousModeEnabled: boolean;
|
|
32
32
|
readyForReviewNotificationsEnabled: boolean;
|
|
33
33
|
shortcuts: RuntimeProjectShortcut[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../../src/config/runtime-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAiBtF,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,cAAc,CAAC;IAChC,
|
|
1
|
+
{"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../../src/config/runtime-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAiBtF,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,cAAc,CAAC;IAChC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,0BAA0B,EAAE,OAAO,CAAC;IACpC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,MAAM,CAAC;IACpC,2BAA2B,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,wBAAwB;IACxC,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,kCAAkC,CAAC,EAAE,OAAO,CAAC;IAC7C,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAoDD,wBAAgB,oCAAoC,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,GAAG,IAAI,CAQ/G;AAwFD,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D;AAwID,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuBhF;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE;IACP,eAAe,EAAE,cAAc,CAAC;IAChC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,0BAA0B,EAAE,OAAO,CAAC;IACpC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC7B,GACC,OAAO,CAAC,kBAAkB,CAAC,CA+B7B;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4BrH"}
|
|
@@ -8,7 +8,7 @@ const CONFIG_FILENAME = "config.json";
|
|
|
8
8
|
const PROJECT_CONFIG_DIR = ".kanban";
|
|
9
9
|
const PROJECT_CONFIG_FILENAME = "config.json";
|
|
10
10
|
const DEFAULT_AGENT_ID = "claude";
|
|
11
|
-
const AUTO_SELECT_AGENT_PRIORITY = ["claude", "codex", "opencode", "gemini", "cline"];
|
|
11
|
+
const AUTO_SELECT_AGENT_PRIORITY = ["claude", "codex", "opencode", "droid", "gemini", "cline"];
|
|
12
12
|
const DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED = true;
|
|
13
13
|
const DEFAULT_READY_FOR_REVIEW_NOTIFICATIONS_ENABLED = true;
|
|
14
14
|
const DEFAULT_COMMIT_PROMPT_TEMPLATE = `You are in a worktree on a detached HEAD. When you are finished with the task, commit the working changes onto {{base_ref}}.
|
|
@@ -69,6 +69,7 @@ function normalizeAgentId(agentId) {
|
|
|
69
69
|
agentId === "codex" ||
|
|
70
70
|
agentId === "gemini" ||
|
|
71
71
|
agentId === "opencode" ||
|
|
72
|
+
agentId === "droid" ||
|
|
72
73
|
agentId === "cline") {
|
|
73
74
|
return agentId;
|
|
74
75
|
}
|
|
@@ -81,15 +82,13 @@ function normalizeShortcut(shortcut) {
|
|
|
81
82
|
if (!shortcut || typeof shortcut !== "object") {
|
|
82
83
|
return null;
|
|
83
84
|
}
|
|
84
|
-
const id = typeof shortcut.id === "string" ? shortcut.id.trim() : "";
|
|
85
85
|
const label = typeof shortcut.label === "string" ? shortcut.label.trim() : "";
|
|
86
86
|
const command = typeof shortcut.command === "string" ? shortcut.command.trim() : "";
|
|
87
87
|
const icon = typeof shortcut.icon === "string" ? shortcut.icon.trim() : "";
|
|
88
|
-
if (!
|
|
88
|
+
if (!label || !command) {
|
|
89
89
|
return null;
|
|
90
90
|
}
|
|
91
91
|
return {
|
|
92
|
-
id,
|
|
93
92
|
label,
|
|
94
93
|
command,
|
|
95
94
|
icon: icon || undefined,
|
|
@@ -121,7 +120,7 @@ function normalizeBoolean(value, fallback) {
|
|
|
121
120
|
}
|
|
122
121
|
return fallback;
|
|
123
122
|
}
|
|
124
|
-
function
|
|
123
|
+
function normalizeShortcutLabel(value) {
|
|
125
124
|
if (typeof value !== "string") {
|
|
126
125
|
return null;
|
|
127
126
|
}
|
|
@@ -145,7 +144,7 @@ function toRuntimeConfigState({ globalConfigPath, projectConfigPath, globalConfi
|
|
|
145
144
|
globalConfigPath,
|
|
146
145
|
projectConfigPath,
|
|
147
146
|
selectedAgentId: normalizeAgentId(globalConfig?.selectedAgentId),
|
|
148
|
-
|
|
147
|
+
selectedShortcutLabel: normalizeShortcutLabel(globalConfig?.selectedShortcutLabel),
|
|
149
148
|
agentAutonomousModeEnabled: normalizeBoolean(globalConfig?.agentAutonomousModeEnabled, DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED),
|
|
150
149
|
readyForReviewNotificationsEnabled: normalizeBoolean(globalConfig?.readyForReviewNotificationsEnabled, DEFAULT_READY_FOR_REVIEW_NOTIFICATIONS_ENABLED),
|
|
151
150
|
shortcuts: normalizeShortcuts(projectConfig?.shortcuts),
|
|
@@ -170,9 +169,9 @@ async function writeRuntimeGlobalConfigFile(configPath, config) {
|
|
|
170
169
|
const existingSelectedAgentId = hasOwnKey(existing, "selectedAgentId")
|
|
171
170
|
? normalizeAgentId(existing?.selectedAgentId)
|
|
172
171
|
: undefined;
|
|
173
|
-
const
|
|
174
|
-
const
|
|
175
|
-
?
|
|
172
|
+
const selectedShortcutLabel = config.selectedShortcutLabel === undefined ? undefined : normalizeShortcutLabel(config.selectedShortcutLabel);
|
|
173
|
+
const existingSelectedShortcutLabel = hasOwnKey(existing, "selectedShortcutLabel")
|
|
174
|
+
? normalizeShortcutLabel(existing?.selectedShortcutLabel)
|
|
176
175
|
: undefined;
|
|
177
176
|
const agentAutonomousModeEnabled = config.agentAutonomousModeEnabled === undefined
|
|
178
177
|
? DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED
|
|
@@ -195,13 +194,13 @@ async function writeRuntimeGlobalConfigFile(configPath, config) {
|
|
|
195
194
|
else if (existingSelectedAgentId !== undefined) {
|
|
196
195
|
payload.selectedAgentId = existingSelectedAgentId;
|
|
197
196
|
}
|
|
198
|
-
if (
|
|
199
|
-
if (
|
|
200
|
-
payload.
|
|
197
|
+
if (selectedShortcutLabel !== undefined) {
|
|
198
|
+
if (selectedShortcutLabel) {
|
|
199
|
+
payload.selectedShortcutLabel = selectedShortcutLabel;
|
|
201
200
|
}
|
|
202
201
|
}
|
|
203
|
-
else if (
|
|
204
|
-
payload.
|
|
202
|
+
else if (existingSelectedShortcutLabel) {
|
|
203
|
+
payload.selectedShortcutLabel = existingSelectedShortcutLabel;
|
|
205
204
|
}
|
|
206
205
|
if (hasOwnKey(existing, "agentAutonomousModeEnabled") ||
|
|
207
206
|
agentAutonomousModeEnabled !== DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED) {
|
|
@@ -259,7 +258,7 @@ export async function saveRuntimeConfig(cwd, config) {
|
|
|
259
258
|
const projectConfigPath = getRuntimeProjectConfigPath(cwd);
|
|
260
259
|
await writeRuntimeGlobalConfigFile(globalConfigPath, {
|
|
261
260
|
selectedAgentId: config.selectedAgentId,
|
|
262
|
-
|
|
261
|
+
selectedShortcutLabel: config.selectedShortcutLabel,
|
|
263
262
|
agentAutonomousModeEnabled: config.agentAutonomousModeEnabled,
|
|
264
263
|
readyForReviewNotificationsEnabled: config.readyForReviewNotificationsEnabled,
|
|
265
264
|
commitPromptTemplate: config.commitPromptTemplate,
|
|
@@ -270,7 +269,7 @@ export async function saveRuntimeConfig(cwd, config) {
|
|
|
270
269
|
globalConfigPath,
|
|
271
270
|
projectConfigPath,
|
|
272
271
|
selectedAgentId: normalizeAgentId(config.selectedAgentId),
|
|
273
|
-
|
|
272
|
+
selectedShortcutLabel: normalizeShortcutLabel(config.selectedShortcutLabel),
|
|
274
273
|
agentAutonomousModeEnabled: normalizeBoolean(config.agentAutonomousModeEnabled, DEFAULT_AGENT_AUTONOMOUS_MODE_ENABLED),
|
|
275
274
|
readyForReviewNotificationsEnabled: normalizeBoolean(config.readyForReviewNotificationsEnabled, DEFAULT_READY_FOR_REVIEW_NOTIFICATIONS_ENABLED),
|
|
276
275
|
shortcuts: normalizeShortcuts(config.shortcuts),
|
|
@@ -284,7 +283,7 @@ export async function updateRuntimeConfig(cwd, updates) {
|
|
|
284
283
|
const current = await loadRuntimeConfig(cwd);
|
|
285
284
|
const nextConfig = {
|
|
286
285
|
selectedAgentId: updates.selectedAgentId ?? current.selectedAgentId,
|
|
287
|
-
|
|
286
|
+
selectedShortcutLabel: updates.selectedShortcutLabel === undefined ? current.selectedShortcutLabel : updates.selectedShortcutLabel,
|
|
288
287
|
agentAutonomousModeEnabled: updates.agentAutonomousModeEnabled ?? current.agentAutonomousModeEnabled,
|
|
289
288
|
readyForReviewNotificationsEnabled: updates.readyForReviewNotificationsEnabled ?? current.readyForReviewNotificationsEnabled,
|
|
290
289
|
shortcuts: updates.shortcuts ?? current.shortcuts,
|
|
@@ -292,7 +291,7 @@ export async function updateRuntimeConfig(cwd, updates) {
|
|
|
292
291
|
openPrPromptTemplate: updates.openPrPromptTemplate ?? current.openPrPromptTemplate,
|
|
293
292
|
};
|
|
294
293
|
const hasChanges = nextConfig.selectedAgentId !== current.selectedAgentId ||
|
|
295
|
-
nextConfig.
|
|
294
|
+
nextConfig.selectedShortcutLabel !== current.selectedShortcutLabel ||
|
|
296
295
|
nextConfig.agentAutonomousModeEnabled !== current.agentAutonomousModeEnabled ||
|
|
297
296
|
nextConfig.readyForReviewNotificationsEnabled !== current.readyForReviewNotificationsEnabled ||
|
|
298
297
|
nextConfig.commitPromptTemplate !== current.commitPromptTemplate ||
|