@basou/core 0.23.0 → 0.25.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/dist/index.d.ts +27 -18
- package/dist/index.js +198 -128
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -21,69 +21,165 @@ function summarizeAdapterOutput(_stream, _raw) {
|
|
|
21
21
|
throw new Error("adapter_output summary is not implemented in this release");
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// src/adapters/claude-code/ask-user-question.ts
|
|
25
|
+
function readString(value) {
|
|
26
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
27
|
+
}
|
|
28
|
+
function isObject(value) {
|
|
29
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30
|
+
}
|
|
31
|
+
function toolUsesOf(record) {
|
|
32
|
+
const message = isObject(record.message) ? record.message : void 0;
|
|
33
|
+
const content = message !== void 0 && Array.isArray(message.content) ? message.content : [];
|
|
34
|
+
const result = [];
|
|
35
|
+
for (const item of content) {
|
|
36
|
+
if (isObject(item) && readString(item.type) === "tool_use") result.push(item);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
function indexAskAnswers(records) {
|
|
41
|
+
const byId = /* @__PURE__ */ new Map();
|
|
42
|
+
for (const record of records) {
|
|
43
|
+
const result = record.toolUseResult;
|
|
44
|
+
if (!isObject(result)) continue;
|
|
45
|
+
const answers = result.answers;
|
|
46
|
+
if (!isObject(answers)) continue;
|
|
47
|
+
const message = isObject(record.message) ? record.message : void 0;
|
|
48
|
+
const content = message !== void 0 && Array.isArray(message.content) ? message.content : [];
|
|
49
|
+
for (const item of content) {
|
|
50
|
+
if (isObject(item) && readString(item.type) === "tool_result") {
|
|
51
|
+
const id = readString(item.tool_use_id);
|
|
52
|
+
if (id !== void 0) byId.set(id, answers);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return byId;
|
|
57
|
+
}
|
|
58
|
+
function readOfferedOptions(input) {
|
|
59
|
+
const byQuestion = /* @__PURE__ */ new Map();
|
|
60
|
+
const questions = Array.isArray(input.questions) ? input.questions : [];
|
|
61
|
+
for (const q of questions) {
|
|
62
|
+
if (!isObject(q)) continue;
|
|
63
|
+
const text = readString(q.question);
|
|
64
|
+
if (text === void 0) continue;
|
|
65
|
+
const labels = /* @__PURE__ */ new Set();
|
|
66
|
+
const options = Array.isArray(q.options) ? q.options : [];
|
|
67
|
+
for (const o of options) {
|
|
68
|
+
if (!isObject(o)) continue;
|
|
69
|
+
const label = readString(o.label);
|
|
70
|
+
if (label !== void 0) labels.add(label.trim());
|
|
71
|
+
}
|
|
72
|
+
byQuestion.set(text, labels);
|
|
73
|
+
}
|
|
74
|
+
return byQuestion;
|
|
75
|
+
}
|
|
76
|
+
function countUncapturedDecisionPoints(records) {
|
|
77
|
+
const answersById = indexAskAnswers(records);
|
|
78
|
+
if (answersById.size === 0) return 0;
|
|
79
|
+
let count = 0;
|
|
80
|
+
for (const record of records) {
|
|
81
|
+
if (readString(record.type) !== "assistant") continue;
|
|
82
|
+
for (const tool of toolUsesOf(record)) {
|
|
83
|
+
if (readString(tool.name) !== "AskUserQuestion") continue;
|
|
84
|
+
const useId = readString(tool.id);
|
|
85
|
+
const answers = useId !== void 0 ? answersById.get(useId) : void 0;
|
|
86
|
+
if (answers === void 0) continue;
|
|
87
|
+
const input = isObject(tool.input) ? tool.input : void 0;
|
|
88
|
+
if (input === void 0) continue;
|
|
89
|
+
const offeredByQuestion = readOfferedOptions(input);
|
|
90
|
+
for (const [question, answer] of Object.entries(answers)) {
|
|
91
|
+
if (question.length === 0) continue;
|
|
92
|
+
const trimmed = typeof answer === "string" ? answer.trim() : "";
|
|
93
|
+
if (trimmed.length === 0) continue;
|
|
94
|
+
const offered = offeredByQuestion.get(question);
|
|
95
|
+
if (offered === void 0 || !offered.has(trimmed)) count += 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return count;
|
|
100
|
+
}
|
|
101
|
+
|
|
24
102
|
// src/adapters/claude-code/stop-hook.ts
|
|
25
|
-
var
|
|
26
|
-
var
|
|
103
|
+
var DEFAULT_STOP_HOOK_MIN_EDITS = 2;
|
|
104
|
+
var CAPTURE_INVOCATION = /(?:basou|(?:\S*\/)?node\s+\S*cli\/dist\/index\.js)/;
|
|
105
|
+
var CAPTURE_VERB = /(?:decision\s+(?:capture|record)|note)\b/;
|
|
106
|
+
var CAPTURE_COMMAND_PATTERN = new RegExp(
|
|
107
|
+
`(?:^|[\\n;&|(])\\s*${CAPTURE_INVOCATION.source}\\s+${CAPTURE_VERB.source}`
|
|
108
|
+
);
|
|
27
109
|
var FILE_EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "NotebookEdit"]);
|
|
28
110
|
function evaluateStopHook(input) {
|
|
29
|
-
const
|
|
111
|
+
const minEdits = input.minEdits ?? DEFAULT_STOP_HOOK_MIN_EDITS;
|
|
30
112
|
if (input.stopHookActive) {
|
|
31
|
-
return {
|
|
113
|
+
return {
|
|
114
|
+
kind: "silent",
|
|
115
|
+
reason: "stop_hook_active",
|
|
116
|
+
commandCount: 0,
|
|
117
|
+
fileCount: 0,
|
|
118
|
+
decisionPointCount: 0
|
|
119
|
+
};
|
|
32
120
|
}
|
|
33
121
|
let commandCount = 0;
|
|
34
122
|
let fileCount = 0;
|
|
35
123
|
let captured = false;
|
|
36
124
|
for (const record of input.records) {
|
|
37
|
-
if (
|
|
38
|
-
for (const tool of
|
|
39
|
-
const name =
|
|
125
|
+
if (readString2(record.type) !== "assistant") continue;
|
|
126
|
+
for (const tool of toolUsesOf2(record)) {
|
|
127
|
+
const name = readString2(tool.name);
|
|
40
128
|
if (name === void 0) continue;
|
|
41
129
|
if (name === "Bash") {
|
|
42
130
|
commandCount += 1;
|
|
43
|
-
const
|
|
44
|
-
const command =
|
|
131
|
+
const toolInput = isObject2(tool.input) ? tool.input : void 0;
|
|
132
|
+
const command = toolInput !== void 0 ? readString2(toolInput.command) : void 0;
|
|
45
133
|
if (command !== void 0 && CAPTURE_COMMAND_PATTERN.test(command)) captured = true;
|
|
46
134
|
} else if (FILE_EDIT_TOOLS.has(name)) {
|
|
47
135
|
fileCount += 1;
|
|
48
136
|
}
|
|
49
137
|
}
|
|
50
138
|
}
|
|
139
|
+
const decisionPointCount = countUncapturedDecisionPoints(input.records);
|
|
140
|
+
const counts = { commandCount, fileCount, decisionPointCount };
|
|
51
141
|
if (captured) {
|
|
52
|
-
return { kind: "silent", reason: "already_captured",
|
|
142
|
+
return { kind: "silent", reason: "already_captured", ...counts };
|
|
53
143
|
}
|
|
54
|
-
|
|
55
|
-
|
|
144
|
+
const substantive = fileCount >= minEdits || decisionPointCount > 0;
|
|
145
|
+
if (!substantive) {
|
|
146
|
+
return { kind: "silent", reason: "not_substantive", ...counts };
|
|
56
147
|
}
|
|
57
|
-
return {
|
|
58
|
-
kind: "nudge",
|
|
59
|
-
additionalContext: renderNudge(commandCount, fileCount),
|
|
60
|
-
commandCount,
|
|
61
|
-
fileCount
|
|
62
|
-
};
|
|
148
|
+
return { kind: "nudge", additionalContext: renderNudge(counts), ...counts };
|
|
63
149
|
}
|
|
64
|
-
function renderNudge(
|
|
65
|
-
const
|
|
66
|
-
|
|
150
|
+
function renderNudge(counts) {
|
|
151
|
+
const did = [];
|
|
152
|
+
if (counts.commandCount > 0) {
|
|
153
|
+
did.push(`ran ${counts.commandCount} ${counts.commandCount === 1 ? "command" : "commands"}`);
|
|
154
|
+
}
|
|
155
|
+
if (counts.fileCount > 0) {
|
|
156
|
+
did.push(`edited ${counts.fileCount} ${counts.fileCount === 1 ? "file" : "files"}`);
|
|
157
|
+
}
|
|
158
|
+
if (counts.decisionPointCount > 0) {
|
|
159
|
+
const n = counts.decisionPointCount;
|
|
160
|
+
did.push(`answered ${n} open-ended ${n === 1 ? "question" : "questions"}`);
|
|
161
|
+
}
|
|
162
|
+
const summary = did.length > 0 ? did.join(", ") : "did substantive work";
|
|
67
163
|
return [
|
|
68
|
-
`This session
|
|
164
|
+
`This session ${summary} but recorded no decisions or next step.`,
|
|
69
165
|
"If meaningful decisions were made (the chosen approach, rejected alternatives, and why) or there is a clear next step, capture them now so the next session can resume correctly:",
|
|
70
166
|
' - Decisions: run `basou decision capture` and pipe a JSON array (one object per decision; "title" required, plus optional rationale/alternatives/rejected_reason/linked_files; set "kind":"track" for an unfinished strategic direction).',
|
|
71
167
|
' - Next step: run `basou note "<what you would do next>"`.',
|
|
72
168
|
"If nothing is worth capturing, just stop \u2014 do not invent decisions."
|
|
73
169
|
].join("\n");
|
|
74
170
|
}
|
|
75
|
-
function
|
|
171
|
+
function readString2(value) {
|
|
76
172
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
77
173
|
}
|
|
78
|
-
function
|
|
174
|
+
function isObject2(value) {
|
|
79
175
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
80
176
|
}
|
|
81
|
-
function
|
|
82
|
-
const message =
|
|
177
|
+
function toolUsesOf2(record) {
|
|
178
|
+
const message = isObject2(record.message) ? record.message : void 0;
|
|
83
179
|
const content = message !== void 0 && Array.isArray(message.content) ? message.content : [];
|
|
84
180
|
const result = [];
|
|
85
181
|
for (const item of content) {
|
|
86
|
-
if (
|
|
182
|
+
if (isObject2(item) && readString2(item.type) === "tool_use") result.push(item);
|
|
87
183
|
}
|
|
88
184
|
return result;
|
|
89
185
|
}
|
|
@@ -195,21 +291,21 @@ function claudeTranscriptToImportPayload(records, options) {
|
|
|
195
291
|
const engagementTsMs = [];
|
|
196
292
|
const seenEngagementMessageIds = /* @__PURE__ */ new Set();
|
|
197
293
|
for (const record of records) {
|
|
198
|
-
const ts =
|
|
294
|
+
const ts = readString3(record.timestamp);
|
|
199
295
|
if (ts === void 0) continue;
|
|
200
296
|
if (minTs === void 0 || Date.parse(ts) < Date.parse(minTs)) minTs = ts;
|
|
201
297
|
if (maxTs === void 0 || Date.parse(ts) > Date.parse(maxTs)) maxTs = ts;
|
|
202
|
-
if (workingDir === void 0) workingDir =
|
|
203
|
-
if (claudeSessionId === void 0) claudeSessionId =
|
|
298
|
+
if (workingDir === void 0) workingDir = readString3(record.cwd);
|
|
299
|
+
if (claudeSessionId === void 0) claudeSessionId = readString3(record.sessionId);
|
|
204
300
|
if (record.isSidechain !== true) {
|
|
205
301
|
const tsMs = Date.parse(ts);
|
|
206
302
|
if (Number.isFinite(tsMs)) {
|
|
207
|
-
const recType =
|
|
303
|
+
const recType = readString3(record.type);
|
|
208
304
|
if (recType === "user") {
|
|
209
305
|
if (isHumanUserMessage(record)) engagementTsMs.push(tsMs);
|
|
210
306
|
} else if (recType === "assistant") {
|
|
211
|
-
const msg =
|
|
212
|
-
const mid = msg !== void 0 ?
|
|
307
|
+
const msg = isObject3(record.message) ? record.message : void 0;
|
|
308
|
+
const mid = msg !== void 0 ? readString3(msg.id) : void 0;
|
|
213
309
|
if (mid === void 0 || !seenEngagementMessageIds.has(mid)) {
|
|
214
310
|
if (mid !== void 0) seenEngagementMessageIds.add(mid);
|
|
215
311
|
engagementTsMs.push(tsMs);
|
|
@@ -217,11 +313,11 @@ function claudeTranscriptToImportPayload(records, options) {
|
|
|
217
313
|
}
|
|
218
314
|
}
|
|
219
315
|
}
|
|
220
|
-
if (
|
|
221
|
-
const message =
|
|
222
|
-
const usage = message !== void 0 &&
|
|
316
|
+
if (readString3(record.type) !== "assistant") continue;
|
|
317
|
+
const message = isObject3(record.message) ? record.message : void 0;
|
|
318
|
+
const usage = message !== void 0 && isObject3(message.usage) ? message.usage : void 0;
|
|
223
319
|
if (usage !== void 0) {
|
|
224
|
-
const messageId = message !== void 0 ?
|
|
320
|
+
const messageId = message !== void 0 ? readString3(message.id) : void 0;
|
|
225
321
|
const alreadyCounted = messageId !== void 0 && seenMessageIds.has(messageId);
|
|
226
322
|
if (!alreadyCounted) {
|
|
227
323
|
if (messageId !== void 0) seenMessageIds.add(messageId);
|
|
@@ -230,20 +326,20 @@ function claudeTranscriptToImportPayload(records, options) {
|
|
|
230
326
|
cachedInputTokens += readNonNegInt(usage.cache_read_input_tokens);
|
|
231
327
|
}
|
|
232
328
|
}
|
|
233
|
-
const cwd =
|
|
329
|
+
const cwd = readString3(record.cwd) ?? workingDir ?? ".";
|
|
234
330
|
for (const item of toolUses(record)) {
|
|
235
|
-
const name =
|
|
236
|
-
const input =
|
|
331
|
+
const name = readString3(item.name);
|
|
332
|
+
const input = isObject3(item.input) ? item.input : void 0;
|
|
237
333
|
if (input === void 0) continue;
|
|
238
334
|
if (name === "Bash") {
|
|
239
|
-
const command =
|
|
335
|
+
const command = readString3(input.command);
|
|
240
336
|
if (command !== void 0) {
|
|
241
337
|
derived.push(commandExecutedEvent(ts, placeholderSessionId, command, cwd));
|
|
242
338
|
}
|
|
243
339
|
continue;
|
|
244
340
|
}
|
|
245
341
|
if (name === "AskUserQuestion") {
|
|
246
|
-
const useId =
|
|
342
|
+
const useId = readString3(item.id);
|
|
247
343
|
const answers = useId !== void 0 ? askAnswers.get(useId) : void 0;
|
|
248
344
|
if (answers !== void 0) {
|
|
249
345
|
const offeredByQuestion = readOfferedOptions(input);
|
|
@@ -261,7 +357,7 @@ function claudeTranscriptToImportPayload(records, options) {
|
|
|
261
357
|
continue;
|
|
262
358
|
}
|
|
263
359
|
if (name === "Edit" || name === "Write" || name === "NotebookEdit") {
|
|
264
|
-
const path2 =
|
|
360
|
+
const path2 = readString3(input.file_path) ?? readString3(input.notebook_path);
|
|
265
361
|
if (path2 !== void 0) {
|
|
266
362
|
const changeType = name === "Write" ? "added" : "modified";
|
|
267
363
|
relatedFiles.add(path2);
|
|
@@ -363,76 +459,40 @@ function decisionRecordedEvent(occurredAt, sessionId, title) {
|
|
|
363
459
|
title
|
|
364
460
|
};
|
|
365
461
|
}
|
|
366
|
-
function
|
|
462
|
+
function readString3(value) {
|
|
367
463
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
368
464
|
}
|
|
369
465
|
function readNonNegInt(value) {
|
|
370
466
|
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : 0;
|
|
371
467
|
}
|
|
372
|
-
function
|
|
468
|
+
function isObject3(value) {
|
|
373
469
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
374
470
|
}
|
|
375
471
|
function isHumanUserMessage(record) {
|
|
376
|
-
const message =
|
|
472
|
+
const message = isObject3(record.message) ? record.message : void 0;
|
|
377
473
|
if (message === void 0) return false;
|
|
378
474
|
const content = message.content;
|
|
379
475
|
if (typeof content === "string") return content.length > 0;
|
|
380
476
|
if (Array.isArray(content)) {
|
|
381
477
|
return content.some((block) => {
|
|
382
|
-
if (!
|
|
383
|
-
const type =
|
|
478
|
+
if (!isObject3(block)) return false;
|
|
479
|
+
const type = readString3(block.type);
|
|
384
480
|
return type !== void 0 && type !== "tool_result";
|
|
385
481
|
});
|
|
386
482
|
}
|
|
387
483
|
return false;
|
|
388
484
|
}
|
|
389
485
|
function toolUses(record) {
|
|
390
|
-
const message =
|
|
486
|
+
const message = isObject3(record.message) ? record.message : void 0;
|
|
391
487
|
const content = message !== void 0 && Array.isArray(message.content) ? message.content : [];
|
|
392
488
|
const result = [];
|
|
393
489
|
for (const item of content) {
|
|
394
|
-
if (
|
|
490
|
+
if (isObject3(item) && readString3(item.type) === "tool_use") {
|
|
395
491
|
result.push(item);
|
|
396
492
|
}
|
|
397
493
|
}
|
|
398
494
|
return result;
|
|
399
495
|
}
|
|
400
|
-
function indexAskAnswers(records) {
|
|
401
|
-
const byId = /* @__PURE__ */ new Map();
|
|
402
|
-
for (const record of records) {
|
|
403
|
-
const result = record.toolUseResult;
|
|
404
|
-
if (!isObject2(result)) continue;
|
|
405
|
-
const answers = result.answers;
|
|
406
|
-
if (!isObject2(answers)) continue;
|
|
407
|
-
const message = isObject2(record.message) ? record.message : void 0;
|
|
408
|
-
const content = message !== void 0 && Array.isArray(message.content) ? message.content : [];
|
|
409
|
-
for (const item of content) {
|
|
410
|
-
if (isObject2(item) && readString2(item.type) === "tool_result") {
|
|
411
|
-
const id = readString2(item.tool_use_id);
|
|
412
|
-
if (id !== void 0) byId.set(id, answers);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
return byId;
|
|
417
|
-
}
|
|
418
|
-
function readOfferedOptions(input) {
|
|
419
|
-
const byQuestion = /* @__PURE__ */ new Map();
|
|
420
|
-
const questions = Array.isArray(input.questions) ? input.questions : [];
|
|
421
|
-
for (const q of questions) {
|
|
422
|
-
if (!isObject2(q)) continue;
|
|
423
|
-
const text = readString2(q.question);
|
|
424
|
-
if (text === void 0) continue;
|
|
425
|
-
const labels = /* @__PURE__ */ new Set();
|
|
426
|
-
const options = Array.isArray(q.options) ? q.options : [];
|
|
427
|
-
for (const o of options) {
|
|
428
|
-
if (!isObject2(o)) continue;
|
|
429
|
-
const label = readString2(o.label);
|
|
430
|
-
if (label !== void 0) labels.add(label.trim());
|
|
431
|
-
}
|
|
432
|
-
byQuestion.set(text, labels);
|
|
433
|
-
}
|
|
434
|
-
return byQuestion;
|
|
435
|
-
}
|
|
436
496
|
|
|
437
497
|
// src/adapters/codex/rollout-importer.ts
|
|
438
498
|
var CODEX_IMPORT_SOURCE = "codex-import";
|
|
@@ -450,31 +510,31 @@ function codexRolloutToImportPayload(records, options) {
|
|
|
450
510
|
const completions = [];
|
|
451
511
|
const completedTurnIds = /* @__PURE__ */ new Set();
|
|
452
512
|
for (const record of records) {
|
|
453
|
-
const ts =
|
|
513
|
+
const ts = readString4(record.timestamp);
|
|
454
514
|
if (ts === void 0) continue;
|
|
455
515
|
if (minTs === void 0 || Date.parse(ts) < Date.parse(minTs)) minTs = ts;
|
|
456
516
|
if (maxTs === void 0 || Date.parse(ts) > Date.parse(maxTs)) maxTs = ts;
|
|
457
|
-
const payload2 =
|
|
517
|
+
const payload2 = isObject4(record.payload) ? record.payload : void 0;
|
|
458
518
|
if (payload2 === void 0) continue;
|
|
459
|
-
if (
|
|
460
|
-
if (workingDir === void 0) workingDir =
|
|
461
|
-
if (codexSessionId === void 0) codexSessionId =
|
|
519
|
+
if (readString4(record.type) === "session_meta") {
|
|
520
|
+
if (workingDir === void 0) workingDir = readString4(payload2.cwd);
|
|
521
|
+
if (codexSessionId === void 0) codexSessionId = readString4(payload2.id);
|
|
462
522
|
continue;
|
|
463
523
|
}
|
|
464
|
-
if (
|
|
465
|
-
const info =
|
|
466
|
-
const totals = info !== void 0 &&
|
|
524
|
+
if (readString4(record.type) === "event_msg" && readString4(payload2.type) === "token_count") {
|
|
525
|
+
const info = isObject4(payload2.info) ? payload2.info : void 0;
|
|
526
|
+
const totals = info !== void 0 && isObject4(info.total_token_usage) ? info.total_token_usage : void 0;
|
|
467
527
|
if (totals !== void 0) lastTokenTotals = totals;
|
|
468
528
|
continue;
|
|
469
529
|
}
|
|
470
|
-
if (
|
|
471
|
-
const pt =
|
|
530
|
+
if (readString4(record.type) === "event_msg") {
|
|
531
|
+
const pt = readString4(payload2.type);
|
|
472
532
|
if (pt === "user_message" || pt === "agent_message" || pt === "task_started" || pt === "task_complete") {
|
|
473
533
|
const tsMs = Date.parse(ts);
|
|
474
534
|
if (Number.isFinite(tsMs)) engagementTsMs.push(tsMs);
|
|
475
535
|
}
|
|
476
536
|
if (pt === "task_complete") {
|
|
477
|
-
const turnId =
|
|
537
|
+
const turnId = readString4(payload2.turn_id);
|
|
478
538
|
if (turnId === void 0 || !completedTurnIds.has(turnId)) {
|
|
479
539
|
if (turnId !== void 0) completedTurnIds.add(turnId);
|
|
480
540
|
completions.push({
|
|
@@ -485,9 +545,9 @@ function codexRolloutToImportPayload(records, options) {
|
|
|
485
545
|
}
|
|
486
546
|
continue;
|
|
487
547
|
}
|
|
488
|
-
if (
|
|
489
|
-
if (
|
|
490
|
-
if (
|
|
548
|
+
if (readString4(record.type) !== "response_item") continue;
|
|
549
|
+
if (readString4(payload2.type) !== "function_call") continue;
|
|
550
|
+
if (readString4(payload2.name) !== "exec_command") continue;
|
|
491
551
|
const command = readExecCommand(payload2.arguments);
|
|
492
552
|
if (command === void 0) continue;
|
|
493
553
|
const cwd = command.workdir ?? workingDir ?? ".";
|
|
@@ -598,17 +658,17 @@ function commandExecutedEvent2(occurredAt, sessionId, command, cwd, outcome) {
|
|
|
598
658
|
duration_ms: outcome.durationMs
|
|
599
659
|
};
|
|
600
660
|
}
|
|
601
|
-
function
|
|
661
|
+
function readString4(value) {
|
|
602
662
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
603
663
|
}
|
|
604
664
|
function readNonNegInt2(value) {
|
|
605
665
|
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : 0;
|
|
606
666
|
}
|
|
607
|
-
function
|
|
667
|
+
function isObject4(value) {
|
|
608
668
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
609
669
|
}
|
|
610
670
|
function readExecCommand(value) {
|
|
611
|
-
const raw =
|
|
671
|
+
const raw = readString4(value);
|
|
612
672
|
if (raw === void 0) return void 0;
|
|
613
673
|
let parsed;
|
|
614
674
|
try {
|
|
@@ -616,19 +676,19 @@ function readExecCommand(value) {
|
|
|
616
676
|
} catch {
|
|
617
677
|
return void 0;
|
|
618
678
|
}
|
|
619
|
-
if (!
|
|
620
|
-
const cmd =
|
|
679
|
+
if (!isObject4(parsed)) return void 0;
|
|
680
|
+
const cmd = readString4(parsed.cmd);
|
|
621
681
|
if (cmd === void 0) return void 0;
|
|
622
|
-
return { cmd, workdir:
|
|
682
|
+
return { cmd, workdir: readString4(parsed.workdir) };
|
|
623
683
|
}
|
|
624
684
|
function readCallId(value, outputs) {
|
|
625
|
-
const callId =
|
|
685
|
+
const callId = readString4(value);
|
|
626
686
|
return callId !== void 0 ? outputs.get(callId) : void 0;
|
|
627
687
|
}
|
|
628
688
|
function turnIntervalFromComplete(endTs, payload, startMsByTurnId) {
|
|
629
689
|
const endMs = Date.parse(endTs);
|
|
630
690
|
if (!Number.isFinite(endMs)) return void 0;
|
|
631
|
-
const turnId =
|
|
691
|
+
const turnId = readString4(payload.turn_id);
|
|
632
692
|
const indexedStart = turnId !== void 0 ? startMsByTurnId.get(turnId) : void 0;
|
|
633
693
|
const durationMs = readNonNegInt2(payload.duration_ms);
|
|
634
694
|
const startMs = indexedStart !== void 0 ? indexedStart : durationMs > 0 ? endMs - durationMs : void 0;
|
|
@@ -638,11 +698,11 @@ function turnIntervalFromComplete(endTs, payload, startMsByTurnId) {
|
|
|
638
698
|
function indexTaskStarts(records) {
|
|
639
699
|
const byTurnId = /* @__PURE__ */ new Map();
|
|
640
700
|
for (const record of records) {
|
|
641
|
-
if (
|
|
642
|
-
const payload =
|
|
643
|
-
if (payload === void 0 ||
|
|
644
|
-
const turnId =
|
|
645
|
-
const startMs = Date.parse(
|
|
701
|
+
if (readString4(record.type) !== "event_msg") continue;
|
|
702
|
+
const payload = isObject4(record.payload) ? record.payload : void 0;
|
|
703
|
+
if (payload === void 0 || readString4(payload.type) !== "task_started") continue;
|
|
704
|
+
const turnId = readString4(payload.turn_id);
|
|
705
|
+
const startMs = Date.parse(readString4(record.timestamp) ?? "");
|
|
646
706
|
if (turnId !== void 0 && Number.isFinite(startMs) && !byTurnId.has(turnId)) {
|
|
647
707
|
byTurnId.set(turnId, startMs);
|
|
648
708
|
}
|
|
@@ -664,12 +724,12 @@ function parseWallTimeMs(output) {
|
|
|
664
724
|
function indexOutputs(records) {
|
|
665
725
|
const byId = /* @__PURE__ */ new Map();
|
|
666
726
|
for (const record of records) {
|
|
667
|
-
if (
|
|
668
|
-
const payload =
|
|
727
|
+
if (readString4(record.type) !== "response_item") continue;
|
|
728
|
+
const payload = isObject4(record.payload) ? record.payload : void 0;
|
|
669
729
|
if (payload === void 0) continue;
|
|
670
|
-
if (
|
|
671
|
-
const callId =
|
|
672
|
-
const output =
|
|
730
|
+
if (readString4(payload.type) !== "function_call_output") continue;
|
|
731
|
+
const callId = readString4(payload.call_id);
|
|
732
|
+
const output = readString4(payload.output);
|
|
673
733
|
if (callId !== void 0 && output !== void 0) byId.set(callId, output);
|
|
674
734
|
}
|
|
675
735
|
return byId;
|
|
@@ -5120,12 +5180,11 @@ function stalenessBanner(staleness) {
|
|
|
5120
5180
|
if (staleness === null) return [];
|
|
5121
5181
|
if ((staleness.unverifiableSessions ?? 0) > 0) {
|
|
5122
5182
|
return [
|
|
5123
|
-
`> \u26A0\uFE0F **\
|
|
5183
|
+
`> \u26A0\uFE0F **\u518D\u53D6\u308A\u8FBC\u307F\u304C\u5FC5\u8981** \u2014 native \u30ED\u30B0\u304C\u5909\u5316\u3057\u305F\u304C\u901A\u5E38\u306E refresh \u3067\u306F\u53D6\u308A\u8FBC\u3081\u306A\u3044\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${staleness.unverifiableSessions} \u4EF6\u3042\u308A\u307E\u3059\u3002\`basou refresh --force\` \u3067\u518D\u53D6\u308A\u8FBC\u307F\u3057\u3066\u304F\u3060\u3055\u3044(\u8A73\u7D30\u306F\u672B\u5C3E\u300C\u3053\u308C\u306F\u6700\u65B0\u304B\u300D)\u3002`
|
|
5124
5184
|
];
|
|
5125
5185
|
}
|
|
5126
|
-
if (staleness.newSessions > 0
|
|
5127
|
-
const parts = [];
|
|
5128
|
-
if (staleness.newSessions > 0) parts.push(`\u65B0\u898F ${staleness.newSessions} \u4EF6`);
|
|
5186
|
+
if (staleness.newSessions > 0) {
|
|
5187
|
+
const parts = [`\u65B0\u898F ${staleness.newSessions} \u4EF6`];
|
|
5129
5188
|
if (staleness.updatedSessions > 0) parts.push(`\u66F4\u65B0 ${staleness.updatedSessions} \u4EF6`);
|
|
5130
5189
|
return [
|
|
5131
5190
|
`> \u26A0\uFE0F **\u53E4\u3044\u3067\u3059\uFF08\u672A\u53D6\u308A\u8FBC\u307F ${parts.join("\u30FB")}\uFF09** \u2014 \u7740\u624B\u524D\u306B\u5FC5\u305A \`basou refresh\` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044(\u8A73\u7D30\u306F\u672B\u5C3E\u300C\u3053\u308C\u306F\u6700\u65B0\u304B\u300D)\u3002`
|
|
@@ -5136,19 +5195,30 @@ function stalenessBanner(staleness) {
|
|
|
5136
5195
|
function freshnessVerdict(summary, staleness, now) {
|
|
5137
5196
|
if (staleness !== null && (staleness.unverifiableSessions ?? 0) > 0) {
|
|
5138
5197
|
return [
|
|
5139
|
-
`\u26A0\uFE0F \
|
|
5140
|
-
"`basou
|
|
5198
|
+
`\u26A0\uFE0F native \u30ED\u30B0\u304C\u5909\u5316\u3057\u307E\u3057\u305F\u304C\u3001\u901A\u5E38\u306E \`basou refresh\` \u3067\u306F\u5B89\u5168\u306B\u518D\u53D6\u308A\u8FBC\u307F\u3067\u304D\u306A\u3044\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${staleness.unverifiableSessions} \u4EF6\u3042\u308A\u307E\u3059(\u975E\u8FFD\u8A18\u5909\u66F4\u30FB\u524D\u30C1\u30A7\u30FC\u30F3\u4E0D\u6574\u5408\u306A\u3069)\u3002`,
|
|
5199
|
+
"`basou refresh --force` \u3067\u518D\u53D6\u308A\u8FBC\u307F\u3057\u3066\u304F\u3060\u3055\u3044\u3002(`basou verify` \u306F\u5225\u7269=\u53D6\u308A\u8FBC\u307F\u6E08\u307F\u30C7\u30FC\u30BF\u306E\u6539\u7AC4/\u7834\u640D\u691C\u67FB\u3067\u3001\u30D8\u30C3\u30C0\u306E suspect \u3068\u306F\u5225\u8EF8\u3067\u3059\u3002verify \u304C clean \u3067\u3082\u672A\u53D6\u308A\u8FBC\u307F\u306F\u6B8B\u308A\u5F97\u307E\u3059\u3002)"
|
|
5141
5200
|
];
|
|
5142
5201
|
}
|
|
5143
|
-
if (staleness !== null &&
|
|
5144
|
-
const parts = [];
|
|
5145
|
-
if (staleness.newSessions > 0) parts.push(`\u65B0\u898F ${staleness.newSessions} \u4EF6`);
|
|
5202
|
+
if (staleness !== null && staleness.newSessions > 0) {
|
|
5203
|
+
const parts = [`\u65B0\u898F ${staleness.newSessions} \u4EF6`];
|
|
5146
5204
|
if (staleness.updatedSessions > 0) parts.push(`\u66F4\u65B0 ${staleness.updatedSessions} \u4EF6`);
|
|
5147
5205
|
return [
|
|
5148
5206
|
`\u26A0\uFE0F \u53E4\u3044\u3067\u3059\u3002\u6700\u5F8C\u306E\u53D6\u308A\u8FBC\u307F\u4EE5\u964D\u306B\u672A\u53D6\u308A\u8FBC\u307F\u306E\u4F5C\u696D\u304C\u3042\u308A\u307E\u3059(${parts.join("\u30FB")})\u3002`,
|
|
5149
5207
|
"\u7740\u624B\u524D\u306B\u5FC5\u305A `basou refresh` \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
5150
5208
|
];
|
|
5151
5209
|
}
|
|
5210
|
+
if (staleness !== null && staleness.updatedSessions > 0) {
|
|
5211
|
+
const lines2 = [
|
|
5212
|
+
`\u26A0\uFE0F \u66F4\u65B0\u3055\u308C\u305F\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${staleness.updatedSessions} \u4EF6\u3042\u308A\u307E\u3059\u3002\`basou refresh\` \u3067\u53D6\u308A\u8FBC\u3081\u307E\u3059\u3002`,
|
|
5213
|
+
"(\u9032\u884C\u4E2D\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u3042\u308B\u5834\u5408\u3001\u305D\u308C\u81EA\u8EAB\u306F\u53D6\u308A\u8FBC\u307F\u5F8C\u3082\u5897\u3048\u7D9A\u3051\u308B\u305F\u3081\u6B8B\u308A\u307E\u3059\uFF1D\u6B63\u5E38\u3067\u3059\u3002)"
|
|
5214
|
+
];
|
|
5215
|
+
if (summary.suspects.length > 0) {
|
|
5216
|
+
lines2.push(
|
|
5217
|
+
`\u307E\u305F\u8981\u6CE8\u610F\u30BB\u30C3\u30B7\u30E7\u30F3\u304C ${summary.suspects.length} \u4EF6\u3042\u308A\u307E\u3059(\u4E0A\u8A18\u300C\u8981\u6CE8\u610F session\u300D\u53C2\u7167)\u3002`
|
|
5218
|
+
);
|
|
5219
|
+
}
|
|
5220
|
+
return lines2;
|
|
5221
|
+
}
|
|
5152
5222
|
if (summary.freshness.newestStartedAt === null) {
|
|
5153
5223
|
return [
|
|
5154
5224
|
"\u2139\uFE0F \u307E\u3060\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
@@ -7529,7 +7599,7 @@ export {
|
|
|
7529
7599
|
CLAUDE_IMPORT_SOURCE,
|
|
7530
7600
|
CODEX_IMPORT_SOURCE,
|
|
7531
7601
|
ChildProcessRunner,
|
|
7532
|
-
|
|
7602
|
+
DEFAULT_STOP_HOOK_MIN_EDITS,
|
|
7533
7603
|
DecisionIdSchema,
|
|
7534
7604
|
EventIdSchema,
|
|
7535
7605
|
EventSchema,
|