@deeplake/hivemind 0.7.45 → 0.7.47
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +64 -0
- package/bundle/cli.js +22702 -7775
- package/codex/bundle/capture.js +228 -0
- package/codex/bundle/commands/auth-login.js +228 -0
- package/codex/bundle/graph-pull-worker.js +1370 -0
- package/codex/bundle/pre-tool-use.js +228 -0
- package/codex/bundle/session-start-setup.js +228 -0
- package/codex/bundle/session-start.js +255 -4
- package/codex/bundle/shell/deeplake-shell.js +1028 -28
- package/codex/bundle/skillify-worker.js +94 -3
- package/codex/bundle/stop.js +282 -50
- package/codex/skills/hivemind-goals/SKILL.md +157 -0
- package/cursor/bundle/capture.js +282 -50
- package/cursor/bundle/commands/auth-login.js +228 -0
- package/cursor/bundle/graph-pull-worker.js +1370 -0
- package/cursor/bundle/pre-tool-use.js +228 -0
- package/cursor/bundle/session-end.js +65 -44
- package/cursor/bundle/session-start.js +662 -6
- package/cursor/bundle/shell/deeplake-shell.js +1028 -28
- package/cursor/bundle/skillify-worker.js +94 -3
- package/hermes/bundle/capture.js +282 -50
- package/hermes/bundle/commands/auth-login.js +228 -0
- package/hermes/bundle/graph-pull-worker.js +1370 -0
- package/hermes/bundle/pre-tool-use.js +228 -0
- package/hermes/bundle/session-end.js +65 -44
- package/hermes/bundle/session-start.js +662 -6
- package/hermes/bundle/shell/deeplake-shell.js +1028 -28
- package/hermes/bundle/skillify-worker.js +94 -3
- package/mcp/bundle/server.js +228 -0
- package/openclaw/dist/chunks/config-FH6JYSJW.js +53 -0
- package/openclaw/dist/index.js +307 -2
- package/openclaw/dist/skillify-worker.js +94 -3
- package/openclaw/openclaw.plugin.json +4 -2
- package/openclaw/package.json +1 -1
- package/openclaw/skills/hivemind-goals/SKILL.md +30 -0
- package/package.json +4 -1
- package/openclaw/dist/chunks/config-XEK4MJJS.js +0 -36
|
@@ -378,6 +378,65 @@ var SKILLS_COLUMNS = Object.freeze([
|
|
|
378
378
|
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
379
379
|
{ name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
380
380
|
]);
|
|
381
|
+
var RULES_COLUMNS = Object.freeze([
|
|
382
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
383
|
+
{ name: "rule_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
384
|
+
{ name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
385
|
+
{ name: "scope", sql: "TEXT NOT NULL DEFAULT 'team'" },
|
|
386
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
|
|
387
|
+
{ name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
388
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
389
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
390
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
391
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
392
|
+
]);
|
|
393
|
+
var TASKS_COLUMNS = Object.freeze([
|
|
394
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
395
|
+
{ name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
396
|
+
{ name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
397
|
+
{ name: "scope", sql: "TEXT NOT NULL DEFAULT 'me'" },
|
|
398
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
|
|
399
|
+
{ name: "assigned_to", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
400
|
+
{ name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
401
|
+
{ name: "kpis", sql: "JSONB" },
|
|
402
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
403
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
404
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
405
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
406
|
+
]);
|
|
407
|
+
var TASK_EVENTS_COLUMNS = Object.freeze([
|
|
408
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
409
|
+
{ name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
410
|
+
{ name: "task_version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
411
|
+
{ name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
412
|
+
{ name: "value", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
413
|
+
{ name: "note", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
414
|
+
{ name: "source", sql: "TEXT NOT NULL DEFAULT 'user'" },
|
|
415
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
416
|
+
{ name: "ts", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
417
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
418
|
+
]);
|
|
419
|
+
var GOALS_COLUMNS = Object.freeze([
|
|
420
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
421
|
+
{ name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
422
|
+
{ name: "owner", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
423
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'opened'" },
|
|
424
|
+
{ name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
425
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
426
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
427
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
428
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
429
|
+
]);
|
|
430
|
+
var KPIS_COLUMNS = Object.freeze([
|
|
431
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
432
|
+
{ name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
433
|
+
{ name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
434
|
+
{ name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
435
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
436
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
437
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
438
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
439
|
+
]);
|
|
381
440
|
function validateSchema(label, cols) {
|
|
382
441
|
const seen = /* @__PURE__ */ new Set();
|
|
383
442
|
for (const col of cols) {
|
|
@@ -395,9 +454,38 @@ function validateSchema(label, cols) {
|
|
|
395
454
|
}
|
|
396
455
|
}
|
|
397
456
|
}
|
|
457
|
+
var CODEBASE_COLUMNS = Object.freeze([
|
|
458
|
+
// Identity key (matches the PK below)
|
|
459
|
+
{ name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
460
|
+
{ name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
461
|
+
{ name: "repo_slug", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
462
|
+
{ name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
463
|
+
{ name: "worktree_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
464
|
+
{ name: "commit_sha", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
465
|
+
// Observation metadata
|
|
466
|
+
{ name: "parent_sha", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
467
|
+
{ name: "branch", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
468
|
+
{ name: "ts", sql: "TIMESTAMP" },
|
|
469
|
+
{ name: "pushed_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
470
|
+
// Snapshot payload
|
|
471
|
+
{ name: "snapshot_sha256", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
472
|
+
{ name: "snapshot_jsonb", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
473
|
+
{ name: "node_count", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
474
|
+
{ name: "edge_count", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
475
|
+
// Generator metadata (for drift diagnostics — what hivemind version produced this?)
|
|
476
|
+
{ name: "generator", sql: "TEXT NOT NULL DEFAULT 'hivemind-graph'" },
|
|
477
|
+
{ name: "generator_version", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
478
|
+
{ name: "schema_version", sql: "BIGINT NOT NULL DEFAULT 1" }
|
|
479
|
+
]);
|
|
398
480
|
validateSchema("MEMORY_COLUMNS", MEMORY_COLUMNS);
|
|
399
481
|
validateSchema("SESSIONS_COLUMNS", SESSIONS_COLUMNS);
|
|
400
482
|
validateSchema("SKILLS_COLUMNS", SKILLS_COLUMNS);
|
|
483
|
+
validateSchema("RULES_COLUMNS", RULES_COLUMNS);
|
|
484
|
+
validateSchema("TASKS_COLUMNS", TASKS_COLUMNS);
|
|
485
|
+
validateSchema("TASK_EVENTS_COLUMNS", TASK_EVENTS_COLUMNS);
|
|
486
|
+
validateSchema("GOALS_COLUMNS", GOALS_COLUMNS);
|
|
487
|
+
validateSchema("KPIS_COLUMNS", KPIS_COLUMNS);
|
|
488
|
+
validateSchema("CODEBASE_COLUMNS", CODEBASE_COLUMNS);
|
|
401
489
|
function buildCreateTableSql(tableName, cols) {
|
|
402
490
|
const safe = sqlIdent(tableName);
|
|
403
491
|
const colSql = cols.map((c) => `${c.name} ${c.sql}`).join(", ");
|
|
@@ -693,9 +781,12 @@ function resolveRecordScope(args) {
|
|
|
693
781
|
|
|
694
782
|
// dist/src/skillify/state.js
|
|
695
783
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, writeSync, mkdirSync as mkdirSync2, renameSync as renameSync2, rmdirSync, existsSync as existsSync4, lstatSync, unlinkSync, openSync, closeSync } from "node:fs";
|
|
784
|
+
import { join as join6 } from "node:path";
|
|
785
|
+
|
|
786
|
+
// dist/src/utils/repo-identity.js
|
|
696
787
|
import { execSync } from "node:child_process";
|
|
697
788
|
import { createHash } from "node:crypto";
|
|
698
|
-
import {
|
|
789
|
+
import { basename, resolve } from "node:path";
|
|
699
790
|
|
|
700
791
|
// dist/src/skillify/legacy-migration.js
|
|
701
792
|
import { existsSync as existsSync3, renameSync } from "node:fs";
|
|
@@ -881,7 +972,7 @@ async function query(sql, retries = 4) {
|
|
|
881
972
|
const base = Math.min(3e4, 2e3 * Math.pow(2, attempt));
|
|
882
973
|
const delay = base + Math.floor(Math.random() * 1e3);
|
|
883
974
|
wlog(`fetch failed (${e?.name ?? e?.code ?? e?.message}), retrying in ${delay}ms (attempt ${attempt + 1}/${retries})`);
|
|
884
|
-
await new Promise((
|
|
975
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
885
976
|
continue;
|
|
886
977
|
}
|
|
887
978
|
throw e;
|
|
@@ -897,7 +988,7 @@ async function query(sql, retries = 4) {
|
|
|
897
988
|
const base = Math.min(3e4, 2e3 * Math.pow(2, attempt));
|
|
898
989
|
const delay = base + Math.floor(Math.random() * 1e3);
|
|
899
990
|
wlog(`API ${r.status}, retrying in ${delay}ms (attempt ${attempt + 1}/${retries})`);
|
|
900
|
-
await new Promise((
|
|
991
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
901
992
|
continue;
|
|
902
993
|
}
|
|
903
994
|
throw new Error(`API ${r.status}: ${(await r.text()).slice(0, 200)}`);
|
package/hermes/bundle/capture.js
CHANGED
|
@@ -53,13 +53,13 @@ var init_index_marker_store = __esm({
|
|
|
53
53
|
|
|
54
54
|
// dist/src/utils/stdin.js
|
|
55
55
|
function readStdin() {
|
|
56
|
-
return new Promise((
|
|
56
|
+
return new Promise((resolve3, reject) => {
|
|
57
57
|
let data = "";
|
|
58
58
|
process.stdin.setEncoding("utf-8");
|
|
59
59
|
process.stdin.on("data", (chunk) => data += chunk);
|
|
60
60
|
process.stdin.on("end", () => {
|
|
61
61
|
try {
|
|
62
|
-
|
|
62
|
+
resolve3(JSON.parse(data));
|
|
63
63
|
} catch (err) {
|
|
64
64
|
reject(new Error(`Failed to parse hook input: ${err}`));
|
|
65
65
|
}
|
|
@@ -97,6 +97,23 @@ function loadConfig() {
|
|
|
97
97
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
98
98
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
99
99
|
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
100
|
+
// Defaults match the table name written into the SQL — keep aligned
|
|
101
|
+
// with RULES_COLUMNS / TASKS_COLUMNS / TASK_EVENTS_COLUMNS in
|
|
102
|
+
// deeplake-schema.ts and with the e2e test-org override convention
|
|
103
|
+
// (memory_test / sessions_test → goals_test, etc.) documented in
|
|
104
|
+
// CLAUDE.md.
|
|
105
|
+
rulesTableName: process.env.HIVEMIND_RULES_TABLE ?? "hivemind_rules",
|
|
106
|
+
tasksTableName: process.env.HIVEMIND_TASKS_TABLE ?? "hivemind_tasks",
|
|
107
|
+
taskEventsTableName: process.env.HIVEMIND_TASK_EVENTS_TABLE ?? "hivemind_task_events",
|
|
108
|
+
// Goals + KPIs (refined design — VFS path classifier maps
|
|
109
|
+
// memory/goal/<user>/<status>/<uuid>.md → hivemind_goals row
|
|
110
|
+
// memory/kpi/<uuid>/<kpi_id>.md → hivemind_kpis row
|
|
111
|
+
// See src/shell/deeplake-fs.ts for the translation logic and
|
|
112
|
+
// GOALS_COLUMNS / KPIS_COLUMNS in deeplake-schema.ts for the
|
|
113
|
+
// table shape.
|
|
114
|
+
goalsTableName: process.env.HIVEMIND_GOALS_TABLE ?? "hivemind_goals",
|
|
115
|
+
kpisTableName: process.env.HIVEMIND_KPIS_TABLE ?? "hivemind_kpis",
|
|
116
|
+
codebaseTableName: process.env.HIVEMIND_CODEBASE_TABLE ?? "codebase",
|
|
100
117
|
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join(home, ".deeplake", "memory")
|
|
101
118
|
};
|
|
102
119
|
}
|
|
@@ -197,6 +214,65 @@ var SKILLS_COLUMNS = Object.freeze([
|
|
|
197
214
|
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
198
215
|
{ name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
199
216
|
]);
|
|
217
|
+
var RULES_COLUMNS = Object.freeze([
|
|
218
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
219
|
+
{ name: "rule_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
220
|
+
{ name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
221
|
+
{ name: "scope", sql: "TEXT NOT NULL DEFAULT 'team'" },
|
|
222
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
|
|
223
|
+
{ name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
224
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
225
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
226
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
227
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
228
|
+
]);
|
|
229
|
+
var TASKS_COLUMNS = Object.freeze([
|
|
230
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
231
|
+
{ name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
232
|
+
{ name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
233
|
+
{ name: "scope", sql: "TEXT NOT NULL DEFAULT 'me'" },
|
|
234
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
|
|
235
|
+
{ name: "assigned_to", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
236
|
+
{ name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
237
|
+
{ name: "kpis", sql: "JSONB" },
|
|
238
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
239
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
240
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
241
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
242
|
+
]);
|
|
243
|
+
var TASK_EVENTS_COLUMNS = Object.freeze([
|
|
244
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
245
|
+
{ name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
246
|
+
{ name: "task_version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
247
|
+
{ name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
248
|
+
{ name: "value", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
249
|
+
{ name: "note", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
250
|
+
{ name: "source", sql: "TEXT NOT NULL DEFAULT 'user'" },
|
|
251
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
252
|
+
{ name: "ts", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
253
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
254
|
+
]);
|
|
255
|
+
var GOALS_COLUMNS = Object.freeze([
|
|
256
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
257
|
+
{ name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
258
|
+
{ name: "owner", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
259
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'opened'" },
|
|
260
|
+
{ name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
261
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
262
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
263
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
264
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
265
|
+
]);
|
|
266
|
+
var KPIS_COLUMNS = Object.freeze([
|
|
267
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
268
|
+
{ name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
269
|
+
{ name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
270
|
+
{ name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
271
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
272
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
273
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
274
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
275
|
+
]);
|
|
200
276
|
function validateSchema(label, cols) {
|
|
201
277
|
const seen = /* @__PURE__ */ new Set();
|
|
202
278
|
for (const col of cols) {
|
|
@@ -214,9 +290,38 @@ function validateSchema(label, cols) {
|
|
|
214
290
|
}
|
|
215
291
|
}
|
|
216
292
|
}
|
|
293
|
+
var CODEBASE_COLUMNS = Object.freeze([
|
|
294
|
+
// Identity key (matches the PK below)
|
|
295
|
+
{ name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
296
|
+
{ name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
297
|
+
{ name: "repo_slug", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
298
|
+
{ name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
299
|
+
{ name: "worktree_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
300
|
+
{ name: "commit_sha", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
301
|
+
// Observation metadata
|
|
302
|
+
{ name: "parent_sha", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
303
|
+
{ name: "branch", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
304
|
+
{ name: "ts", sql: "TIMESTAMP" },
|
|
305
|
+
{ name: "pushed_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
306
|
+
// Snapshot payload
|
|
307
|
+
{ name: "snapshot_sha256", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
308
|
+
{ name: "snapshot_jsonb", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
309
|
+
{ name: "node_count", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
310
|
+
{ name: "edge_count", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
311
|
+
// Generator metadata (for drift diagnostics — what hivemind version produced this?)
|
|
312
|
+
{ name: "generator", sql: "TEXT NOT NULL DEFAULT 'hivemind-graph'" },
|
|
313
|
+
{ name: "generator_version", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
314
|
+
{ name: "schema_version", sql: "BIGINT NOT NULL DEFAULT 1" }
|
|
315
|
+
]);
|
|
217
316
|
validateSchema("MEMORY_COLUMNS", MEMORY_COLUMNS);
|
|
218
317
|
validateSchema("SESSIONS_COLUMNS", SESSIONS_COLUMNS);
|
|
219
318
|
validateSchema("SKILLS_COLUMNS", SKILLS_COLUMNS);
|
|
319
|
+
validateSchema("RULES_COLUMNS", RULES_COLUMNS);
|
|
320
|
+
validateSchema("TASKS_COLUMNS", TASKS_COLUMNS);
|
|
321
|
+
validateSchema("TASK_EVENTS_COLUMNS", TASK_EVENTS_COLUMNS);
|
|
322
|
+
validateSchema("GOALS_COLUMNS", GOALS_COLUMNS);
|
|
323
|
+
validateSchema("KPIS_COLUMNS", KPIS_COLUMNS);
|
|
324
|
+
validateSchema("CODEBASE_COLUMNS", CODEBASE_COLUMNS);
|
|
220
325
|
function buildCreateTableSql(tableName, cols) {
|
|
221
326
|
const safe = sqlIdent(tableName);
|
|
222
327
|
const colSql = cols.map((c) => `${c.name} ${c.sql}`).join(", ");
|
|
@@ -441,7 +546,7 @@ function getQueryTimeoutMs() {
|
|
|
441
546
|
return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
|
|
442
547
|
}
|
|
443
548
|
function sleep2(ms) {
|
|
444
|
-
return new Promise((
|
|
549
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
445
550
|
}
|
|
446
551
|
function isTimeoutError(error) {
|
|
447
552
|
const name = error instanceof Error ? error.name.toLowerCase() : "";
|
|
@@ -471,7 +576,7 @@ var Semaphore = class {
|
|
|
471
576
|
this.active++;
|
|
472
577
|
return;
|
|
473
578
|
}
|
|
474
|
-
await new Promise((
|
|
579
|
+
await new Promise((resolve3) => this.waiting.push(resolve3));
|
|
475
580
|
}
|
|
476
581
|
release() {
|
|
477
582
|
this.active--;
|
|
@@ -781,6 +886,24 @@ var DeeplakeApi = class {
|
|
|
781
886
|
* This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
|
|
782
887
|
* worker.
|
|
783
888
|
*/
|
|
889
|
+
/**
|
|
890
|
+
* Create the codebase table. One row per (org, workspace, repo, user,
|
|
891
|
+
* worktree, commit) — see CODEBASE_COLUMNS for the schema. Healing
|
|
892
|
+
* + index follow the same pattern as ensureSessionsTable.
|
|
893
|
+
*/
|
|
894
|
+
async ensureCodebaseTable(name) {
|
|
895
|
+
const safe = sqlIdent(name);
|
|
896
|
+
const tables = await this.listTables();
|
|
897
|
+
if (!tables.includes(safe)) {
|
|
898
|
+
log3(`table "${safe}" not found, creating`);
|
|
899
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, CODEBASE_COLUMNS), safe);
|
|
900
|
+
log3(`table "${safe}" created`);
|
|
901
|
+
if (!tables.includes(safe))
|
|
902
|
+
this._tablesCache = [...tables, safe];
|
|
903
|
+
}
|
|
904
|
+
await this.healSchema(safe, CODEBASE_COLUMNS);
|
|
905
|
+
await this.ensureLookupIndex(safe, "codebase_identity", `("org_id", "workspace_id", "repo_slug", "user_id", "worktree_id", "commit_sha")`);
|
|
906
|
+
}
|
|
784
907
|
async ensureSkillsTable(name) {
|
|
785
908
|
const safe = sqlIdent(name);
|
|
786
909
|
const tables = await this.listTables();
|
|
@@ -794,6 +917,111 @@ var DeeplakeApi = class {
|
|
|
794
917
|
await this.healSchema(safe, SKILLS_COLUMNS);
|
|
795
918
|
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
796
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* Create the rules table.
|
|
922
|
+
*
|
|
923
|
+
* One row per rule version (same write pattern as skills): edits INSERT
|
|
924
|
+
* a fresh row with version+1, reads pick latest per rule_id via
|
|
925
|
+
* `ORDER BY version DESC LIMIT 1`. Sidesteps the Deeplake
|
|
926
|
+
* UPDATE-coalescing quirk by never UPDATEing.
|
|
927
|
+
*/
|
|
928
|
+
async ensureRulesTable(name) {
|
|
929
|
+
const safe = sqlIdent(name);
|
|
930
|
+
const tables = await this.listTables();
|
|
931
|
+
if (!tables.includes(safe)) {
|
|
932
|
+
log3(`table "${safe}" not found, creating`);
|
|
933
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, RULES_COLUMNS), safe);
|
|
934
|
+
log3(`table "${safe}" created`);
|
|
935
|
+
if (!tables.includes(safe))
|
|
936
|
+
this._tablesCache = [...tables, safe];
|
|
937
|
+
}
|
|
938
|
+
await this.healSchema(safe, RULES_COLUMNS);
|
|
939
|
+
await this.ensureLookupIndex(safe, "rule_id_version", `("rule_id", "version")`);
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Create the tasks table.
|
|
943
|
+
*
|
|
944
|
+
* Same write pattern as rules + skills. `kpis` is a nullable JSONB
|
|
945
|
+
* column with the agent's KPI metadata; KPI current values come from
|
|
946
|
+
* `task_events` (SUM(value)), not this snapshot.
|
|
947
|
+
*/
|
|
948
|
+
async ensureTasksTable(name) {
|
|
949
|
+
const safe = sqlIdent(name);
|
|
950
|
+
const tables = await this.listTables();
|
|
951
|
+
if (!tables.includes(safe)) {
|
|
952
|
+
log3(`table "${safe}" not found, creating`);
|
|
953
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, TASKS_COLUMNS), safe);
|
|
954
|
+
log3(`table "${safe}" created`);
|
|
955
|
+
if (!tables.includes(safe))
|
|
956
|
+
this._tablesCache = [...tables, safe];
|
|
957
|
+
}
|
|
958
|
+
await this.healSchema(safe, TASKS_COLUMNS);
|
|
959
|
+
await this.ensureLookupIndex(safe, "task_id_version", `("task_id", "version")`);
|
|
960
|
+
}
|
|
961
|
+
/**
|
|
962
|
+
* Create the task-events table.
|
|
963
|
+
*
|
|
964
|
+
* Append-only. Every INSERT is a fresh row; never UPDATE. KPI current
|
|
965
|
+
* value is `SUM(value) WHERE task_id=? AND kpi_id=?`. Index on
|
|
966
|
+
* (task_id, kpi_id) is the canonical aggregation key.
|
|
967
|
+
*/
|
|
968
|
+
async ensureTaskEventsTable(name) {
|
|
969
|
+
const safe = sqlIdent(name);
|
|
970
|
+
const tables = await this.listTables();
|
|
971
|
+
if (!tables.includes(safe)) {
|
|
972
|
+
log3(`table "${safe}" not found, creating`);
|
|
973
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, TASK_EVENTS_COLUMNS), safe);
|
|
974
|
+
log3(`table "${safe}" created`);
|
|
975
|
+
if (!tables.includes(safe))
|
|
976
|
+
this._tablesCache = [...tables, safe];
|
|
977
|
+
}
|
|
978
|
+
await this.healSchema(safe, TASK_EVENTS_COLUMNS);
|
|
979
|
+
await this.ensureLookupIndex(safe, "task_id_kpi_id", `("task_id", "kpi_id")`);
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Create the goals table.
|
|
983
|
+
*
|
|
984
|
+
* Backed by the VFS path convention memory/goal/<owner>/<status>/<goal_id>.md.
|
|
985
|
+
* INSERT-only version-bumped: rm and mv operations translate to fresh
|
|
986
|
+
* v=N+1 rows (status flips for mv → closed; rm is the same soft-close).
|
|
987
|
+
* The (goal_id, version) index lets the VFS dispatch a cheap latest-row
|
|
988
|
+
* read on cat / Read of a single goal.
|
|
989
|
+
*/
|
|
990
|
+
async ensureGoalsTable(name) {
|
|
991
|
+
const safe = sqlIdent(name);
|
|
992
|
+
const tables = await this.listTables();
|
|
993
|
+
if (!tables.includes(safe)) {
|
|
994
|
+
log3(`table "${safe}" not found, creating`);
|
|
995
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, GOALS_COLUMNS), safe);
|
|
996
|
+
log3(`table "${safe}" created`);
|
|
997
|
+
if (!tables.includes(safe))
|
|
998
|
+
this._tablesCache = [...tables, safe];
|
|
999
|
+
}
|
|
1000
|
+
await this.healSchema(safe, GOALS_COLUMNS);
|
|
1001
|
+
await this.ensureLookupIndex(safe, "goal_id_version", `("goal_id", "version")`);
|
|
1002
|
+
await this.ensureLookupIndex(safe, "owner_status", `("owner", "status")`);
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Create the kpis table.
|
|
1006
|
+
*
|
|
1007
|
+
* Backed by memory/kpi/<goal_id>/<kpi_id>.md. KPI rows do NOT carry
|
|
1008
|
+
* owner — ownership derives from the parent goal via logical join on
|
|
1009
|
+
* goal_id. INSERT-only version-bumped. (goal_id, kpi_id) index is the
|
|
1010
|
+
* canonical lookup the VFS uses on Read and Write.
|
|
1011
|
+
*/
|
|
1012
|
+
async ensureKpisTable(name) {
|
|
1013
|
+
const safe = sqlIdent(name);
|
|
1014
|
+
const tables = await this.listTables();
|
|
1015
|
+
if (!tables.includes(safe)) {
|
|
1016
|
+
log3(`table "${safe}" not found, creating`);
|
|
1017
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, KPIS_COLUMNS), safe);
|
|
1018
|
+
log3(`table "${safe}" created`);
|
|
1019
|
+
if (!tables.includes(safe))
|
|
1020
|
+
this._tablesCache = [...tables, safe];
|
|
1021
|
+
}
|
|
1022
|
+
await this.healSchema(safe, KPIS_COLUMNS);
|
|
1023
|
+
await this.ensureLookupIndex(safe, "goal_id_kpi_id", `("goal_id", "kpi_id")`);
|
|
1024
|
+
}
|
|
797
1025
|
};
|
|
798
1026
|
|
|
799
1027
|
// dist/src/utils/session-path.js
|
|
@@ -1056,7 +1284,7 @@ var EmbedClient = class {
|
|
|
1056
1284
|
}
|
|
1057
1285
|
}
|
|
1058
1286
|
connectOnce() {
|
|
1059
|
-
return new Promise((
|
|
1287
|
+
return new Promise((resolve3, reject) => {
|
|
1060
1288
|
const sock = connect(this.socketPath);
|
|
1061
1289
|
const to = setTimeout(() => {
|
|
1062
1290
|
sock.destroy();
|
|
@@ -1064,7 +1292,7 @@ var EmbedClient = class {
|
|
|
1064
1292
|
}, this.timeoutMs);
|
|
1065
1293
|
sock.once("connect", () => {
|
|
1066
1294
|
clearTimeout(to);
|
|
1067
|
-
|
|
1295
|
+
resolve3(sock);
|
|
1068
1296
|
});
|
|
1069
1297
|
sock.once("error", (e) => {
|
|
1070
1298
|
clearTimeout(to);
|
|
@@ -1146,7 +1374,7 @@ var EmbedClient = class {
|
|
|
1146
1374
|
throw new Error("daemon did not become ready within spawnWaitMs");
|
|
1147
1375
|
}
|
|
1148
1376
|
sendAndWait(sock, req) {
|
|
1149
|
-
return new Promise((
|
|
1377
|
+
return new Promise((resolve3, reject) => {
|
|
1150
1378
|
let buf = "";
|
|
1151
1379
|
const to = setTimeout(() => {
|
|
1152
1380
|
sock.destroy();
|
|
@@ -1161,7 +1389,7 @@ var EmbedClient = class {
|
|
|
1161
1389
|
const line = buf.slice(0, nl);
|
|
1162
1390
|
clearTimeout(to);
|
|
1163
1391
|
try {
|
|
1164
|
-
|
|
1392
|
+
resolve3(JSON.parse(line));
|
|
1165
1393
|
} catch (e) {
|
|
1166
1394
|
reject(e);
|
|
1167
1395
|
}
|
|
@@ -1818,9 +2046,54 @@ function spawnSkillifyWorker(opts) {
|
|
|
1818
2046
|
|
|
1819
2047
|
// dist/src/skillify/state.js
|
|
1820
2048
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, writeSync as writeSync3, mkdirSync as mkdirSync10, renameSync as renameSync6, rmdirSync, existsSync as existsSync9, lstatSync as lstatSync2, unlinkSync as unlinkSync5, openSync as openSync4, closeSync as closeSync4 } from "node:fs";
|
|
2049
|
+
import { join as join18 } from "node:path";
|
|
2050
|
+
|
|
2051
|
+
// dist/src/utils/repo-identity.js
|
|
1821
2052
|
import { execSync as execSync2 } from "node:child_process";
|
|
1822
2053
|
import { createHash } from "node:crypto";
|
|
1823
|
-
import {
|
|
2054
|
+
import { basename as basename2, resolve as resolve2 } from "node:path";
|
|
2055
|
+
var DEFAULT_PORTS = {
|
|
2056
|
+
http: "80",
|
|
2057
|
+
https: "443",
|
|
2058
|
+
ssh: "22",
|
|
2059
|
+
git: "9418"
|
|
2060
|
+
};
|
|
2061
|
+
function normalizeGitRemoteUrl(url) {
|
|
2062
|
+
let s = url.trim();
|
|
2063
|
+
const schemeMatch = s.match(/^([a-z][a-z0-9+.-]*):\/\//i);
|
|
2064
|
+
const scheme = schemeMatch ? schemeMatch[1].toLowerCase() : null;
|
|
2065
|
+
if (schemeMatch)
|
|
2066
|
+
s = s.slice(schemeMatch[0].length);
|
|
2067
|
+
if (!scheme) {
|
|
2068
|
+
const scp = s.match(/^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/);
|
|
2069
|
+
if (scp)
|
|
2070
|
+
s = `${scp[1]}/${scp[2]}`;
|
|
2071
|
+
}
|
|
2072
|
+
s = s.replace(/^[^@/]+@/, "");
|
|
2073
|
+
if (scheme && DEFAULT_PORTS[scheme]) {
|
|
2074
|
+
s = s.replace(new RegExp(`^([^/]+):${DEFAULT_PORTS[scheme]}(/|$)`), "$1$2");
|
|
2075
|
+
}
|
|
2076
|
+
s = s.replace(/\.git\/?$/i, "");
|
|
2077
|
+
s = s.replace(/\/+$/, "");
|
|
2078
|
+
return s.toLowerCase();
|
|
2079
|
+
}
|
|
2080
|
+
function deriveProjectKey(cwd) {
|
|
2081
|
+
const absCwd = resolve2(cwd);
|
|
2082
|
+
const project = basename2(absCwd) || "unknown";
|
|
2083
|
+
let signature = null;
|
|
2084
|
+
try {
|
|
2085
|
+
const raw = execSync2("git config --get remote.origin.url", {
|
|
2086
|
+
cwd: absCwd,
|
|
2087
|
+
encoding: "utf-8",
|
|
2088
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2089
|
+
}).trim();
|
|
2090
|
+
signature = raw ? normalizeGitRemoteUrl(raw) : null;
|
|
2091
|
+
} catch {
|
|
2092
|
+
}
|
|
2093
|
+
const input = signature ?? absCwd;
|
|
2094
|
+
const key = createHash("sha1").update(input).digest("hex").slice(0, 16);
|
|
2095
|
+
return { key, project };
|
|
2096
|
+
}
|
|
1824
2097
|
|
|
1825
2098
|
// dist/src/skillify/legacy-migration.js
|
|
1826
2099
|
import { existsSync as existsSync8, renameSync as renameSync5 } from "node:fs";
|
|
@@ -1875,47 +2148,6 @@ function statePath2(projectKey) {
|
|
|
1875
2148
|
function lockPath3(projectKey) {
|
|
1876
2149
|
return join18(getStateDir(), `${projectKey}.lock`);
|
|
1877
2150
|
}
|
|
1878
|
-
var DEFAULT_PORTS = {
|
|
1879
|
-
http: "80",
|
|
1880
|
-
https: "443",
|
|
1881
|
-
ssh: "22",
|
|
1882
|
-
git: "9418"
|
|
1883
|
-
};
|
|
1884
|
-
function normalizeGitRemoteUrl(url) {
|
|
1885
|
-
let s = url.trim();
|
|
1886
|
-
const schemeMatch = s.match(/^([a-z][a-z0-9+.-]*):\/\//i);
|
|
1887
|
-
const scheme = schemeMatch ? schemeMatch[1].toLowerCase() : null;
|
|
1888
|
-
if (schemeMatch)
|
|
1889
|
-
s = s.slice(schemeMatch[0].length);
|
|
1890
|
-
if (!scheme) {
|
|
1891
|
-
const scp = s.match(/^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/);
|
|
1892
|
-
if (scp)
|
|
1893
|
-
s = `${scp[1]}/${scp[2]}`;
|
|
1894
|
-
}
|
|
1895
|
-
s = s.replace(/^[^@/]+@/, "");
|
|
1896
|
-
if (scheme && DEFAULT_PORTS[scheme]) {
|
|
1897
|
-
s = s.replace(new RegExp(`^([^/]+):${DEFAULT_PORTS[scheme]}(/|$)`), "$1$2");
|
|
1898
|
-
}
|
|
1899
|
-
s = s.replace(/\.git\/?$/i, "");
|
|
1900
|
-
s = s.replace(/\/+$/, "");
|
|
1901
|
-
return s.toLowerCase();
|
|
1902
|
-
}
|
|
1903
|
-
function deriveProjectKey(cwd) {
|
|
1904
|
-
const project = basename2(cwd) || "unknown";
|
|
1905
|
-
let signature = null;
|
|
1906
|
-
try {
|
|
1907
|
-
const raw = execSync2("git config --get remote.origin.url", {
|
|
1908
|
-
cwd,
|
|
1909
|
-
encoding: "utf-8",
|
|
1910
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
1911
|
-
}).trim();
|
|
1912
|
-
signature = raw ? normalizeGitRemoteUrl(raw) : null;
|
|
1913
|
-
} catch {
|
|
1914
|
-
}
|
|
1915
|
-
const input = signature ?? cwd;
|
|
1916
|
-
const key = createHash("sha1").update(input).digest("hex").slice(0, 16);
|
|
1917
|
-
return { key, project };
|
|
1918
|
-
}
|
|
1919
2151
|
function readState2(projectKey) {
|
|
1920
2152
|
migrateLegacyStateDir();
|
|
1921
2153
|
const p = statePath2(projectKey);
|