@plumpslabs/kuma 2.3.0 → 2.3.2
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 +3 -1
- package/dist/{agentDetector-FDRVUNJY.js → agentDetector-G4RBMZ6X.js} +1 -1
- package/dist/chunk-5N6KXACT.js +880 -0
- package/dist/{chunk-IXMWW5WA.js → chunk-E2KFPEBT.js} +80 -1
- package/dist/{chunk-OUPFJQKW.js → chunk-EIK7T746.js} +43 -2
- package/dist/{chunk-IMO4QAFJ.js → chunk-EQ2CE4UC.js} +120 -5
- package/dist/{chunk-WP3WRPDC.js → chunk-JIL533AM.js} +2 -2
- package/dist/{chunk-5A6AKUJZ.js → chunk-L5WU2HTN.js} +3 -1
- package/dist/{chunk-TT37TE4P.js → chunk-SU7BTOND.js} +37 -2
- package/dist/index.js +393 -107
- package/dist/{init-O4MBXFZL.js → init-AJAESUZZ.js} +2 -2
- package/dist/kumaDb-RC2EO3OB.js +63 -0
- package/dist/{kumaGraph-GW5SWOHQ.js → kumaGraph-5IZ4FDZA.js} +3 -3
- package/dist/{kumaMemory-IO7TVE7W.js → kumaMemory-ME4XWD5Z.js} +3 -3
- package/dist/kumaMiner-GFEGUWGH.js +142 -0
- package/dist/kumaVerifier-VYW5WH6V.js +108 -0
- package/dist/pathValidator-V4DC6U6Z.js +22 -0
- package/dist/{safetyScore-7FU7XSY5.js → safetyScore-QX2LBJ7H.js} +31 -7
- package/dist/{sessionMemory-52ECPXZ6.js → sessionMemory-LI4FIAMF.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-6NEMSUKP.js +0 -304
- package/dist/kumaDb-KN7Z4B5V.js +0 -19
package/dist/index.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ALL_CONFIG_TYPES,
|
|
4
|
+
formatInitResults,
|
|
5
|
+
runInit
|
|
6
|
+
} from "./chunk-L5WU2HTN.js";
|
|
2
7
|
import {
|
|
3
8
|
analyzeImpact,
|
|
4
9
|
autoHeal,
|
|
@@ -9,39 +14,52 @@ import {
|
|
|
9
14
|
getGraphStats,
|
|
10
15
|
searchGraph,
|
|
11
16
|
traceFlow
|
|
12
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-EQ2CE4UC.js";
|
|
13
18
|
import {
|
|
19
|
+
buildDriftMessages,
|
|
20
|
+
getGitDiffStat,
|
|
21
|
+
getSessionStats,
|
|
22
|
+
getUnresolvedCount
|
|
23
|
+
} from "./chunk-JIL533AM.js";
|
|
24
|
+
import {
|
|
25
|
+
addContextNote,
|
|
26
|
+
addSecurityFinding,
|
|
27
|
+
addTodo,
|
|
28
|
+
checkPortability,
|
|
29
|
+
ensureGitignore,
|
|
30
|
+
getBenchmarkDiff,
|
|
14
31
|
getChanges,
|
|
15
32
|
getDb,
|
|
16
33
|
getResearchCache,
|
|
34
|
+
getSecurityFindings,
|
|
35
|
+
listContextNotes,
|
|
36
|
+
listDecisionLog,
|
|
37
|
+
listResearchCache,
|
|
38
|
+
listTodos,
|
|
39
|
+
recordDecisionLog,
|
|
40
|
+
rollbackChange,
|
|
41
|
+
runDoctor,
|
|
42
|
+
runGarbageCollection,
|
|
43
|
+
saveBenchmark,
|
|
17
44
|
saveDb,
|
|
18
45
|
saveHealthSnapshot,
|
|
19
|
-
saveResearchCache
|
|
20
|
-
|
|
46
|
+
saveResearchCache,
|
|
47
|
+
updateDecisionStatus,
|
|
48
|
+
updateTodoStatus
|
|
49
|
+
} from "./chunk-5N6KXACT.js";
|
|
21
50
|
import {
|
|
22
51
|
formatDecisionTemplate,
|
|
23
52
|
getProactiveMemories,
|
|
24
53
|
recordDecision,
|
|
25
54
|
scoreMemoryRelevance
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import {
|
|
28
|
-
buildDriftMessages,
|
|
29
|
-
getGitDiffStat,
|
|
30
|
-
getSessionStats,
|
|
31
|
-
getUnresolvedCount
|
|
32
|
-
} from "./chunk-WP3WRPDC.js";
|
|
55
|
+
} from "./chunk-EIK7T746.js";
|
|
33
56
|
import {
|
|
34
57
|
sessionMemory
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import {
|
|
37
|
-
ALL_CONFIG_TYPES,
|
|
38
|
-
formatInitResults,
|
|
39
|
-
runInit
|
|
40
|
-
} from "./chunk-5A6AKUJZ.js";
|
|
58
|
+
} from "./chunk-SU7BTOND.js";
|
|
41
59
|
import {
|
|
42
60
|
getProjectRoot,
|
|
43
61
|
validateFilePath
|
|
44
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-E2KFPEBT.js";
|
|
45
63
|
|
|
46
64
|
// src/index.ts
|
|
47
65
|
import { readFileSync } from "fs";
|
|
@@ -69,10 +87,14 @@ async function handleContext(params) {
|
|
|
69
87
|
return handleNavigate(params);
|
|
70
88
|
case "changes":
|
|
71
89
|
return handleChanges(params);
|
|
90
|
+
case "rollback":
|
|
91
|
+
return handleRollback(params);
|
|
92
|
+
case "researches":
|
|
93
|
+
return handleResearches(params);
|
|
72
94
|
case "health":
|
|
73
95
|
return handleHealth(params);
|
|
74
96
|
default:
|
|
75
|
-
return `Unknown action "${action}". Use: init, research, impact, navigate, changes, health`;
|
|
97
|
+
return `Unknown action "${action}". Use: init, research, impact, navigate, changes, rollback, researches, health`;
|
|
76
98
|
}
|
|
77
99
|
}
|
|
78
100
|
async function handleInit(_params) {
|
|
@@ -132,6 +154,17 @@ async function handleInit(_params) {
|
|
|
132
154
|
lines.push(` \u{1F3AF} Goal: ${summary.currentGoal || "not set"}`);
|
|
133
155
|
lines.push(` \u{1F4DD} Modified: ${summary.modifiedFiles?.length || 0} file(s)`);
|
|
134
156
|
lines.push(` \u{1F6E0}\uFE0F Tool calls: ${summary.toolCallCount}`);
|
|
157
|
+
try {
|
|
158
|
+
const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-QX2LBJ7H.js");
|
|
159
|
+
const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-RC2EO3OB.js");
|
|
160
|
+
const score = await computeSafetyScore(_params.goal);
|
|
161
|
+
const checksStr = JSON.stringify(score.checks);
|
|
162
|
+
await saveHealthSnapshot2(score.score, score.risk, checksStr, score.summary);
|
|
163
|
+
lines.push("");
|
|
164
|
+
lines.push("**Health Score**");
|
|
165
|
+
lines.push(formatSafetyScore(score));
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
135
168
|
lines.push("", "\u{1F4A1} Call kuma_context({ action: 'research', scope: '<area>' }) to research a specific area.");
|
|
136
169
|
return lines.join("\n");
|
|
137
170
|
}
|
|
@@ -154,8 +187,15 @@ async function handleResearch(params) {
|
|
|
154
187
|
}
|
|
155
188
|
}
|
|
156
189
|
if (record) {
|
|
157
|
-
const
|
|
158
|
-
|
|
190
|
+
const ageSeconds = Math.floor((Date.now() - (record.validatedAt ? new Date(record.validatedAt).getTime() : 0)) / 1e3);
|
|
191
|
+
const ageStr = ageSeconds > 86400 ? `${Math.floor(ageSeconds / 86400)}d` : ageSeconds > 3600 ? `${Math.floor(ageSeconds / 3600)}h` : `${Math.floor(ageSeconds / 60)}m`;
|
|
192
|
+
lines.push(` \u2705 Found cached research (${ageStr} old)`);
|
|
193
|
+
if (ageSeconds > 86400) {
|
|
194
|
+
lines.push(` ${ageSeconds > 604800 ? "\u{1F534}" : "\u{1F7E1}"} **Staleness:** Cache is ${ageStr} old \u2014 may be stale`);
|
|
195
|
+
if (ageSeconds > 604800) {
|
|
196
|
+
lines.push(" \u{1F4A1} Consider re-researching: cache is over a week old");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
159
199
|
} else {
|
|
160
200
|
lines.push(" \u23F3 No cached research \u2014 starting fresh");
|
|
161
201
|
}
|
|
@@ -182,13 +222,30 @@ async function handleResearch(params) {
|
|
|
182
222
|
try {
|
|
183
223
|
const graphResult = await searchGraph(scope, 15);
|
|
184
224
|
const graphLines = graphResult.split("\n");
|
|
185
|
-
if (graphLines.length > 1) {
|
|
225
|
+
if (graphLines.length > 1 && !graphResult.includes("No results")) {
|
|
186
226
|
lines.push(` \u{1F4CA} ${graphLines.filter((l) => l.includes("\u2022")).length} relevant node(s) found`);
|
|
187
227
|
for (const l of graphLines.slice(0, 8)) {
|
|
188
228
|
if (l.includes("\u2022")) lines.push(` ${l}`);
|
|
189
229
|
}
|
|
190
230
|
} else {
|
|
191
|
-
lines.push(" \u23F3 No graph data
|
|
231
|
+
lines.push(" \u23F3 No graph data \u2014 searching codebase...");
|
|
232
|
+
try {
|
|
233
|
+
const fg = (await import("fast-glob")).default;
|
|
234
|
+
const root = getProjectRoot();
|
|
235
|
+
const ignorePatterns = ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**", "**/.kuma/**"];
|
|
236
|
+
const files = await fg([`**/*${scope}*`], { cwd: root, ignore: ignorePatterns, onlyFiles: true, deep: 6 });
|
|
237
|
+
if (files.length > 0) {
|
|
238
|
+
lines.push(` \u{1F4C1} Found ${files.length} file(s) in codebase matching "${scope}":`);
|
|
239
|
+
for (const f of files.slice(0, 8)) {
|
|
240
|
+
lines.push(` \u{1F4C4} ${f}`);
|
|
241
|
+
}
|
|
242
|
+
if (files.length > 8) lines.push(` ... and ${files.length - 8} more`);
|
|
243
|
+
} else {
|
|
244
|
+
lines.push(" \u23F3 No codebase matches \u2014 build graph by using more tools");
|
|
245
|
+
}
|
|
246
|
+
} catch {
|
|
247
|
+
lines.push(" \u23F3 No graph data yet \u2014 build by using more tools");
|
|
248
|
+
}
|
|
192
249
|
}
|
|
193
250
|
} catch {
|
|
194
251
|
lines.push(" \u26A0\uFE0F Graph query failed");
|
|
@@ -257,11 +314,23 @@ async function handleChanges(params) {
|
|
|
257
314
|
const since = params.since;
|
|
258
315
|
return await getChanges({ filePath, since });
|
|
259
316
|
}
|
|
317
|
+
async function handleRollback(params) {
|
|
318
|
+
const target = params.target;
|
|
319
|
+
if (!target) return "\u26A0\uFE0F target parameter required (change ID, e.g. '5').";
|
|
320
|
+
const changeId = parseInt(target, 10);
|
|
321
|
+
if (isNaN(changeId)) return `\u26A0\uFE0F Invalid change ID: "${target}". Use a numeric ID from kuma_context({ action: 'changes' }).`;
|
|
322
|
+
sessionMemory.recordToolCall("kuma_context_rollback", { changeId });
|
|
323
|
+
return await rollbackChange(changeId);
|
|
324
|
+
}
|
|
325
|
+
async function handleResearches(_params) {
|
|
326
|
+
sessionMemory.recordToolCall("kuma_context_researches", {});
|
|
327
|
+
return await listResearchCache();
|
|
328
|
+
}
|
|
260
329
|
async function handleHealth(_params) {
|
|
261
330
|
sessionMemory.recordToolCall("kuma_context_health", {});
|
|
262
331
|
try {
|
|
263
|
-
const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-
|
|
264
|
-
const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-
|
|
332
|
+
const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-QX2LBJ7H.js");
|
|
333
|
+
const { saveHealthSnapshot: saveHealthSnapshot2 } = await import("./kumaDb-RC2EO3OB.js");
|
|
265
334
|
const score = await computeSafetyScore();
|
|
266
335
|
const checksStr = JSON.stringify(score.checks);
|
|
267
336
|
await saveHealthSnapshot2(score.score, score.risk, checksStr, score.summary);
|
|
@@ -298,6 +367,8 @@ async function handleMemory(params) {
|
|
|
298
367
|
switch (action) {
|
|
299
368
|
case "decision":
|
|
300
369
|
return handleDecision(params);
|
|
370
|
+
case "mine":
|
|
371
|
+
return handleMine(params);
|
|
301
372
|
case "research_save":
|
|
302
373
|
return handleResearchSave(params);
|
|
303
374
|
case "session":
|
|
@@ -308,8 +379,16 @@ async function handleMemory(params) {
|
|
|
308
379
|
return handleSearch(params);
|
|
309
380
|
case "changes":
|
|
310
381
|
return handleChanges2(params);
|
|
382
|
+
case "todo":
|
|
383
|
+
return handleTodo(params);
|
|
384
|
+
case "context":
|
|
385
|
+
return handleContext2(params);
|
|
386
|
+
case "benchmark":
|
|
387
|
+
return handleBenchmark(params);
|
|
388
|
+
case "decision_log":
|
|
389
|
+
return handleDecisionLog(params);
|
|
311
390
|
default:
|
|
312
|
-
return `Unknown action "${action}"
|
|
391
|
+
return `Unknown action "${action}".`;
|
|
313
392
|
}
|
|
314
393
|
}
|
|
315
394
|
async function handleDecision(params) {
|
|
@@ -318,15 +397,13 @@ async function handleDecision(params) {
|
|
|
318
397
|
case "template":
|
|
319
398
|
return formatDecisionTemplate();
|
|
320
399
|
case "suggest": {
|
|
321
|
-
const { shouldRecordDecision } = await import("./kumaMemory-
|
|
400
|
+
const { shouldRecordDecision } = await import("./kumaMemory-ME4XWD5Z.js");
|
|
322
401
|
const check = shouldRecordDecision();
|
|
323
402
|
return check.worth ? `\u{1F4A1} Decision suggested: "${check.title}"
|
|
324
403
|
Use kuma_memory({ action: 'decision', title: '...', context: '...', rationale: '...', outcome: '...' }) to record.` : "\u2705 No decision needed at this time.";
|
|
325
404
|
}
|
|
326
405
|
case "record":
|
|
327
|
-
if (!params.title || !params.rationale)
|
|
328
|
-
return "\u26A0\uFE0F title and rationale are required. Optionally: context, outcome.";
|
|
329
|
-
}
|
|
406
|
+
if (!params.title || !params.rationale) return "\u26A0\uFE0F title and rationale are required.";
|
|
330
407
|
return recordDecision({
|
|
331
408
|
title: params.title,
|
|
332
409
|
context: params.context || "",
|
|
@@ -350,68 +427,44 @@ async function handleResearchSave(params) {
|
|
|
350
427
|
await saveResearchCache(scope, record, void 0, params.confidence);
|
|
351
428
|
try {
|
|
352
429
|
const researchDir = path2.join(getProjectRoot(), ".kuma", "research");
|
|
353
|
-
if (!fs2.existsSync(researchDir)) {
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
fs2.writeFileSync(
|
|
357
|
-
path2.join(researchDir, `${scope}.json`),
|
|
358
|
-
JSON.stringify(JSON.parse(record), null, 2),
|
|
359
|
-
"utf-8"
|
|
360
|
-
);
|
|
430
|
+
if (!fs2.existsSync(researchDir)) fs2.mkdirSync(researchDir, { recursive: true });
|
|
431
|
+
fs2.writeFileSync(path2.join(researchDir, `${scope}.json`), JSON.stringify(JSON.parse(record), null, 2), "utf-8");
|
|
361
432
|
} catch {
|
|
362
433
|
}
|
|
363
|
-
return `\u2705 Research "${scope}" saved
|
|
434
|
+
return `\u2705 Research "${scope}" saved.`;
|
|
364
435
|
}
|
|
365
436
|
async function handleSession(params) {
|
|
366
437
|
const topic = params.topic;
|
|
367
438
|
const summary = sessionMemory.getSummary(topic);
|
|
368
|
-
if (topic)
|
|
369
|
-
return typeof summary.content === "string" ? summary.content : JSON.stringify(summary, null, 2);
|
|
370
|
-
}
|
|
439
|
+
if (topic) return typeof summary.content === "string" ? summary.content : JSON.stringify(summary, null, 2);
|
|
371
440
|
const modifiedFiles = summary.modifiedFiles || [];
|
|
372
441
|
const failures = summary.unresolvedFailures || [];
|
|
373
442
|
const lines = [
|
|
374
|
-
"\u{1F4CB} **Session Summary
|
|
375
|
-
`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
376
|
-
"",
|
|
443
|
+
"\u{1F4CB} **Session Summary**\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n",
|
|
377
444
|
`\u{1F3AF} Goal: ${summary.currentGoal || "not set"}`,
|
|
378
445
|
`\u{1F550} Duration: ${summary.sessionDuration}`,
|
|
379
|
-
`\u{1F6E0}\uFE0F Tool calls: ${summary.toolCallCount}
|
|
380
|
-
|
|
446
|
+
`\u{1F6E0}\uFE0F Tool calls: ${summary.toolCallCount}
|
|
447
|
+
`
|
|
381
448
|
];
|
|
382
449
|
if (modifiedFiles.length > 0) {
|
|
383
450
|
lines.push(`**Modified Files** (${modifiedFiles.length}):`);
|
|
384
451
|
for (const f of modifiedFiles.slice(0, 10)) {
|
|
385
|
-
|
|
386
|
-
lines.push(` ${icon} ${f.filePath}`);
|
|
387
|
-
}
|
|
388
|
-
if (modifiedFiles.length > 10) {
|
|
389
|
-
lines.push(` ... and ${modifiedFiles.length - 10} more`);
|
|
452
|
+
lines.push(` ${f.status === "created" ? "\u2728" : f.status === "modified" ? "\u{1F4DD}" : "\u274C"} ${f.filePath}`);
|
|
390
453
|
}
|
|
454
|
+
if (modifiedFiles.length > 10) lines.push(` ... and ${modifiedFiles.length - 10} more`);
|
|
391
455
|
lines.push("");
|
|
392
456
|
}
|
|
393
457
|
if (failures.length > 0) {
|
|
394
458
|
lines.push(`**Unresolved Issues** (${failures.length}):`);
|
|
395
|
-
for (const f of failures.slice(0, 5)) {
|
|
396
|
-
lines.push(` \u274C ${f.task}: ${f.error.substring(0, 80)}`);
|
|
397
|
-
}
|
|
398
|
-
lines.push("");
|
|
399
|
-
}
|
|
400
|
-
const completed = summary.completedSteps || [];
|
|
401
|
-
if (completed.length > 0) {
|
|
402
|
-
lines.push(`**Completed Steps**:`);
|
|
403
|
-
for (const s of completed) {
|
|
404
|
-
lines.push(` \u2705 ${s}`);
|
|
405
|
-
}
|
|
459
|
+
for (const f of failures.slice(0, 5)) lines.push(` \u274C ${f.task}: ${f.error.substring(0, 80)}`);
|
|
406
460
|
lines.push("");
|
|
407
461
|
}
|
|
408
|
-
lines.push("\u{1F4A1} Use kuma_memory({ action: 'decision', decisionAction: 'record', ... }) to document decisions.");
|
|
409
462
|
return lines.join("\n");
|
|
410
463
|
}
|
|
411
464
|
async function handleHeal(params) {
|
|
412
465
|
if (params.healAction === "check") {
|
|
413
466
|
const stale = await detectStaleNodes();
|
|
414
|
-
if (stale.length === 0) return "\u2705 No stale entries found
|
|
467
|
+
if (stale.length === 0) return "\u2705 No stale entries found.";
|
|
415
468
|
return `\u{1F50D} ${stale.length} stale entr${stale.length > 1 ? "ies" : "y"} found. Use kuma_memory({ action: 'heal' }) to repair.`;
|
|
416
469
|
}
|
|
417
470
|
const result = await autoHeal();
|
|
@@ -422,31 +475,88 @@ async function handleSearch(params) {
|
|
|
422
475
|
if (!query) return "\u26A0\uFE0F query or scope parameter required.";
|
|
423
476
|
const limit = params.limit || 20;
|
|
424
477
|
const memResults = sessionMemory.searchMemory(query, limit);
|
|
425
|
-
const { searchGraph: searchGraph2 } = await import("./kumaGraph-
|
|
478
|
+
const { searchGraph: searchGraph2 } = await import("./kumaGraph-5IZ4FDZA.js");
|
|
426
479
|
const graphResults = await searchGraph2(query, Math.min(limit, 10));
|
|
427
|
-
const lines = [
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
""
|
|
431
|
-
];
|
|
480
|
+
const lines = [`\u{1F50D} **Search Results** \u2014 "${query}"
|
|
481
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
482
|
+
`];
|
|
432
483
|
if (memResults.length > 0) {
|
|
433
484
|
lines.push(`**Session Memory** (${memResults.length}):`);
|
|
434
|
-
for (const r of memResults.slice(0, 5)) {
|
|
435
|
-
lines.push(` \u2022 ${r.content.substring(0, 120)}`);
|
|
436
|
-
}
|
|
485
|
+
for (const r of memResults.slice(0, 5)) lines.push(` \u2022 ${r.content.substring(0, 120)}`);
|
|
437
486
|
lines.push("");
|
|
438
487
|
}
|
|
439
|
-
lines.push("**Knowledge Graph
|
|
440
|
-
lines.push(graphResults);
|
|
441
|
-
if (memResults.length === 0 && graphResults.includes("No results")) {
|
|
442
|
-
lines.push("", "\u{1F4A1} No results found. Try a different query or research the topic first.");
|
|
443
|
-
}
|
|
488
|
+
lines.push("**Knowledge Graph:**\n" + graphResults);
|
|
444
489
|
return lines.join("\n");
|
|
445
490
|
}
|
|
446
491
|
async function handleChanges2(params) {
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
492
|
+
const sinceNum = typeof params.since === "number" ? params.since : typeof params.since === "string" ? parseInt(params.since, 10) || void 0 : void 0;
|
|
493
|
+
return await getChanges({ filePath: params.target, since: sinceNum });
|
|
494
|
+
}
|
|
495
|
+
async function handleTodo(params) {
|
|
496
|
+
if (params.todoId && params.status) {
|
|
497
|
+
return await updateTodoStatus(params.todoId, params.status);
|
|
498
|
+
}
|
|
499
|
+
if (params.title) {
|
|
500
|
+
return await addTodo({
|
|
501
|
+
title: params.title,
|
|
502
|
+
description: params.description,
|
|
503
|
+
scope: params.scope,
|
|
504
|
+
deps: params.deps,
|
|
505
|
+
successCriteria: params.success_criteria
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
return await listTodos(params.scope, params.status);
|
|
509
|
+
}
|
|
510
|
+
async function handleContext2(params) {
|
|
511
|
+
if (params.content && params.source) {
|
|
512
|
+
return await addContextNote({
|
|
513
|
+
source: params.source,
|
|
514
|
+
content: params.content,
|
|
515
|
+
scope: params.scope,
|
|
516
|
+
filePaths: params.target ? JSON.stringify([params.target]) : void 0
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
return await listContextNotes(params.scope);
|
|
520
|
+
}
|
|
521
|
+
async function handleBenchmark(params) {
|
|
522
|
+
if (params.label) {
|
|
523
|
+
if (params.metrics) {
|
|
524
|
+
try {
|
|
525
|
+
const metrics = JSON.parse(params.metrics);
|
|
526
|
+
return await saveBenchmark(params.label, metrics);
|
|
527
|
+
} catch {
|
|
528
|
+
return `\u26A0\uFE0F Invalid metrics JSON: "${params.metrics.substring(0, 100)}"`;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return await getBenchmarkDiff(params.label, params.labelB);
|
|
532
|
+
}
|
|
533
|
+
return `\u26A0\uFE0F label required. Use: kuma_memory({ action: 'benchmark', label: 'phase-3', metrics: '{"tsc_errors": 245}' })`;
|
|
534
|
+
}
|
|
535
|
+
async function handleDecisionLog(params) {
|
|
536
|
+
if (params.target && params.status) {
|
|
537
|
+
const id = parseInt(params.target, 10);
|
|
538
|
+
if (!isNaN(id)) return await updateDecisionStatus(id, params.status);
|
|
539
|
+
}
|
|
540
|
+
if (params.title && params.rationale) {
|
|
541
|
+
return await recordDecisionLog({
|
|
542
|
+
title: params.title,
|
|
543
|
+
context: params.context,
|
|
544
|
+
rationale: params.rationale,
|
|
545
|
+
outcome: params.outcome,
|
|
546
|
+
status: params.status
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
return await listDecisionLog(params.status);
|
|
550
|
+
}
|
|
551
|
+
async function handleMine(params) {
|
|
552
|
+
sessionMemory.recordToolCall("kuma_memory_mine", { scope: params.scope });
|
|
553
|
+
const { mineHistoricalDecisions } = await import("./kumaMiner-GFEGUWGH.js");
|
|
554
|
+
return await mineHistoricalDecisions({
|
|
555
|
+
scope: params.scope,
|
|
556
|
+
since: typeof params.since === "string" ? params.since : void 0,
|
|
557
|
+
confirm: params.confirm,
|
|
558
|
+
limit: params.limit
|
|
559
|
+
});
|
|
450
560
|
}
|
|
451
561
|
|
|
452
562
|
// src/engine/kumaLock.ts
|
|
@@ -1011,6 +1121,58 @@ async function safetyCheck(action, filePath, command) {
|
|
|
1011
1121
|
} catch {
|
|
1012
1122
|
checks.push({ name: "Knowledge Graph Health", passed: true, detail: "\u26A0\uFE0F Could not check" });
|
|
1013
1123
|
}
|
|
1124
|
+
if (filePath) {
|
|
1125
|
+
try {
|
|
1126
|
+
const fs7 = await import("fs");
|
|
1127
|
+
const path7 = await import("path");
|
|
1128
|
+
const root = process.cwd();
|
|
1129
|
+
const fullPath = path7.resolve(root, filePath);
|
|
1130
|
+
if (fs7.existsSync(fullPath)) {
|
|
1131
|
+
const stat = fs7.statSync(fullPath);
|
|
1132
|
+
const sizeKB = Math.round(stat.size / 1024);
|
|
1133
|
+
if (sizeKB > 500) {
|
|
1134
|
+
checks.push({
|
|
1135
|
+
name: "File Size Warning",
|
|
1136
|
+
passed: false,
|
|
1137
|
+
detail: `\u{1F4CF} File is ${sizeKB}KB \u2014 large file edits are risky`
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
if (filePath.endsWith(".ts") || filePath.endsWith(".js")) {
|
|
1141
|
+
const baseName = path7.basename(filePath, path7.extname(filePath));
|
|
1142
|
+
const testPatterns = [
|
|
1143
|
+
filePath.replace(/\.(ts|js)$/, ".test.$1"),
|
|
1144
|
+
filePath.replace(/\.(ts|js)$/, ".spec.$1"),
|
|
1145
|
+
filePath.replace(/^src\//, "tests/").replace(/\.(ts|js)$/, ".test.$1"),
|
|
1146
|
+
`**/__tests__/**/${baseName}.test.${path7.extname(filePath).slice(1)}`
|
|
1147
|
+
];
|
|
1148
|
+
let hasTests = false;
|
|
1149
|
+
const fg = await import("fast-glob");
|
|
1150
|
+
for (const pattern of testPatterns) {
|
|
1151
|
+
const matches = await fg.default(pattern, { cwd: root, ignore: ["**/node_modules/**"] });
|
|
1152
|
+
if (matches.length > 0) {
|
|
1153
|
+
hasTests = true;
|
|
1154
|
+
break;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
if (!hasTests) {
|
|
1158
|
+
checks.push({
|
|
1159
|
+
name: "Tests Check",
|
|
1160
|
+
passed: true,
|
|
1161
|
+
// Not a blocker, just informative
|
|
1162
|
+
detail: `\u{1F9EA} No test file found for "${path7.basename(filePath)}" \u2014 consider adding tests`
|
|
1163
|
+
});
|
|
1164
|
+
} else {
|
|
1165
|
+
checks.push({
|
|
1166
|
+
name: "Tests Check",
|
|
1167
|
+
passed: true,
|
|
1168
|
+
detail: "\u2705 Test file found"
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
} catch {
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1014
1176
|
const failed = checks.filter((c) => !c.passed);
|
|
1015
1177
|
const riskLevel = failed.length >= 3 ? "critical" : failed.length >= 2 ? "high" : failed.length >= 1 ? "medium" : "low";
|
|
1016
1178
|
const allowed = failed.length === 0;
|
|
@@ -1458,6 +1620,8 @@ async function handleSafety(params) {
|
|
|
1458
1620
|
switch (action) {
|
|
1459
1621
|
case "guard":
|
|
1460
1622
|
return handleGuard(params);
|
|
1623
|
+
case "verify":
|
|
1624
|
+
return handleVerify(params);
|
|
1461
1625
|
case "check":
|
|
1462
1626
|
return handleCheck(params);
|
|
1463
1627
|
case "audit":
|
|
@@ -1468,8 +1632,18 @@ async function handleSafety(params) {
|
|
|
1468
1632
|
return handleHealth2(params);
|
|
1469
1633
|
case "override":
|
|
1470
1634
|
return handleOverride(params);
|
|
1635
|
+
case "security":
|
|
1636
|
+
return handleSecurity(params);
|
|
1637
|
+
case "gc":
|
|
1638
|
+
return handleGc(params);
|
|
1639
|
+
case "doctor":
|
|
1640
|
+
return handleDoctor(params);
|
|
1641
|
+
case "portability":
|
|
1642
|
+
return handlePortability(params);
|
|
1643
|
+
case "gitignore":
|
|
1644
|
+
return handleGitignore(params);
|
|
1471
1645
|
default:
|
|
1472
|
-
return `Unknown action "${action}"
|
|
1646
|
+
return `Unknown action "${action}".`;
|
|
1473
1647
|
}
|
|
1474
1648
|
}
|
|
1475
1649
|
async function handleGuard(params) {
|
|
@@ -1479,15 +1653,10 @@ async function handleGuard(params) {
|
|
|
1479
1653
|
});
|
|
1480
1654
|
}
|
|
1481
1655
|
async function handleCheck(params) {
|
|
1482
|
-
|
|
1483
|
-
const filePath = params.filePath;
|
|
1484
|
-
const command = params.command;
|
|
1485
|
-
return await safetyCheck(action, filePath, command);
|
|
1656
|
+
return await safetyCheck("check", params.filePath, params.command);
|
|
1486
1657
|
}
|
|
1487
1658
|
async function handleAudit(params) {
|
|
1488
|
-
if (params.limit === 0)
|
|
1489
|
-
return await auditStats();
|
|
1490
|
-
}
|
|
1659
|
+
if (params.limit === 0) return await auditStats();
|
|
1491
1660
|
return await queryAudit({
|
|
1492
1661
|
toolName: params.toolName,
|
|
1493
1662
|
riskLevel: params.riskLevel,
|
|
@@ -1516,18 +1685,86 @@ async function handleLock(params) {
|
|
|
1516
1685
|
}
|
|
1517
1686
|
async function handleHealth2(_params) {
|
|
1518
1687
|
try {
|
|
1519
|
-
const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-
|
|
1688
|
+
const { computeSafetyScore, formatSafetyScore } = await import("./safetyScore-QX2LBJ7H.js");
|
|
1520
1689
|
const score = await computeSafetyScore();
|
|
1521
|
-
|
|
1522
|
-
await saveHealthSnapshot(score.score, score.risk, checksStr, score.summary);
|
|
1690
|
+
await saveHealthSnapshot(score.score, score.risk, JSON.stringify(score.checks), score.summary);
|
|
1523
1691
|
return formatSafetyScore(score);
|
|
1524
1692
|
} catch (err) {
|
|
1525
1693
|
return `Error computing health: ${err}`;
|
|
1526
1694
|
}
|
|
1527
1695
|
}
|
|
1528
1696
|
function handleOverride(params) {
|
|
1529
|
-
|
|
1530
|
-
|
|
1697
|
+
return safetyOverride(params.toolName || "unknown", params.reason);
|
|
1698
|
+
}
|
|
1699
|
+
async function handleSecurity(params) {
|
|
1700
|
+
sessionMemory.recordToolCall("kuma_safety_security", {});
|
|
1701
|
+
if (params.filePath) {
|
|
1702
|
+
try {
|
|
1703
|
+
const fs7 = await import("fs");
|
|
1704
|
+
const path7 = await import("path");
|
|
1705
|
+
const root = process.cwd();
|
|
1706
|
+
const fullPath = path7.resolve(root, params.filePath);
|
|
1707
|
+
if (fs7.existsSync(fullPath) && fs7.statSync(fullPath).isFile()) {
|
|
1708
|
+
const content = fs7.readFileSync(fullPath, "utf-8");
|
|
1709
|
+
const lines = content.split("\n");
|
|
1710
|
+
const findings = [];
|
|
1711
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1712
|
+
const line = lines[i];
|
|
1713
|
+
const lc = line.toLowerCase();
|
|
1714
|
+
if (lc.includes("credentials: true")) {
|
|
1715
|
+
findings.push({ line: i + 1, pattern: "credentials-leak", severity: "high", message: "`credentials: true` in Prisma select may leak sensitive fields" });
|
|
1716
|
+
}
|
|
1717
|
+
if (lc.includes("console.log") && (lc.includes("token") || lc.includes("secret") || lc.includes("key") || lc.includes("password"))) {
|
|
1718
|
+
findings.push({ line: i + 1, pattern: "console-log-secret", severity: "high", message: "Potential secret logged to console" });
|
|
1719
|
+
}
|
|
1720
|
+
if (lc.includes("process.env") && (lc.includes("api_key") || lc.includes("secret") || lc.includes("token"))) {
|
|
1721
|
+
findings.push({ line: i + 1, pattern: "env-in-code", severity: "medium", message: "process.env.KEY referenced in code \u2014 ensure not in client bundle" });
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
for (const f of findings) {
|
|
1725
|
+
await addSecurityFinding({
|
|
1726
|
+
filePath: params.filePath,
|
|
1727
|
+
lineNumber: f.line,
|
|
1728
|
+
pattern: f.pattern,
|
|
1729
|
+
severity: f.severity,
|
|
1730
|
+
message: f.message
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
if (findings.length === 0) {
|
|
1734
|
+
return `\u{1F512} No security issues found in "${params.filePath}".`;
|
|
1735
|
+
}
|
|
1736
|
+
return `\u{1F512} **Security Scan** \u2014 ${findings.length} finding(s) in "${params.filePath}":
|
|
1737
|
+
${findings.map((f) => ` ${f.severity === "high" ? "\u{1F534}" : "\u{1F7E1}"} L${f.line}: ${f.message}`).join("\n")}`;
|
|
1738
|
+
}
|
|
1739
|
+
} catch {
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
return await getSecurityFindings();
|
|
1743
|
+
}
|
|
1744
|
+
async function handleGc(_params) {
|
|
1745
|
+
sessionMemory.recordToolCall("kuma_safety_gc", {});
|
|
1746
|
+
return await runGarbageCollection();
|
|
1747
|
+
}
|
|
1748
|
+
async function handleDoctor(_params) {
|
|
1749
|
+
sessionMemory.recordToolCall("kuma_safety_doctor", {});
|
|
1750
|
+
return await runDoctor();
|
|
1751
|
+
}
|
|
1752
|
+
async function handlePortability(_params) {
|
|
1753
|
+
sessionMemory.recordToolCall("kuma_safety_portability", {});
|
|
1754
|
+
return await checkPortability();
|
|
1755
|
+
}
|
|
1756
|
+
async function handleGitignore(_params) {
|
|
1757
|
+
sessionMemory.recordToolCall("kuma_safety_gitignore", {});
|
|
1758
|
+
return await ensureGitignore();
|
|
1759
|
+
}
|
|
1760
|
+
async function handleVerify(params) {
|
|
1761
|
+
sessionMemory.recordToolCall("kuma_safety_verify", { scope: params.scope || params.filePath });
|
|
1762
|
+
const { runAutoVerification } = await import("./kumaVerifier-VYW5WH6V.js");
|
|
1763
|
+
return await runAutoVerification({
|
|
1764
|
+
scope: params.scope || params.filePath,
|
|
1765
|
+
force: params.force,
|
|
1766
|
+
timeoutMs: 3e4
|
|
1767
|
+
});
|
|
1531
1768
|
}
|
|
1532
1769
|
|
|
1533
1770
|
// src/manifest.ts
|
|
@@ -1536,7 +1773,7 @@ function registerAllTools(server) {
|
|
|
1536
1773
|
"kuma_context",
|
|
1537
1774
|
"**Call FIRST every session.** Understand your project before making changes. Actions: init (load project brief), research (5-step pipeline: cache\u2192staleness\u2192graph\u2192impact\u2192decision), impact (analyze change effects), navigate (trace code flow), changes (view change log), health (project health score 0-100). RESEARCH IS REQUIRED before editing unfamiliar code.",
|
|
1538
1775
|
{
|
|
1539
|
-
action: z.enum(["init", "research", "impact", "navigate", "changes", "health"]).describe("Action: init=project brief, research=5-step research pipeline (REQUIRED before edits), impact=analyze change effects, navigate=trace code flow, changes=view change log, health=project health score"),
|
|
1776
|
+
action: z.enum(["init", "research", "impact", "navigate", "changes", "health", "rollback", "researches"]).describe("Action: init=project brief, research=5-step research pipeline (REQUIRED before edits), impact=analyze change effects, navigate=trace code flow, changes=view change log, rollback=undo a change by ID, researches=list all cached research, health=project health score"),
|
|
1540
1777
|
scope: z.string().optional().describe("Research scope for research action (e.g. 'auth', 'database', 'api')"),
|
|
1541
1778
|
target: z.string().optional().describe("Target symbol/file for impact/navigate/changes"),
|
|
1542
1779
|
goal: z.string().optional().describe("Current goal (for init/health)"),
|
|
@@ -1561,17 +1798,18 @@ function registerAllTools(server) {
|
|
|
1561
1798
|
);
|
|
1562
1799
|
server.tool(
|
|
1563
1800
|
"kuma_memory",
|
|
1564
|
-
"Record and retrieve project knowledge. Actions: decision (ADR-style record/template/suggest), research_save (save research
|
|
1801
|
+
"Record and retrieve project knowledge. Actions: decision (ADR-style record/template/suggest), mine (mine historical decisions from git log & code comments), research_save (save research), session (session summary), heal (graph repair), search (search all), changes (change log), todo (persistent todo CRUD), context (inject context notes), benchmark (capture/diff metrics), decision_log (living document with status tracking).",
|
|
1565
1802
|
{
|
|
1566
|
-
action: z.enum(["decision", "research_save", "session", "heal", "search", "changes"]).describe("Memory action: decision=
|
|
1567
|
-
scope: z.string().optional().describe("Scope for research_save/search"),
|
|
1803
|
+
action: z.enum(["decision", "mine", "research_save", "session", "heal", "search", "changes", "todo", "context", "benchmark", "decision_log"]).describe("Memory action: decision=ADR, mine=mine git log & comments, research_save=save, session=summary, heal=repair, search=search, changes=log, todo=manage todos, context=inject notes, benchmark=capture/diff, decision_log=manage decisions"),
|
|
1804
|
+
scope: z.string().optional().describe("Scope for research_save/search/todo/context/mine"),
|
|
1568
1805
|
query: z.string().optional().describe("Search query for search action"),
|
|
1569
|
-
content: z.string().optional().describe("Content/notes for research_save"),
|
|
1806
|
+
content: z.string().optional().describe("Content/notes for research_save / context"),
|
|
1570
1807
|
record: z.string().optional().describe("JSON record string for research_save"),
|
|
1571
1808
|
confidence: z.number().min(0).max(1).optional().describe("Confidence for research_save (0-1)"),
|
|
1809
|
+
confirm: z.boolean().optional().describe("Confirm and record candidates automatically for mine action"),
|
|
1572
1810
|
// Decision params
|
|
1573
1811
|
decisionAction: z.enum(["template", "suggest", "record"]).optional().describe("Decision sub-action"),
|
|
1574
|
-
title: z.string().optional().describe("Decision title"),
|
|
1812
|
+
title: z.string().optional().describe("Decision/todo/benchmark title"),
|
|
1575
1813
|
context: z.string().optional().describe("Decision context"),
|
|
1576
1814
|
rationale: z.string().optional().describe("Decision rationale"),
|
|
1577
1815
|
outcome: z.string().optional().describe("Decision outcome"),
|
|
@@ -1579,9 +1817,21 @@ function registerAllTools(server) {
|
|
|
1579
1817
|
healAction: z.enum(["check", "heal"]).optional().describe("Heal sub-action"),
|
|
1580
1818
|
topic: z.string().optional().describe("Memory topic for session"),
|
|
1581
1819
|
limit: z.number().min(1).max(100).optional().describe("Result limit"),
|
|
1582
|
-
target: z.string().optional().describe("File path for changes"),
|
|
1820
|
+
target: z.string().optional().describe("File path for changes / decision_log ID"),
|
|
1583
1821
|
since: z.number().optional().describe("Timestamp filter for changes"),
|
|
1584
|
-
compact: z.boolean().optional().default(false).describe("Compact output mode")
|
|
1822
|
+
compact: z.boolean().optional().default(false).describe("Compact output mode"),
|
|
1823
|
+
// Todo params
|
|
1824
|
+
description: z.string().optional().describe("Todo description"),
|
|
1825
|
+
deps: z.string().optional().describe("Todo dependencies (JSON array)"),
|
|
1826
|
+
success_criteria: z.string().optional().describe("Todo success criteria"),
|
|
1827
|
+
status: z.string().optional().describe("Status for todo/decision_log"),
|
|
1828
|
+
todoId: z.number().optional().describe("Todo ID for status update"),
|
|
1829
|
+
// Context params
|
|
1830
|
+
source: z.string().optional().describe("Context source (e.g. 'slack', 'jira', 'meeting')"),
|
|
1831
|
+
// Benchmark params
|
|
1832
|
+
label: z.string().optional().describe("Benchmark label"),
|
|
1833
|
+
metrics: z.string().optional().describe("Benchmark metrics JSON"),
|
|
1834
|
+
labelB: z.string().optional().describe("Second benchmark label for diff")
|
|
1585
1835
|
},
|
|
1586
1836
|
async (params) => {
|
|
1587
1837
|
try {
|
|
@@ -1592,6 +1842,7 @@ function registerAllTools(server) {
|
|
|
1592
1842
|
content: params.content,
|
|
1593
1843
|
record: params.record,
|
|
1594
1844
|
confidence: params.confidence,
|
|
1845
|
+
confirm: params.confirm,
|
|
1595
1846
|
decisionAction: params.decisionAction,
|
|
1596
1847
|
title: params.title,
|
|
1597
1848
|
context: params.context,
|
|
@@ -1611,14 +1862,16 @@ function registerAllTools(server) {
|
|
|
1611
1862
|
);
|
|
1612
1863
|
server.tool(
|
|
1613
1864
|
"kuma_safety",
|
|
1614
|
-
"Safety checks, policy enforcement,
|
|
1865
|
+
"Safety checks, policy enforcement, security scanning, integrated auto-verification, and project hygiene. Actions: guard (anti-pattern detection), verify (auto-run scoped tests), check (pre-exec safety), audit (query trail), lock (multi-agent), health (score), security (scan for leaks), gc (garbage collection), doctor (health check), portability (path check), gitignore (auto-config), override (bypass).",
|
|
1615
1866
|
{
|
|
1616
|
-
action: z.enum(["guard", "check", "audit", "lock", "health", "override"]).describe("Safety action: guard=anti-patterns, check=pre-exec safety, audit=query trail, lock=multi-agent, health=score, override=
|
|
1867
|
+
action: z.enum(["guard", "verify", "check", "audit", "lock", "health", "override", "security", "gc", "doctor", "portability", "gitignore"]).describe("Safety action: guard=anti-patterns, verify=auto-run scoped tests, check=pre-exec safety, audit=query trail, lock=multi-agent, health=score, security=scan leaks, gc=garbage collect, doctor=health check, portability=paths, gitignore=config, override=bypass"),
|
|
1868
|
+
// Verify params
|
|
1869
|
+
scope: z.string().optional().describe("Scope for verify or context (e.g. 'auth', file path)"),
|
|
1617
1870
|
// Guard params
|
|
1618
1871
|
guardGoal: z.string().optional().describe("Goal for guard check"),
|
|
1619
1872
|
guardCheck: z.enum(["all", "anti-pattern", "loop", "drift", "context"]).optional().describe("Guard check type"),
|
|
1620
1873
|
// Check params
|
|
1621
|
-
filePath: z.string().optional().describe("File path for check/lock"),
|
|
1874
|
+
filePath: z.string().optional().describe("File path for check/lock/security scan"),
|
|
1622
1875
|
command: z.string().optional().describe("Command for check"),
|
|
1623
1876
|
// Audit params
|
|
1624
1877
|
toolName: z.string().optional().describe("Filter audit by tool name"),
|
|
@@ -1641,6 +1894,7 @@ function registerAllTools(server) {
|
|
|
1641
1894
|
guardGoal: params.guardGoal,
|
|
1642
1895
|
guardCheck: params.guardCheck,
|
|
1643
1896
|
filePath: params.filePath,
|
|
1897
|
+
scope: params.scope,
|
|
1644
1898
|
command: params.command,
|
|
1645
1899
|
toolName: params.toolName,
|
|
1646
1900
|
riskLevel: params.riskLevel,
|
|
@@ -1788,7 +2042,7 @@ async function main() {
|
|
|
1788
2042
|
});
|
|
1789
2043
|
(async () => {
|
|
1790
2044
|
try {
|
|
1791
|
-
const { generateInitMdContent } = await import("./init-
|
|
2045
|
+
const { generateInitMdContent } = await import("./init-AJAESUZZ.js");
|
|
1792
2046
|
const fs7 = await import("fs");
|
|
1793
2047
|
const path7 = await import("path");
|
|
1794
2048
|
const initMdPath = path7.resolve(process.cwd(), ".kuma/init.md");
|
|
@@ -1804,7 +2058,7 @@ async function main() {
|
|
|
1804
2058
|
})();
|
|
1805
2059
|
(async () => {
|
|
1806
2060
|
try {
|
|
1807
|
-
const { detectAgent, getSkillPath, getAgentLabel } = await import("./agentDetector-
|
|
2061
|
+
const { detectAgent, getSkillPath, getAgentLabel } = await import("./agentDetector-G4RBMZ6X.js");
|
|
1808
2062
|
const { generateSkill, getSecondaryFiles } = await import("./skillGenerator-F6YO4H5D.js");
|
|
1809
2063
|
const fs7 = await import("fs");
|
|
1810
2064
|
const path7 = await import("path");
|
|
@@ -1838,6 +2092,38 @@ async function main() {
|
|
|
1838
2092
|
console.error(`[${SERVER_NAME}] Failed to auto-create skill file: ${err}`);
|
|
1839
2093
|
}
|
|
1840
2094
|
})();
|
|
2095
|
+
(async () => {
|
|
2096
|
+
try {
|
|
2097
|
+
console.error(`[${SERVER_NAME}] \u{1F504} Running cold start bootstrap...`);
|
|
2098
|
+
const sessionInfo = sessionMemory.loadSession();
|
|
2099
|
+
if (sessionInfo.hasPrevSession) {
|
|
2100
|
+
console.error(`[${SERVER_NAME}] \u2705 Restored session (${sessionInfo.toolCallCount} previous tool calls)`);
|
|
2101
|
+
}
|
|
2102
|
+
try {
|
|
2103
|
+
const { buildFromSessionMemory } = await import("./kumaGraph-5IZ4FDZA.js");
|
|
2104
|
+
const edgeCount = await buildFromSessionMemory();
|
|
2105
|
+
if (edgeCount > 0) {
|
|
2106
|
+
console.error(`[${SERVER_NAME}] \u2705 Graph auto-populated with ${edgeCount} entries from session memory`);
|
|
2107
|
+
}
|
|
2108
|
+
} catch (err) {
|
|
2109
|
+
console.error(`[${SERVER_NAME}] \u26A0\uFE0F Graph auto-population: ${err}`);
|
|
2110
|
+
}
|
|
2111
|
+
try {
|
|
2112
|
+
const { getDb: getDb2, saveDb: saveDb2 } = await import("./kumaDb-RC2EO3OB.js");
|
|
2113
|
+
const db = await getDb2();
|
|
2114
|
+
db.run(
|
|
2115
|
+
`INSERT INTO sessions (started_at, goal, tool_calls) VALUES (?, ?, ?)`,
|
|
2116
|
+
[Math.floor(Date.now() / 1e3), sessionMemory.getSummary().currentGoal || "Session start", sessionInfo.toolCallCount]
|
|
2117
|
+
);
|
|
2118
|
+
saveDb2(db);
|
|
2119
|
+
} catch (err) {
|
|
2120
|
+
console.error(`[${SERVER_NAME}] \u26A0\uFE0F Session DB record: ${err}`);
|
|
2121
|
+
}
|
|
2122
|
+
console.error(`[${SERVER_NAME}] \u2705 Cold start bootstrap complete`);
|
|
2123
|
+
} catch (err) {
|
|
2124
|
+
console.error(`[${SERVER_NAME}] \u26A0\uFE0F Cold start bootstrap error: ${err}`);
|
|
2125
|
+
}
|
|
2126
|
+
})();
|
|
1841
2127
|
const server = new McpServer(
|
|
1842
2128
|
{
|
|
1843
2129
|
name: SERVER_NAME,
|