@plumpslabs/kuma 2.3.7 → 2.3.9
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 +25 -3
- package/dist/{chunk-GDNAWLHF.js → chunk-3TX6Q37T.js} +89 -2
- package/dist/{chunk-X5TPBDKO.js → chunk-OJALFQ4H.js} +2 -2
- package/dist/chunk-Q2444HWO.js +282 -0
- package/dist/{chunk-BI7KD3SG.js → chunk-R6B3VUSB.js} +2 -2
- package/dist/chunk-RI3DKY62.js +155 -0
- package/dist/{chunk-FOQQ2CSL.js → chunk-SPHI2BOO.js} +1 -1
- package/dist/{chunk-K64NSHBR.js → chunk-ZKDYTYMS.js} +108 -2
- package/dist/contextDigest-5JXLH56Z.js +177 -0
- package/dist/domainRules-ED6EOFVY.js +20 -0
- package/dist/index.js +393 -198
- package/dist/kumaAstValidator-CNM7FHYA.js +150 -0
- package/dist/kumaCheckpoint-XIQWRMGV.js +207 -0
- package/dist/kumaCodeScanner-LFJGPJNH.js +566 -0
- package/dist/kumaContractEngine-KX27T4N7.js +305 -0
- package/dist/{kumaDb-DJUDLYBJ.js → kumaDb-IC7UX7PU.js} +3 -1
- package/dist/kumaDriftDetector-QBY6OJOO.js +237 -0
- package/dist/kumaGotchas-5HODT5RI.js +151 -0
- package/dist/{kumaGraph-35TAIBWD.js → kumaGraph-GUQM75WL.js} +8 -2
- package/dist/{kumaMemory-5SR3TGRL.js → kumaMemory-FMOWIODH.js} +2 -2
- package/dist/{kumaMiner-P5KCUSF7.js → kumaMiner-3RXEOCBP.js} +3 -3
- package/dist/kumaPolicyEngine-ORBWL5PT.js +311 -0
- package/dist/kumaProgressiveContext-CVSNPY3W.js +231 -0
- package/dist/{kumaSearch-LG2OYEJY.js → kumaSearch-B5WVYHHD.js} +1 -1
- package/dist/kumaTrajectory-T6DXGOG4.js +460 -0
- package/dist/{kumaVerifier-LFRNIGSL.js → kumaVerifier-KAYJHR5K.js} +25 -2
- package/dist/{kumaVisualize-ODCWFSUY.js → kumaVisualize-AFL7STLL.js} +1 -1
- package/dist/safetyAudit-32WSA4Z5.js +12 -0
- package/dist/{safetyScore-PJGRRBWP.js → safetyScore-WU27EOG4.js} +5 -5
- package/dist/{sessionMemory-HBBXUSIP.js → sessionMemory-4UWA3E5J.js} +1 -1
- package/package.json +18 -13
- package/packages/ide/studio/dist/index.js +140 -0
- package/packages/ide/studio/public/index.html +500 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
sessionMemory
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-R6B3VUSB.js";
|
|
4
4
|
import {
|
|
5
5
|
getLatestVerifications,
|
|
6
6
|
saveVerification
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3TX6Q37T.js";
|
|
8
8
|
import "./chunk-E2KFPEBT.js";
|
|
9
9
|
|
|
10
10
|
// src/engine/kumaVerifier.ts
|
|
@@ -56,6 +56,24 @@ var _localRunning = false;
|
|
|
56
56
|
var _currentProcess = null;
|
|
57
57
|
var STALE_RESULT_MS = 3e5;
|
|
58
58
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
59
|
+
var RUNAWAY_WINDOW_MS = 3e5;
|
|
60
|
+
var RUNAWAY_MAX_CALLS = 3;
|
|
61
|
+
var _verifyCallTimestamps = [];
|
|
62
|
+
function checkRunaway() {
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
while (_verifyCallTimestamps.length > 0 && _verifyCallTimestamps[0] < now - RUNAWAY_WINDOW_MS) {
|
|
65
|
+
_verifyCallTimestamps.shift();
|
|
66
|
+
}
|
|
67
|
+
if (_verifyCallTimestamps.length >= RUNAWAY_MAX_CALLS) {
|
|
68
|
+
const oldestInWindow = _verifyCallTimestamps[0];
|
|
69
|
+
const waitMs = RUNAWAY_WINDOW_MS - (now - oldestInWindow);
|
|
70
|
+
const waitSec = Math.ceil(waitMs / 1e3);
|
|
71
|
+
return `\u26D4 **Runaway protection active** \u2014 ${RUNAWAY_MAX_CALLS}+ verify calls in the last 5 minutes. Please wait ${waitSec}s before trying again.
|
|
72
|
+
\u{1F4A1} This prevents resource exhaustion (CPU/RAM) from uncontrolled test spawning.`;
|
|
73
|
+
}
|
|
74
|
+
_verifyCallTimestamps.push(now);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
59
77
|
function getRunningVerificationPid() {
|
|
60
78
|
return _currentProcess?.pid ?? null;
|
|
61
79
|
}
|
|
@@ -126,6 +144,11 @@ async function runAutoVerification(options = {}) {
|
|
|
126
144
|
const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS;
|
|
127
145
|
const denial = checkAllowed(root);
|
|
128
146
|
if (denial) return denial;
|
|
147
|
+
const runawayBlock = checkRunaway();
|
|
148
|
+
if (runawayBlock) {
|
|
149
|
+
releaseFileLock(root);
|
|
150
|
+
return runawayBlock;
|
|
151
|
+
}
|
|
129
152
|
try {
|
|
130
153
|
if (!options.force) {
|
|
131
154
|
const cached = await checkStaleness(scope);
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
getGitDiffStat,
|
|
3
3
|
getSessionStats,
|
|
4
4
|
getUnresolvedCount
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-SPHI2BOO.js";
|
|
6
6
|
import {
|
|
7
7
|
sessionMemory
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-R6B3VUSB.js";
|
|
9
9
|
import "./chunk-E2KFPEBT.js";
|
|
10
10
|
|
|
11
11
|
// src/engine/safetyScore.ts
|
|
@@ -60,7 +60,7 @@ async function computeSafetyScore(inputGoal) {
|
|
|
60
60
|
totalScore += 20;
|
|
61
61
|
}
|
|
62
62
|
try {
|
|
63
|
-
const { getDb } = await import("./kumaDb-
|
|
63
|
+
const { getDb } = await import("./kumaDb-IC7UX7PU.js");
|
|
64
64
|
const db = await getDb();
|
|
65
65
|
const nodeCount = db.exec("SELECT COUNT(*) as c FROM nodes")[0]?.values[0][0] ?? 0;
|
|
66
66
|
const edgeCount = db.exec("SELECT COUNT(*) as c FROM edges")[0]?.values[0][0] ?? 0;
|
|
@@ -91,7 +91,7 @@ async function computeSafetyScore(inputGoal) {
|
|
|
91
91
|
totalScore += 5;
|
|
92
92
|
}
|
|
93
93
|
try {
|
|
94
|
-
const { getDb } = await import("./kumaDb-
|
|
94
|
+
const { getDb } = await import("./kumaDb-IC7UX7PU.js");
|
|
95
95
|
const db = await getDb();
|
|
96
96
|
const researchCount = db.exec("SELECT COUNT(*) as c FROM research_cache")[0]?.values[0][0] ?? 0;
|
|
97
97
|
checks.push({
|
|
@@ -116,7 +116,7 @@ async function computeSafetyScore(inputGoal) {
|
|
|
116
116
|
const hasRunTests = stats.hasRunTests;
|
|
117
117
|
let latestVerif = null;
|
|
118
118
|
try {
|
|
119
|
-
const { getLatestVerifications } = await import("./kumaDb-
|
|
119
|
+
const { getLatestVerifications } = await import("./kumaDb-IC7UX7PU.js");
|
|
120
120
|
const verifs = await getLatestVerifications(1);
|
|
121
121
|
if (verifs.length > 0) latestVerif = verifs[0];
|
|
122
122
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumpslabs/kuma",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.9",
|
|
4
4
|
"description": "Safety-first context & orchestration engine for AI coding agents. MCP server with mandatory research pipeline, knowledge graph, impact analysis, decision memory, and safety guard — works with any MCP client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -9,17 +9,10 @@
|
|
|
9
9
|
"kuma": "dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
|
-
"dist/"
|
|
12
|
+
"dist/",
|
|
13
|
+
"packages/ide/studio/dist/",
|
|
14
|
+
"packages/ide/studio/public/"
|
|
13
15
|
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "tsup src/index.ts --format esm --clean --out-dir dist",
|
|
16
|
-
"dev": "tsup src/index.ts --format esm --watch --out-dir dist",
|
|
17
|
-
"start": "node dist/index.js",
|
|
18
|
-
"typecheck": "tsc --noEmit",
|
|
19
|
-
"lint": "echo 'No linting configured'",
|
|
20
|
-
"prepublishOnly": "npm run build",
|
|
21
|
-
"test": "NODE_OPTIONS=--experimental-vm-modules pnpm exec jest"
|
|
22
|
-
},
|
|
23
16
|
"dependencies": {
|
|
24
17
|
"@modelcontextprotocol/sdk": "^1.7.0",
|
|
25
18
|
"fast-glob": "^3.3.2",
|
|
@@ -68,5 +61,17 @@
|
|
|
68
61
|
"url": "https://github.com/plumpslabs/kuma/issues"
|
|
69
62
|
},
|
|
70
63
|
"homepage": "https://github.com/plumpslabs/kuma#readme",
|
|
71
|
-
"license": "MIT"
|
|
72
|
-
|
|
64
|
+
"license": "MIT",
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsup src/index.ts --format esm --clean --out-dir dist",
|
|
67
|
+
"build:studio": "cd packages/ide/studio && tsup src/index.ts --format esm --clean --out-dir dist",
|
|
68
|
+
"build:all": "pnpm run build && pnpm run build:studio",
|
|
69
|
+
"dev": "tsup src/index.ts --format esm --watch --out-dir dist",
|
|
70
|
+
"start": "node dist/index.js",
|
|
71
|
+
"studio": "node dist/index.js studio",
|
|
72
|
+
"studio:dev": "bun run packages/ide/studio/src/index.ts",
|
|
73
|
+
"typecheck": "tsc --noEmit",
|
|
74
|
+
"lint": "echo 'No linting configured'",
|
|
75
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules pnpm exec jest"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { serve } from "@hono/node-server";
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { join as join2, dirname } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import { spawn } from "child_process";
|
|
9
|
+
|
|
10
|
+
// src/api.ts
|
|
11
|
+
import { Hono } from "hono";
|
|
12
|
+
import { cors } from "hono/cors";
|
|
13
|
+
|
|
14
|
+
// src/db.ts
|
|
15
|
+
import { execSync } from "child_process";
|
|
16
|
+
import { existsSync } from "fs";
|
|
17
|
+
import { join, resolve } from "path";
|
|
18
|
+
function findKumaDb(startDir) {
|
|
19
|
+
let current = startDir ? resolve(startDir) : process.cwd();
|
|
20
|
+
for (let i = 0; i < 20; i++) {
|
|
21
|
+
const candidate = join(current, ".kuma", "kuma.db");
|
|
22
|
+
if (existsSync(candidate)) return candidate;
|
|
23
|
+
const parent = resolve(current, "..");
|
|
24
|
+
if (parent === current) break;
|
|
25
|
+
current = parent;
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function query(sql) {
|
|
30
|
+
const dbPath = findKumaDb();
|
|
31
|
+
if (!dbPath) throw new Error("No .kuma/kuma.db found");
|
|
32
|
+
return execSync(`sqlite3 "${dbPath}" "${sql}"`, {
|
|
33
|
+
encoding: "utf-8",
|
|
34
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
35
|
+
timeout: 1e4
|
|
36
|
+
}).trim();
|
|
37
|
+
}
|
|
38
|
+
function queryJson(sql) {
|
|
39
|
+
const raw = query(sql);
|
|
40
|
+
if (!raw) return [];
|
|
41
|
+
return JSON.parse(raw);
|
|
42
|
+
}
|
|
43
|
+
function getDashboardData() {
|
|
44
|
+
return {
|
|
45
|
+
stats: queryJson(`
|
|
46
|
+
SELECT json_object(
|
|
47
|
+
'node_count', (SELECT COUNT(*) FROM nodes),
|
|
48
|
+
'edge_count', (SELECT COUNT(*) FROM edges),
|
|
49
|
+
'gotcha_count', (SELECT COUNT(*) FROM known_gotchas),
|
|
50
|
+
'trajectory_count', (SELECT COUNT(*) FROM trajectories),
|
|
51
|
+
'skill_count', (SELECT COUNT(*) FROM distilled_skills),
|
|
52
|
+
'health_score', COALESCE((SELECT score FROM health_snapshots ORDER BY created_at DESC LIMIT 1), 0)
|
|
53
|
+
)
|
|
54
|
+
`),
|
|
55
|
+
nodes: queryJson(
|
|
56
|
+
`SELECT json_group_array(json_object('id',id,'name',name,'type',type,'file_path',file_path)) FROM nodes ORDER BY created_at DESC`
|
|
57
|
+
),
|
|
58
|
+
edges: queryJson(
|
|
59
|
+
`SELECT json_group_array(json_object('source',source_id,'target',target_id,'relation',type)) FROM edges`
|
|
60
|
+
),
|
|
61
|
+
gotchas: queryJson(
|
|
62
|
+
`SELECT json_group_array(json_object('id',id,'file_path',file_path,'description',description,'severity',severity,'workaround',workaround)) FROM known_gotchas ORDER BY severity DESC`
|
|
63
|
+
),
|
|
64
|
+
trajectories: queryJson(
|
|
65
|
+
`SELECT json_group_array(json_object('id',id,'goal',goal,'total_duration_ms',total_duration_ms,'success_rate',success_rate,'created_at',created_at)) FROM trajectories ORDER BY created_at DESC LIMIT 20`
|
|
66
|
+
),
|
|
67
|
+
health: queryJson(
|
|
68
|
+
`SELECT json_group_array(json_object('score',score,'summary',summary,'risk_level',risk_level,'created_at',created_at)) FROM health_snapshots ORDER BY created_at DESC LIMIT 10`
|
|
69
|
+
)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/api.ts
|
|
74
|
+
var api = new Hono();
|
|
75
|
+
api.use("/*", cors());
|
|
76
|
+
api.get("/status", (c) => {
|
|
77
|
+
const dbPath = findKumaDb();
|
|
78
|
+
return c.json({
|
|
79
|
+
ok: !!dbPath,
|
|
80
|
+
dbPath,
|
|
81
|
+
project: dbPath ? dbPath.replace("/.kuma/kuma.db", "").split("/").pop() : null
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
api.get("/dashboard", (c) => {
|
|
85
|
+
try {
|
|
86
|
+
const data = getDashboardData();
|
|
87
|
+
return c.json(data);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
return c.json({ error: e.message }, 500);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
var api_default = api;
|
|
93
|
+
|
|
94
|
+
// src/index.ts
|
|
95
|
+
import { Hono as Hono2 } from "hono";
|
|
96
|
+
var args = process.argv.slice(2);
|
|
97
|
+
var PORT = parseInt(args.find((a) => a.startsWith("--port="))?.split("=")[1] || "3322", 10);
|
|
98
|
+
var customDir = args.find((a) => a.startsWith("--dir="))?.split("=")[1];
|
|
99
|
+
var showHelp = args.includes("--help") || args.includes("-h");
|
|
100
|
+
if (showHelp) {
|
|
101
|
+
console.error(`\u2662 Kuma Studio \u2014 Usage:
|
|
102
|
+
bun run src/index.ts [options]
|
|
103
|
+
|
|
104
|
+
Options:
|
|
105
|
+
--port=PORT Server port (default: 3322)
|
|
106
|
+
--dir=PATH Project directory (default: auto-detect from cwd)
|
|
107
|
+
--help, -h Show this help
|
|
108
|
+
`);
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
112
|
+
if (customDir) {
|
|
113
|
+
process.chdir(customDir);
|
|
114
|
+
}
|
|
115
|
+
var app = new Hono2();
|
|
116
|
+
app.route("/api", api_default);
|
|
117
|
+
var htmlPath = join2(__dirname, "..", "public", "index.html");
|
|
118
|
+
var htmlCache = null;
|
|
119
|
+
try {
|
|
120
|
+
htmlCache = readFileSync(htmlPath, "utf-8");
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
app.get("/", (c) => {
|
|
124
|
+
if (!htmlCache) {
|
|
125
|
+
return c.text("index.html not found. Run from packages/ide/studio/", 500);
|
|
126
|
+
}
|
|
127
|
+
return c.html(htmlCache);
|
|
128
|
+
});
|
|
129
|
+
serve({ fetch: app.fetch, port: PORT }, (info) => {
|
|
130
|
+
const dbPath = findKumaDb();
|
|
131
|
+
const projectName = dbPath ? dbPath.replace("/.kuma/kuma.db", "").split("/").pop() : "unknown";
|
|
132
|
+
console.error(`\u2662 Kuma Studio`);
|
|
133
|
+
console.error(` Project: ${projectName}`);
|
|
134
|
+
console.error(` DB: ${dbPath || "not found"}`);
|
|
135
|
+
console.error(` Server: http://localhost:${PORT}`);
|
|
136
|
+
console.error(``);
|
|
137
|
+
const url = `http://localhost:${PORT}`;
|
|
138
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
139
|
+
spawn(cmd, [url], { stdio: "ignore", detached: true });
|
|
140
|
+
});
|