codekanban 0.31.0 → 0.33.0
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 +22 -0
- package/README.zh-CN.md +15 -0
- package/package.json +6 -6
- package/packages/codekanban-cli/README.md +118 -0
- package/packages/codekanban-cli/package.json +48 -0
- package/packages/codekanban-cli/release/install-cli-unix.sh +9 -0
- package/packages/codekanban-cli/release/install-skills-unix.sh +12 -0
- package/packages/codekanban-cli/release/install-unix.sh +16 -0
- package/packages/codekanban-cli/release/install-windows.cmd +19 -0
- package/packages/codekanban-cli/skills/README.md +18 -0
- package/packages/codekanban-cli/skills/codekanban-cli/agents/openai.yaml +4 -0
- package/packages/codekanban-cli/src/core.js +1019 -0
- package/packages/codekanban-cli/src/index.js +13 -0
- package/packages/{node-sdk/src/cli.js → codekanban-cli/src/runtime.js} +353 -6
- package/packages/node-sdk/README.md +57 -33
- package/packages/node-sdk/package.json +2 -7
- package/packages/node-sdk/src/client.js +810 -56
- package/packages/node-sdk/src/terminal-connection.js +2 -2
- package/packages/node-sdk/src/utils.js +25 -3
- package/packages/node-sdk/src/web-session-command-channel.js +2 -2
- package/packages/node-sdk/src/web-session-event-stream.js +1 -1
- package/packages/node-sdk/src/web-session-shared.js +44 -1
- package/skills/codekanban-project-session/agents/openai.yaml +0 -4
- package/skills/codekanban-project-session/scripts/run-codekanban-session.mjs +0 -7
|
@@ -6,7 +6,7 @@ function decodeJsonMessage(raw) {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export class TerminalConnection {
|
|
9
|
-
constructor({ sessionId, url, WebSocketImpl }) {
|
|
9
|
+
constructor({ sessionId, url, WebSocketImpl, webSocketOptions } = {}) {
|
|
10
10
|
if (!sessionId) {
|
|
11
11
|
throw new CodeKanbanValidationError('sessionId is required');
|
|
12
12
|
}
|
|
@@ -25,7 +25,7 @@ export class TerminalConnection {
|
|
|
25
25
|
this.readyMessage = undefined;
|
|
26
26
|
this._listeners = new Map();
|
|
27
27
|
|
|
28
|
-
this.socket = new Socket(url);
|
|
28
|
+
this.socket = webSocketOptions ? new Socket(url, webSocketOptions) : new Socket(url);
|
|
29
29
|
this._readyResolve = null;
|
|
30
30
|
this._readyReject = null;
|
|
31
31
|
this._readyPromise = new Promise((resolve, reject) => {
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
1
|
+
import path from 'node:path';
|
|
2
2
|
|
|
3
3
|
import { CodeKanbanConfigError, CodeKanbanValidationError } from './errors.js';
|
|
4
4
|
|
|
5
|
+
function isWindowsAbsolutePath(value) {
|
|
6
|
+
return /^[a-zA-Z]:[\\/]/.test(value) || value.startsWith('\\\\');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function isPosixAbsolutePath(value) {
|
|
10
|
+
return value.startsWith('/');
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
export function normalizeBaseUrl(baseURL) {
|
|
6
14
|
const value = String(baseURL || '').trim();
|
|
7
15
|
if (!value) {
|
|
@@ -46,14 +54,27 @@ export function ensureArrayOfStrings(value, fieldName) {
|
|
|
46
54
|
|
|
47
55
|
export function normalizeFsPath(inputPath) {
|
|
48
56
|
const value = ensureString(inputPath, 'path');
|
|
57
|
+
if (isWindowsAbsolutePath(value)) {
|
|
58
|
+
return path.win32.normalize(value).toLowerCase();
|
|
59
|
+
}
|
|
60
|
+
if (isPosixAbsolutePath(value)) {
|
|
61
|
+
return path.posix.normalize(value);
|
|
62
|
+
}
|
|
49
63
|
const resolved = path.resolve(value);
|
|
50
64
|
const normalized = path.normalize(resolved);
|
|
51
65
|
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
export function pathBasename(inputPath) {
|
|
55
|
-
const
|
|
56
|
-
|
|
69
|
+
const value = String(inputPath || '').trim();
|
|
70
|
+
if (!value) {
|
|
71
|
+
return 'project';
|
|
72
|
+
}
|
|
73
|
+
const base = isWindowsAbsolutePath(value)
|
|
74
|
+
? path.win32.basename(path.win32.normalize(value))
|
|
75
|
+
: isPosixAbsolutePath(value)
|
|
76
|
+
? path.posix.basename(path.posix.normalize(value))
|
|
77
|
+
: path.basename(path.resolve(value));
|
|
57
78
|
return base || 'project';
|
|
58
79
|
}
|
|
59
80
|
|
|
@@ -97,3 +118,4 @@ export function toCommandString(argv) {
|
|
|
97
118
|
export function createJsonOutput(value) {
|
|
98
119
|
return `${JSON.stringify(value, null, 2)}\n`;
|
|
99
120
|
}
|
|
121
|
+
|
|
@@ -34,7 +34,7 @@ function normalizeHistoryLimit(value) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export class WebSessionCommandChannel {
|
|
37
|
-
constructor({ url, WebSocketImpl } = {}) {
|
|
37
|
+
constructor({ url, WebSocketImpl, webSocketOptions } = {}) {
|
|
38
38
|
const resolvedUrl = ensureString(url, "url");
|
|
39
39
|
const Socket = WebSocketImpl || globalThis.WebSocket;
|
|
40
40
|
if (!Socket) {
|
|
@@ -44,7 +44,7 @@ export class WebSessionCommandChannel {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
this.url = resolvedUrl;
|
|
47
|
-
this.socket = new Socket(resolvedUrl);
|
|
47
|
+
this.socket = webSocketOptions ? new Socket(resolvedUrl, webSocketOptions) : new Socket(resolvedUrl);
|
|
48
48
|
this.protocolVersion = WEB_SESSION_PROTOCOL_VERSION;
|
|
49
49
|
this._pendingRequests = new Map();
|
|
50
50
|
this._pendingFollowUp = null;
|
|
@@ -22,7 +22,7 @@ function nowEventBase() {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export class WebSessionEventStream {
|
|
25
|
-
constructor({ url, sessionId, WebSocketImpl } = {}) {
|
|
25
|
+
constructor({ url, sessionId, WebSocketImpl, webSocketOptions } = {}) {
|
|
26
26
|
const resolvedUrl = ensureString(url, 'url');
|
|
27
27
|
const Socket = WebSocketImpl || globalThis.WebSocket;
|
|
28
28
|
if (!Socket) {
|
|
@@ -73,6 +73,22 @@ function normalizeUsage(value) {
|
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
function normalizeContextEstimate(value, usageFallback) {
|
|
77
|
+
return {
|
|
78
|
+
inputTokens: numberValue(value?.in, numberValue(usageFallback?.in, 0)),
|
|
79
|
+
cachedInputTokens: numberValue(value?.cin, numberValue(usageFallback?.cin, 0)),
|
|
80
|
+
outputTokens: numberValue(value?.out, numberValue(usageFallback?.out, 0)),
|
|
81
|
+
usedTokens: numberValue(
|
|
82
|
+
value?.usd,
|
|
83
|
+
Math.max(
|
|
84
|
+
0,
|
|
85
|
+
numberValue(value?.in, numberValue(usageFallback?.in, 0)) +
|
|
86
|
+
numberValue(value?.out, numberValue(usageFallback?.out, 0)),
|
|
87
|
+
),
|
|
88
|
+
),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
76
92
|
function normalizeHistoryAttachment(value) {
|
|
77
93
|
return {
|
|
78
94
|
id: trimmedString(value?.id),
|
|
@@ -185,6 +201,25 @@ function normalizePendingInput(value) {
|
|
|
185
201
|
};
|
|
186
202
|
}
|
|
187
203
|
|
|
204
|
+
function normalizePendingUserInputState(value) {
|
|
205
|
+
const itemId = trimmedString(value?.iid ?? value?.itemId);
|
|
206
|
+
if (!itemId) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
itemId,
|
|
211
|
+
prompt: trimmedString(value?.txt ?? value?.prompt) || "",
|
|
212
|
+
questions: Array.isArray(value?.qs ?? value?.questions)
|
|
213
|
+
? (value.qs ?? value.questions).map(normalizeUserInputQuestion)
|
|
214
|
+
: [],
|
|
215
|
+
requestedAt:
|
|
216
|
+
isoFromUnixMilli(value?.ra) ||
|
|
217
|
+
(typeof value?.requestedAt === "string"
|
|
218
|
+
? trimmedString(value.requestedAt) || null
|
|
219
|
+
: null),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
188
223
|
export function normalizeWebSessionHistoryItem(value) {
|
|
189
224
|
const updatedTimestamp =
|
|
190
225
|
isoFromUnixMilli(value?.ts2) || isoFromUnixMilli(value?.obs);
|
|
@@ -262,6 +297,10 @@ export function normalizeWebSessionSummaryFromWire(value) {
|
|
|
262
297
|
...normalizeUsage(value?.usa),
|
|
263
298
|
cost: numberValue(value?.cost, 0),
|
|
264
299
|
},
|
|
300
|
+
latestTurnUsage: value?.ltu ? normalizeContextEstimate(value.ltu, null) : null,
|
|
301
|
+
contextEstimate: normalizeContextEstimate(value?.cea, value?.usa),
|
|
302
|
+
contextEstimateMode: trimmedString(value?.cem) || "cumulative_total",
|
|
303
|
+
lastContextCompactionAt: isoFromUnixMilli(value?.lcca),
|
|
265
304
|
contextWindowTokens: nullableNumberValue(value?.cwt),
|
|
266
305
|
contextWindowSource: trimmedString(value?.cws) || "unavailable",
|
|
267
306
|
};
|
|
@@ -274,6 +313,7 @@ export function normalizeWebSessionSnapshotFromWire(frame) {
|
|
|
274
313
|
pendingInputs: Array.isArray(frame?.pi)
|
|
275
314
|
? frame.pi.map(normalizePendingInput).filter(Boolean)
|
|
276
315
|
: [],
|
|
316
|
+
pendingUserInput: normalizePendingUserInputState(frame?.ui),
|
|
277
317
|
};
|
|
278
318
|
}
|
|
279
319
|
|
|
@@ -468,7 +508,9 @@ export function analyzeWebSession(snapshot) {
|
|
|
468
508
|
: [];
|
|
469
509
|
const items = Array.isArray(history.items) ? history.items : [];
|
|
470
510
|
const pendingApproval = findPendingApproval(items);
|
|
471
|
-
const pendingUserInput =
|
|
511
|
+
const pendingUserInput =
|
|
512
|
+
normalizePendingUserInputState(snapshot?.pendingUserInput) ||
|
|
513
|
+
findPendingUserInput(items);
|
|
472
514
|
const latestPlan = findLatestPlan(items);
|
|
473
515
|
const lastAssistantMessage = findLastAssistantMessage(items);
|
|
474
516
|
|
|
@@ -543,6 +585,7 @@ export function analyzeWebSession(snapshot) {
|
|
|
543
585
|
session,
|
|
544
586
|
history,
|
|
545
587
|
pendingInputs,
|
|
588
|
+
pendingUserInput,
|
|
546
589
|
},
|
|
547
590
|
};
|
|
548
591
|
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
interface:
|
|
2
|
-
display_name: "CodeKanban Project Session"
|
|
3
|
-
short_description: "Prefer web sessions for CodeKanban AI work"
|
|
4
|
-
default_prompt: "Use the CodeKanban project session workflow with web session as the default interactive path. Prefer web-session create/control/watch for structured AI work in a project path, and use workflow start or terminal continue only when the user explicitly wants PTY-style terminal behavior or startup profiles such as plan or yolo."
|