@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
|
@@ -121,6 +121,23 @@ function loadConfig() {
|
|
|
121
121
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
122
122
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
123
123
|
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
124
|
+
// Defaults match the table name written into the SQL — keep aligned
|
|
125
|
+
// with RULES_COLUMNS / TASKS_COLUMNS / TASK_EVENTS_COLUMNS in
|
|
126
|
+
// deeplake-schema.ts and with the e2e test-org override convention
|
|
127
|
+
// (memory_test / sessions_test → goals_test, etc.) documented in
|
|
128
|
+
// CLAUDE.md.
|
|
129
|
+
rulesTableName: process.env.HIVEMIND_RULES_TABLE ?? "hivemind_rules",
|
|
130
|
+
tasksTableName: process.env.HIVEMIND_TASKS_TABLE ?? "hivemind_tasks",
|
|
131
|
+
taskEventsTableName: process.env.HIVEMIND_TASK_EVENTS_TABLE ?? "hivemind_task_events",
|
|
132
|
+
// Goals + KPIs (refined design — VFS path classifier maps
|
|
133
|
+
// memory/goal/<user>/<status>/<uuid>.md → hivemind_goals row
|
|
134
|
+
// memory/kpi/<uuid>/<kpi_id>.md → hivemind_kpis row
|
|
135
|
+
// See src/shell/deeplake-fs.ts for the translation logic and
|
|
136
|
+
// GOALS_COLUMNS / KPIS_COLUMNS in deeplake-schema.ts for the
|
|
137
|
+
// table shape.
|
|
138
|
+
goalsTableName: process.env.HIVEMIND_GOALS_TABLE ?? "hivemind_goals",
|
|
139
|
+
kpisTableName: process.env.HIVEMIND_KPIS_TABLE ?? "hivemind_kpis",
|
|
140
|
+
codebaseTableName: process.env.HIVEMIND_CODEBASE_TABLE ?? "codebase",
|
|
124
141
|
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join3(home, ".deeplake", "memory")
|
|
125
142
|
};
|
|
126
143
|
}
|
|
@@ -209,6 +226,65 @@ var SKILLS_COLUMNS = Object.freeze([
|
|
|
209
226
|
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
210
227
|
{ name: "updated_at", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
211
228
|
]);
|
|
229
|
+
var RULES_COLUMNS = Object.freeze([
|
|
230
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
231
|
+
{ name: "rule_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
232
|
+
{ name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
233
|
+
{ name: "scope", sql: "TEXT NOT NULL DEFAULT 'team'" },
|
|
234
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
|
|
235
|
+
{ name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
236
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
237
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
238
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
239
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
240
|
+
]);
|
|
241
|
+
var TASKS_COLUMNS = Object.freeze([
|
|
242
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
243
|
+
{ name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
244
|
+
{ name: "text", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
245
|
+
{ name: "scope", sql: "TEXT NOT NULL DEFAULT 'me'" },
|
|
246
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'active'" },
|
|
247
|
+
{ name: "assigned_to", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
248
|
+
{ name: "assigned_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
249
|
+
{ name: "kpis", sql: "JSONB" },
|
|
250
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
251
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
252
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
253
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
254
|
+
]);
|
|
255
|
+
var TASK_EVENTS_COLUMNS = Object.freeze([
|
|
256
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
257
|
+
{ name: "task_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
258
|
+
{ name: "task_version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
259
|
+
{ name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
260
|
+
{ name: "value", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
261
|
+
{ name: "note", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
262
|
+
{ name: "source", sql: "TEXT NOT NULL DEFAULT 'user'" },
|
|
263
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
264
|
+
{ name: "ts", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
265
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
266
|
+
]);
|
|
267
|
+
var GOALS_COLUMNS = Object.freeze([
|
|
268
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
269
|
+
{ name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
270
|
+
{ name: "owner", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
271
|
+
{ name: "status", sql: "TEXT NOT NULL DEFAULT 'opened'" },
|
|
272
|
+
{ name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
273
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
274
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
275
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
276
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
277
|
+
]);
|
|
278
|
+
var KPIS_COLUMNS = Object.freeze([
|
|
279
|
+
{ name: "id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
280
|
+
{ name: "goal_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
281
|
+
{ name: "kpi_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
282
|
+
{ name: "content", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
283
|
+
{ name: "version", sql: "BIGINT NOT NULL DEFAULT 1" },
|
|
284
|
+
{ name: "created_at", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
285
|
+
{ name: "agent", sql: "TEXT NOT NULL DEFAULT 'manual'" },
|
|
286
|
+
{ name: "plugin_version", sql: "TEXT NOT NULL DEFAULT ''" }
|
|
287
|
+
]);
|
|
212
288
|
function validateSchema(label, cols) {
|
|
213
289
|
const seen = /* @__PURE__ */ new Set();
|
|
214
290
|
for (const col of cols) {
|
|
@@ -226,9 +302,38 @@ function validateSchema(label, cols) {
|
|
|
226
302
|
}
|
|
227
303
|
}
|
|
228
304
|
}
|
|
305
|
+
var CODEBASE_COLUMNS = Object.freeze([
|
|
306
|
+
// Identity key (matches the PK below)
|
|
307
|
+
{ name: "org_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
308
|
+
{ name: "workspace_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
309
|
+
{ name: "repo_slug", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
310
|
+
{ name: "user_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
311
|
+
{ name: "worktree_id", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
312
|
+
{ name: "commit_sha", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
313
|
+
// Observation metadata
|
|
314
|
+
{ name: "parent_sha", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
315
|
+
{ name: "branch", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
316
|
+
{ name: "ts", sql: "TIMESTAMP" },
|
|
317
|
+
{ name: "pushed_by", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
318
|
+
// Snapshot payload
|
|
319
|
+
{ name: "snapshot_sha256", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
320
|
+
{ name: "snapshot_jsonb", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
321
|
+
{ name: "node_count", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
322
|
+
{ name: "edge_count", sql: "BIGINT NOT NULL DEFAULT 0" },
|
|
323
|
+
// Generator metadata (for drift diagnostics — what hivemind version produced this?)
|
|
324
|
+
{ name: "generator", sql: "TEXT NOT NULL DEFAULT 'hivemind-graph'" },
|
|
325
|
+
{ name: "generator_version", sql: "TEXT NOT NULL DEFAULT ''" },
|
|
326
|
+
{ name: "schema_version", sql: "BIGINT NOT NULL DEFAULT 1" }
|
|
327
|
+
]);
|
|
229
328
|
validateSchema("MEMORY_COLUMNS", MEMORY_COLUMNS);
|
|
230
329
|
validateSchema("SESSIONS_COLUMNS", SESSIONS_COLUMNS);
|
|
231
330
|
validateSchema("SKILLS_COLUMNS", SKILLS_COLUMNS);
|
|
331
|
+
validateSchema("RULES_COLUMNS", RULES_COLUMNS);
|
|
332
|
+
validateSchema("TASKS_COLUMNS", TASKS_COLUMNS);
|
|
333
|
+
validateSchema("TASK_EVENTS_COLUMNS", TASK_EVENTS_COLUMNS);
|
|
334
|
+
validateSchema("GOALS_COLUMNS", GOALS_COLUMNS);
|
|
335
|
+
validateSchema("KPIS_COLUMNS", KPIS_COLUMNS);
|
|
336
|
+
validateSchema("CODEBASE_COLUMNS", CODEBASE_COLUMNS);
|
|
232
337
|
function buildCreateTableSql(tableName, cols) {
|
|
233
338
|
const safe = sqlIdent(tableName);
|
|
234
339
|
const colSql = cols.map((c) => `${c.name} ${c.sql}`).join(", ");
|
|
@@ -775,6 +880,24 @@ var DeeplakeApi = class {
|
|
|
775
880
|
* This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
|
|
776
881
|
* worker.
|
|
777
882
|
*/
|
|
883
|
+
/**
|
|
884
|
+
* Create the codebase table. One row per (org, workspace, repo, user,
|
|
885
|
+
* worktree, commit) — see CODEBASE_COLUMNS for the schema. Healing
|
|
886
|
+
* + index follow the same pattern as ensureSessionsTable.
|
|
887
|
+
*/
|
|
888
|
+
async ensureCodebaseTable(name) {
|
|
889
|
+
const safe = sqlIdent(name);
|
|
890
|
+
const tables = await this.listTables();
|
|
891
|
+
if (!tables.includes(safe)) {
|
|
892
|
+
log3(`table "${safe}" not found, creating`);
|
|
893
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, CODEBASE_COLUMNS), safe);
|
|
894
|
+
log3(`table "${safe}" created`);
|
|
895
|
+
if (!tables.includes(safe))
|
|
896
|
+
this._tablesCache = [...tables, safe];
|
|
897
|
+
}
|
|
898
|
+
await this.healSchema(safe, CODEBASE_COLUMNS);
|
|
899
|
+
await this.ensureLookupIndex(safe, "codebase_identity", `("org_id", "workspace_id", "repo_slug", "user_id", "worktree_id", "commit_sha")`);
|
|
900
|
+
}
|
|
778
901
|
async ensureSkillsTable(name) {
|
|
779
902
|
const safe = sqlIdent(name);
|
|
780
903
|
const tables = await this.listTables();
|
|
@@ -788,8 +911,467 @@ var DeeplakeApi = class {
|
|
|
788
911
|
await this.healSchema(safe, SKILLS_COLUMNS);
|
|
789
912
|
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
790
913
|
}
|
|
914
|
+
/**
|
|
915
|
+
* Create the rules table.
|
|
916
|
+
*
|
|
917
|
+
* One row per rule version (same write pattern as skills): edits INSERT
|
|
918
|
+
* a fresh row with version+1, reads pick latest per rule_id via
|
|
919
|
+
* `ORDER BY version DESC LIMIT 1`. Sidesteps the Deeplake
|
|
920
|
+
* UPDATE-coalescing quirk by never UPDATEing.
|
|
921
|
+
*/
|
|
922
|
+
async ensureRulesTable(name) {
|
|
923
|
+
const safe = sqlIdent(name);
|
|
924
|
+
const tables = await this.listTables();
|
|
925
|
+
if (!tables.includes(safe)) {
|
|
926
|
+
log3(`table "${safe}" not found, creating`);
|
|
927
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, RULES_COLUMNS), safe);
|
|
928
|
+
log3(`table "${safe}" created`);
|
|
929
|
+
if (!tables.includes(safe))
|
|
930
|
+
this._tablesCache = [...tables, safe];
|
|
931
|
+
}
|
|
932
|
+
await this.healSchema(safe, RULES_COLUMNS);
|
|
933
|
+
await this.ensureLookupIndex(safe, "rule_id_version", `("rule_id", "version")`);
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Create the tasks table.
|
|
937
|
+
*
|
|
938
|
+
* Same write pattern as rules + skills. `kpis` is a nullable JSONB
|
|
939
|
+
* column with the agent's KPI metadata; KPI current values come from
|
|
940
|
+
* `task_events` (SUM(value)), not this snapshot.
|
|
941
|
+
*/
|
|
942
|
+
async ensureTasksTable(name) {
|
|
943
|
+
const safe = sqlIdent(name);
|
|
944
|
+
const tables = await this.listTables();
|
|
945
|
+
if (!tables.includes(safe)) {
|
|
946
|
+
log3(`table "${safe}" not found, creating`);
|
|
947
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, TASKS_COLUMNS), safe);
|
|
948
|
+
log3(`table "${safe}" created`);
|
|
949
|
+
if (!tables.includes(safe))
|
|
950
|
+
this._tablesCache = [...tables, safe];
|
|
951
|
+
}
|
|
952
|
+
await this.healSchema(safe, TASKS_COLUMNS);
|
|
953
|
+
await this.ensureLookupIndex(safe, "task_id_version", `("task_id", "version")`);
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Create the task-events table.
|
|
957
|
+
*
|
|
958
|
+
* Append-only. Every INSERT is a fresh row; never UPDATE. KPI current
|
|
959
|
+
* value is `SUM(value) WHERE task_id=? AND kpi_id=?`. Index on
|
|
960
|
+
* (task_id, kpi_id) is the canonical aggregation key.
|
|
961
|
+
*/
|
|
962
|
+
async ensureTaskEventsTable(name) {
|
|
963
|
+
const safe = sqlIdent(name);
|
|
964
|
+
const tables = await this.listTables();
|
|
965
|
+
if (!tables.includes(safe)) {
|
|
966
|
+
log3(`table "${safe}" not found, creating`);
|
|
967
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, TASK_EVENTS_COLUMNS), safe);
|
|
968
|
+
log3(`table "${safe}" created`);
|
|
969
|
+
if (!tables.includes(safe))
|
|
970
|
+
this._tablesCache = [...tables, safe];
|
|
971
|
+
}
|
|
972
|
+
await this.healSchema(safe, TASK_EVENTS_COLUMNS);
|
|
973
|
+
await this.ensureLookupIndex(safe, "task_id_kpi_id", `("task_id", "kpi_id")`);
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Create the goals table.
|
|
977
|
+
*
|
|
978
|
+
* Backed by the VFS path convention memory/goal/<owner>/<status>/<goal_id>.md.
|
|
979
|
+
* INSERT-only version-bumped: rm and mv operations translate to fresh
|
|
980
|
+
* v=N+1 rows (status flips for mv → closed; rm is the same soft-close).
|
|
981
|
+
* The (goal_id, version) index lets the VFS dispatch a cheap latest-row
|
|
982
|
+
* read on cat / Read of a single goal.
|
|
983
|
+
*/
|
|
984
|
+
async ensureGoalsTable(name) {
|
|
985
|
+
const safe = sqlIdent(name);
|
|
986
|
+
const tables = await this.listTables();
|
|
987
|
+
if (!tables.includes(safe)) {
|
|
988
|
+
log3(`table "${safe}" not found, creating`);
|
|
989
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, GOALS_COLUMNS), safe);
|
|
990
|
+
log3(`table "${safe}" created`);
|
|
991
|
+
if (!tables.includes(safe))
|
|
992
|
+
this._tablesCache = [...tables, safe];
|
|
993
|
+
}
|
|
994
|
+
await this.healSchema(safe, GOALS_COLUMNS);
|
|
995
|
+
await this.ensureLookupIndex(safe, "goal_id_version", `("goal_id", "version")`);
|
|
996
|
+
await this.ensureLookupIndex(safe, "owner_status", `("owner", "status")`);
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Create the kpis table.
|
|
1000
|
+
*
|
|
1001
|
+
* Backed by memory/kpi/<goal_id>/<kpi_id>.md. KPI rows do NOT carry
|
|
1002
|
+
* owner — ownership derives from the parent goal via logical join on
|
|
1003
|
+
* goal_id. INSERT-only version-bumped. (goal_id, kpi_id) index is the
|
|
1004
|
+
* canonical lookup the VFS uses on Read and Write.
|
|
1005
|
+
*/
|
|
1006
|
+
async ensureKpisTable(name) {
|
|
1007
|
+
const safe = sqlIdent(name);
|
|
1008
|
+
const tables = await this.listTables();
|
|
1009
|
+
if (!tables.includes(safe)) {
|
|
1010
|
+
log3(`table "${safe}" not found, creating`);
|
|
1011
|
+
await this.createTableWithRetry(buildCreateTableSql(safe, KPIS_COLUMNS), safe);
|
|
1012
|
+
log3(`table "${safe}" created`);
|
|
1013
|
+
if (!tables.includes(safe))
|
|
1014
|
+
this._tablesCache = [...tables, safe];
|
|
1015
|
+
}
|
|
1016
|
+
await this.healSchema(safe, KPIS_COLUMNS);
|
|
1017
|
+
await this.ensureLookupIndex(safe, "goal_id_kpi_id", `("goal_id", "kpi_id")`);
|
|
1018
|
+
}
|
|
791
1019
|
};
|
|
792
1020
|
|
|
1021
|
+
// dist/src/rules/write.js
|
|
1022
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
1023
|
+
|
|
1024
|
+
// dist/src/rules/read.js
|
|
1025
|
+
var SELECT_COLS = "id, rule_id, text, scope, status, assigned_by, version, created_at, agent, plugin_version";
|
|
1026
|
+
async function listRules(query, tableName, opts = {}) {
|
|
1027
|
+
const safe = sqlIdent(tableName);
|
|
1028
|
+
const rows = await query(`SELECT ${SELECT_COLS} FROM "${safe}" ORDER BY version DESC, created_at DESC, id DESC`);
|
|
1029
|
+
const latest = /* @__PURE__ */ new Map();
|
|
1030
|
+
for (const r of rows) {
|
|
1031
|
+
const row = normalize(r);
|
|
1032
|
+
if (!row)
|
|
1033
|
+
continue;
|
|
1034
|
+
if (!latest.has(row.rule_id))
|
|
1035
|
+
latest.set(row.rule_id, row);
|
|
1036
|
+
}
|
|
1037
|
+
const statusFilter = opts.status ?? "active";
|
|
1038
|
+
const filtered = [...latest.values()].filter((r) => statusFilter === "all" ? true : r.status === statusFilter);
|
|
1039
|
+
filtered.sort((a, b) => b.created_at.localeCompare(a.created_at) || b.id.localeCompare(a.id));
|
|
1040
|
+
return filtered.slice(0, opts.limit ?? 10);
|
|
1041
|
+
}
|
|
1042
|
+
function normalize(row) {
|
|
1043
|
+
const vRaw = row.version;
|
|
1044
|
+
const version = typeof vRaw === "number" ? vRaw : typeof vRaw === "string" ? Number(vRaw) : NaN;
|
|
1045
|
+
if (!Number.isFinite(version))
|
|
1046
|
+
return null;
|
|
1047
|
+
return {
|
|
1048
|
+
id: String(row.id ?? ""),
|
|
1049
|
+
rule_id: String(row.rule_id ?? ""),
|
|
1050
|
+
text: String(row.text ?? ""),
|
|
1051
|
+
scope: String(row.scope ?? ""),
|
|
1052
|
+
status: String(row.status ?? ""),
|
|
1053
|
+
assigned_by: String(row.assigned_by ?? ""),
|
|
1054
|
+
version,
|
|
1055
|
+
created_at: String(row.created_at ?? ""),
|
|
1056
|
+
agent: String(row.agent ?? ""),
|
|
1057
|
+
plugin_version: String(row.plugin_version ?? "")
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// dist/src/tasks/write.js
|
|
1062
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
1063
|
+
|
|
1064
|
+
// dist/src/tasks/kpi-validator.js
|
|
1065
|
+
function parseKpis(raw) {
|
|
1066
|
+
if (raw == null || raw === "")
|
|
1067
|
+
return [];
|
|
1068
|
+
let arr;
|
|
1069
|
+
if (typeof raw === "string") {
|
|
1070
|
+
try {
|
|
1071
|
+
arr = JSON.parse(raw);
|
|
1072
|
+
} catch {
|
|
1073
|
+
return [];
|
|
1074
|
+
}
|
|
1075
|
+
} else {
|
|
1076
|
+
arr = raw;
|
|
1077
|
+
}
|
|
1078
|
+
if (!Array.isArray(arr))
|
|
1079
|
+
return [];
|
|
1080
|
+
const out = [];
|
|
1081
|
+
for (const item of arr) {
|
|
1082
|
+
const kpi = validateOne(item);
|
|
1083
|
+
if (kpi)
|
|
1084
|
+
out.push(kpi);
|
|
1085
|
+
}
|
|
1086
|
+
return out;
|
|
1087
|
+
}
|
|
1088
|
+
function validateOne(item) {
|
|
1089
|
+
if (!isObject(item))
|
|
1090
|
+
return null;
|
|
1091
|
+
const kpi_id = safeStr(item.kpi_id);
|
|
1092
|
+
const name = safeStr(item.name);
|
|
1093
|
+
const target = num(item.target);
|
|
1094
|
+
const unit = safeStr(item.unit);
|
|
1095
|
+
const generated_by = safeStr(item.generated_by);
|
|
1096
|
+
const generated_at = isoStr(item.generated_at);
|
|
1097
|
+
if (kpi_id === null || name === null || target === null || unit === null || generated_by === null || generated_at === null) {
|
|
1098
|
+
return null;
|
|
1099
|
+
}
|
|
1100
|
+
if (!Number.isInteger(target) || target <= 0) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
const out = {
|
|
1104
|
+
kpi_id,
|
|
1105
|
+
name,
|
|
1106
|
+
target,
|
|
1107
|
+
unit,
|
|
1108
|
+
generated_by,
|
|
1109
|
+
generated_at
|
|
1110
|
+
};
|
|
1111
|
+
const current = num(item.current);
|
|
1112
|
+
if (current !== null)
|
|
1113
|
+
out.current = current;
|
|
1114
|
+
return out;
|
|
1115
|
+
}
|
|
1116
|
+
function isObject(v) {
|
|
1117
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1118
|
+
}
|
|
1119
|
+
function str(v) {
|
|
1120
|
+
if (typeof v !== "string" || v.length === 0)
|
|
1121
|
+
return null;
|
|
1122
|
+
return v;
|
|
1123
|
+
}
|
|
1124
|
+
function safeStr(v) {
|
|
1125
|
+
const s = str(v);
|
|
1126
|
+
if (s === null)
|
|
1127
|
+
return null;
|
|
1128
|
+
if (/[\r\n\u2028\u2029\u0085]/.test(s))
|
|
1129
|
+
return null;
|
|
1130
|
+
return s;
|
|
1131
|
+
}
|
|
1132
|
+
function num(v) {
|
|
1133
|
+
if (typeof v !== "number" || !Number.isFinite(v))
|
|
1134
|
+
return null;
|
|
1135
|
+
return v;
|
|
1136
|
+
}
|
|
1137
|
+
function isoStr(v) {
|
|
1138
|
+
const s = safeStr(v);
|
|
1139
|
+
if (s === null)
|
|
1140
|
+
return null;
|
|
1141
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})?$/.test(s)) {
|
|
1142
|
+
return null;
|
|
1143
|
+
}
|
|
1144
|
+
return s;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// dist/src/tasks/read.js
|
|
1148
|
+
var SELECT_COLS2 = "id, task_id, text, scope, status, assigned_to, assigned_by, kpis, version, created_at, agent, plugin_version";
|
|
1149
|
+
async function listTasks(query, tableName, opts = {}) {
|
|
1150
|
+
const safe = sqlIdent(tableName);
|
|
1151
|
+
const rows = await query(`SELECT ${SELECT_COLS2} FROM "${safe}" ORDER BY version DESC, created_at DESC, id DESC`);
|
|
1152
|
+
const latest = /* @__PURE__ */ new Map();
|
|
1153
|
+
for (const r of rows) {
|
|
1154
|
+
const row = normalize2(r);
|
|
1155
|
+
if (!row)
|
|
1156
|
+
continue;
|
|
1157
|
+
if (!latest.has(row.task_id))
|
|
1158
|
+
latest.set(row.task_id, row);
|
|
1159
|
+
}
|
|
1160
|
+
const scope = opts.scope ?? "all";
|
|
1161
|
+
const status = opts.status ?? "active";
|
|
1162
|
+
const current = opts.current_user;
|
|
1163
|
+
const filtered = [...latest.values()].filter((row) => {
|
|
1164
|
+
if (status !== "all" && row.status !== status)
|
|
1165
|
+
return false;
|
|
1166
|
+
if (scope === "mine") {
|
|
1167
|
+
if (!current)
|
|
1168
|
+
return false;
|
|
1169
|
+
return row.assigned_to === current;
|
|
1170
|
+
}
|
|
1171
|
+
if (scope === "me") {
|
|
1172
|
+
if (!current)
|
|
1173
|
+
return false;
|
|
1174
|
+
return row.scope === "me" && row.assigned_to === current;
|
|
1175
|
+
}
|
|
1176
|
+
if (scope === "team")
|
|
1177
|
+
return row.scope === "team";
|
|
1178
|
+
return true;
|
|
1179
|
+
});
|
|
1180
|
+
filtered.sort((a, b) => b.created_at.localeCompare(a.created_at) || b.id.localeCompare(a.id));
|
|
1181
|
+
return filtered.slice(0, opts.limit ?? 10);
|
|
1182
|
+
}
|
|
1183
|
+
function normalize2(row) {
|
|
1184
|
+
const vRaw = row.version;
|
|
1185
|
+
const version = typeof vRaw === "number" ? vRaw : typeof vRaw === "string" ? Number(vRaw) : NaN;
|
|
1186
|
+
if (!Number.isFinite(version))
|
|
1187
|
+
return null;
|
|
1188
|
+
return {
|
|
1189
|
+
id: String(row.id ?? ""),
|
|
1190
|
+
task_id: String(row.task_id ?? ""),
|
|
1191
|
+
text: String(row.text ?? ""),
|
|
1192
|
+
scope: String(row.scope ?? ""),
|
|
1193
|
+
status: String(row.status ?? ""),
|
|
1194
|
+
assigned_to: String(row.assigned_to ?? ""),
|
|
1195
|
+
assigned_by: String(row.assigned_by ?? ""),
|
|
1196
|
+
kpis: parseKpis(row.kpis),
|
|
1197
|
+
version,
|
|
1198
|
+
created_at: String(row.created_at ?? ""),
|
|
1199
|
+
agent: String(row.agent ?? ""),
|
|
1200
|
+
plugin_version: String(row.plugin_version ?? "")
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// dist/src/events/append.js
|
|
1205
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
1206
|
+
|
|
1207
|
+
// dist/src/events/aggregate.js
|
|
1208
|
+
async function computeAllForTasks(query, tableName, taskIds) {
|
|
1209
|
+
if (taskIds.length === 0)
|
|
1210
|
+
return {};
|
|
1211
|
+
const safe = sqlIdent(tableName);
|
|
1212
|
+
const inList = taskIds.map((id) => `'${sqlStr(id)}'`).join(", ");
|
|
1213
|
+
const rows = await query(`SELECT task_id, kpi_id, SUM(value) AS total FROM "${safe}" WHERE task_id IN (${inList}) GROUP BY task_id, kpi_id`);
|
|
1214
|
+
const out = {};
|
|
1215
|
+
for (const row of rows) {
|
|
1216
|
+
const tid = typeof row.task_id === "string" ? row.task_id : "";
|
|
1217
|
+
const kid = typeof row.kpi_id === "string" ? row.kpi_id : "";
|
|
1218
|
+
if (!tid || !kid)
|
|
1219
|
+
continue;
|
|
1220
|
+
if (!out[tid])
|
|
1221
|
+
out[tid] = {};
|
|
1222
|
+
out[tid][kid] = normalizeTotal(row.total);
|
|
1223
|
+
}
|
|
1224
|
+
return out;
|
|
1225
|
+
}
|
|
1226
|
+
function normalizeTotal(raw) {
|
|
1227
|
+
if (raw == null)
|
|
1228
|
+
return 0;
|
|
1229
|
+
if (typeof raw === "number")
|
|
1230
|
+
return Number.isFinite(raw) ? raw : 0;
|
|
1231
|
+
if (typeof raw === "string") {
|
|
1232
|
+
const n = Number(raw);
|
|
1233
|
+
return Number.isFinite(n) ? n : 0;
|
|
1234
|
+
}
|
|
1235
|
+
return 0;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// dist/src/hooks/shared/context-renderer.js
|
|
1239
|
+
async function renderContextBlock(query, input, opts = {}) {
|
|
1240
|
+
const maxRules = opts.maxRules ?? 10;
|
|
1241
|
+
const maxTasks = opts.maxTasks ?? 10;
|
|
1242
|
+
const log7 = opts.log ?? (() => {
|
|
1243
|
+
});
|
|
1244
|
+
try {
|
|
1245
|
+
let rules = [];
|
|
1246
|
+
try {
|
|
1247
|
+
rules = await listRules(query, input.rulesTable, {
|
|
1248
|
+
status: "active",
|
|
1249
|
+
limit: Math.max(maxRules * 4, maxRules + 1)
|
|
1250
|
+
});
|
|
1251
|
+
} catch (rulesErr) {
|
|
1252
|
+
const rmsg = rulesErr instanceof Error ? rulesErr.message : String(rulesErr);
|
|
1253
|
+
log7(`render-context-block: rules unavailable (continuing): ${rmsg}`);
|
|
1254
|
+
}
|
|
1255
|
+
let teamTasks = [];
|
|
1256
|
+
let myTasks = [];
|
|
1257
|
+
try {
|
|
1258
|
+
teamTasks = await listTasks(query, input.tasksTable, {
|
|
1259
|
+
scope: "team",
|
|
1260
|
+
status: "active",
|
|
1261
|
+
limit: Math.max(maxTasks * 4, maxTasks + 1)
|
|
1262
|
+
});
|
|
1263
|
+
myTasks = await listTasks(query, input.tasksTable, {
|
|
1264
|
+
scope: "me",
|
|
1265
|
+
status: "active",
|
|
1266
|
+
current_user: input.currentUser,
|
|
1267
|
+
limit: Math.max(maxTasks * 4, maxTasks + 1)
|
|
1268
|
+
});
|
|
1269
|
+
} catch (tasksErr) {
|
|
1270
|
+
const tmsg = tasksErr instanceof Error ? tasksErr.message : String(tasksErr);
|
|
1271
|
+
log7(`render-context-block: tasks unavailable (continuing): ${tmsg}`);
|
|
1272
|
+
}
|
|
1273
|
+
const visibleTasks = mergeAndDedupTasks(teamTasks, myTasks);
|
|
1274
|
+
const rulesShown = rules.slice(0, maxRules);
|
|
1275
|
+
const rulesHidden = Math.max(0, rules.length - maxRules);
|
|
1276
|
+
const tasksShown = visibleTasks.slice(0, maxTasks);
|
|
1277
|
+
const tasksHidden = Math.max(0, visibleTasks.length - maxTasks);
|
|
1278
|
+
const taskIds = tasksShown.map((t) => t.task_id);
|
|
1279
|
+
let totals = {};
|
|
1280
|
+
try {
|
|
1281
|
+
totals = await computeAllForTasks(query, input.taskEventsTable, taskIds);
|
|
1282
|
+
} catch (aggErr) {
|
|
1283
|
+
const aggMsg = aggErr instanceof Error ? aggErr.message : String(aggErr);
|
|
1284
|
+
log7(`render-context-block: aggregate failed (continuing with 0/target): ${aggMsg}`);
|
|
1285
|
+
}
|
|
1286
|
+
return formatBlock({
|
|
1287
|
+
rules: rulesShown,
|
|
1288
|
+
rulesHidden,
|
|
1289
|
+
tasks: tasksShown,
|
|
1290
|
+
tasksHidden,
|
|
1291
|
+
totals,
|
|
1292
|
+
currentUser: input.currentUser
|
|
1293
|
+
});
|
|
1294
|
+
} catch (e) {
|
|
1295
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
1296
|
+
log7(`render-context-block: ${msg}`);
|
|
1297
|
+
return "";
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
function mergeAndDedupTasks(teamTasks, myTasks) {
|
|
1301
|
+
const winner = /* @__PURE__ */ new Map();
|
|
1302
|
+
for (const t of [...teamTasks, ...myTasks]) {
|
|
1303
|
+
const prev = winner.get(t.task_id);
|
|
1304
|
+
if (!prev) {
|
|
1305
|
+
winner.set(t.task_id, t);
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
if (t.version > prev.version) {
|
|
1309
|
+
winner.set(t.task_id, t);
|
|
1310
|
+
} else if (t.version === prev.version && t.created_at > prev.created_at) {
|
|
1311
|
+
winner.set(t.task_id, t);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
const merged = [...winner.values()];
|
|
1315
|
+
merged.sort((a, b) => {
|
|
1316
|
+
const aMe = a.scope === "me" ? 0 : 1;
|
|
1317
|
+
const bMe = b.scope === "me" ? 0 : 1;
|
|
1318
|
+
if (aMe !== bMe)
|
|
1319
|
+
return aMe - bMe;
|
|
1320
|
+
return b.created_at.localeCompare(a.created_at);
|
|
1321
|
+
});
|
|
1322
|
+
return merged;
|
|
1323
|
+
}
|
|
1324
|
+
function formatBlock(input) {
|
|
1325
|
+
if (input.rules.length === 0 && input.tasks.length === 0) {
|
|
1326
|
+
return "";
|
|
1327
|
+
}
|
|
1328
|
+
const lines = [];
|
|
1329
|
+
if (input.rules.length > 0) {
|
|
1330
|
+
lines.push(`=== HIVEMIND RULES (${input.rules.length} active) ===`);
|
|
1331
|
+
for (const r of input.rules) {
|
|
1332
|
+
lines.push(`- ${r.rule_id}: ${sanitizeForInject(r.text)}`);
|
|
1333
|
+
}
|
|
1334
|
+
if (input.rulesHidden > 0) {
|
|
1335
|
+
lines.push(`(${input.rulesHidden} more \u2014 run 'hivemind rules list' to see all)`);
|
|
1336
|
+
}
|
|
1337
|
+
lines.push("");
|
|
1338
|
+
}
|
|
1339
|
+
if (input.tasks.length > 0) {
|
|
1340
|
+
lines.push(`=== HIVEMIND TASKS (${input.tasks.length} active) ===`);
|
|
1341
|
+
for (const t of input.tasks) {
|
|
1342
|
+
lines.push(formatTaskLine(t, input.totals[t.task_id] ?? {}, input.currentUser));
|
|
1343
|
+
}
|
|
1344
|
+
if (input.tasksHidden > 0) {
|
|
1345
|
+
lines.push(`(${input.tasksHidden} more \u2014 run 'hivemind tasks list' to see all)`);
|
|
1346
|
+
}
|
|
1347
|
+
lines.push("");
|
|
1348
|
+
}
|
|
1349
|
+
lines.push("=== HIVEMIND HOW-TO ===");
|
|
1350
|
+
lines.push("- Rules above are team principles. Treat any action that would violate one as a critical error and surface it to the user before proceeding.");
|
|
1351
|
+
lines.push("- Tasks above are your current work. Use 'hivemind tasks progress <task-id> <kpi-id> --value N' to record progress on a KPI.");
|
|
1352
|
+
lines.push("- Run 'hivemind rules list' / 'hivemind tasks list' for the full inventories beyond what's shown here.");
|
|
1353
|
+
return lines.join("\n");
|
|
1354
|
+
}
|
|
1355
|
+
function formatTaskLine(task, kpiTotals, currentUser) {
|
|
1356
|
+
const tag = task.scope === "team" ? "[team]" : "[me]";
|
|
1357
|
+
const highlight = task.scope === "team" && task.assigned_to === currentUser ? " \u2605YOU" : "";
|
|
1358
|
+
const kpiSummary = formatKpiSummary(task.kpis, kpiTotals);
|
|
1359
|
+
return `${tag} ${task.task_id}: ${sanitizeForInject(task.text)}${highlight}${kpiSummary}`;
|
|
1360
|
+
}
|
|
1361
|
+
function sanitizeForInject(text) {
|
|
1362
|
+
return text.replace(LINE_TERMINATOR_RE, "\\n");
|
|
1363
|
+
}
|
|
1364
|
+
var LINE_TERMINATOR_RE = /\r\n?|[\n\u2028\u2029\u0085]/g;
|
|
1365
|
+
function formatKpiSummary(kpis, totals) {
|
|
1366
|
+
if (kpis.length === 0)
|
|
1367
|
+
return "";
|
|
1368
|
+
const parts = kpis.map((k) => {
|
|
1369
|
+
const current = totals[k.kpi_id] ?? 0;
|
|
1370
|
+
return `${sanitizeForInject(k.name)}: ${current}/${k.target} ${sanitizeForInject(k.unit)}`;
|
|
1371
|
+
});
|
|
1372
|
+
return ` | ${parts.join(", ")}`;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
793
1375
|
// dist/src/cli/skillify-spec.js
|
|
794
1376
|
var SKILLIFY_COMMANDS = [
|
|
795
1377
|
{ cmd: "hivemind skillify", desc: "show scope, team, install, per-project state" },
|
|
@@ -1723,6 +2305,61 @@ async function autoPullSkills(deps = {}) {
|
|
|
1723
2305
|
}
|
|
1724
2306
|
}
|
|
1725
2307
|
|
|
2308
|
+
// dist/src/hooks/shared/goals-instructions.js
|
|
2309
|
+
var GOALS_INSTRUCTIONS_CLI = `HIVEMIND GOALS \u2014 track team goals via the \`hivemind\` CLI on this runtime. Your Write/Edit tools do NOT route to the team-shared tables here, so use these shell commands instead. All commands persist to the org-shared \`hivemind_goals\` / \`hivemind_kpis\` tables \u2014 other team members see your goals at SessionStart.
|
|
2310
|
+
|
|
2311
|
+
Commands (invoke via your Shell / terminal / Bash tool):
|
|
2312
|
+
|
|
2313
|
+
hivemind goal add "<text>"
|
|
2314
|
+
Create a new goal (status=opened, assigned to you). Prints goal_id on stdout.
|
|
2315
|
+
|
|
2316
|
+
hivemind goal list [--all|--mine]
|
|
2317
|
+
List goals. Default: --mine. Columns are tab-separated: goal_id, owner, status, first-line-of-text.
|
|
2318
|
+
|
|
2319
|
+
hivemind goal done <goal_id>
|
|
2320
|
+
Mark a goal closed.
|
|
2321
|
+
|
|
2322
|
+
hivemind goal progress <goal_id> <opened|in_progress|closed>
|
|
2323
|
+
Flip a goal to any status.
|
|
2324
|
+
|
|
2325
|
+
hivemind kpi add <goal_id> <kpi_id> <target> <unit> [name...]
|
|
2326
|
+
Add a KPI to an existing goal. <kpi_id> = short slug (e.g. k-prs).
|
|
2327
|
+
<target> = positive integer. [name] defaults to the kpi_id.
|
|
2328
|
+
|
|
2329
|
+
hivemind kpi list <goal_id>
|
|
2330
|
+
Tab-separated list of (kpi_id, first-line-of-content).
|
|
2331
|
+
|
|
2332
|
+
hivemind kpi bump <goal_id> <kpi_id> <delta>
|
|
2333
|
+
Increment (positive int) or decrement (negative) the current value of one KPI.
|
|
2334
|
+
|
|
2335
|
+
Workflow when the user expresses a goal:
|
|
2336
|
+
1. \`hivemind goal add "<short description>"\` \u2014 capture stdout as goal_id.
|
|
2337
|
+
2. ONLY if the user explicitly asks for KPIs: \`hivemind kpi add <goal_id> <slug> <target> <unit>\` per KPI.
|
|
2338
|
+
3. Tell the user the goal_id and that it is now visible to the team.
|
|
2339
|
+
|
|
2340
|
+
Do NOT use Write/Edit on \`~/.deeplake/memory/goal/...\` here \u2014 on this runtime those tool calls write to the host filesystem only, not the shared table.`;
|
|
2341
|
+
|
|
2342
|
+
// dist/src/graph/spawn-pull-worker.js
|
|
2343
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
2344
|
+
import { join as join17 } from "node:path";
|
|
2345
|
+
function spawnGraphPullWorker(cwd, bundleDir, deps = {}) {
|
|
2346
|
+
if (process.env.HIVEMIND_GRAPH_PULL === "0")
|
|
2347
|
+
return;
|
|
2348
|
+
const workerPath = join17(bundleDir, "graph-pull-worker.js");
|
|
2349
|
+
const opts = {
|
|
2350
|
+
detached: true,
|
|
2351
|
+
stdio: ["ignore", "ignore", "ignore"]
|
|
2352
|
+
};
|
|
2353
|
+
try {
|
|
2354
|
+
const sp = deps.spawn ?? spawn3;
|
|
2355
|
+
const child = sp("nohup", ["node", workerPath, "--cwd", cwd], opts);
|
|
2356
|
+
child.on("error", () => {
|
|
2357
|
+
});
|
|
2358
|
+
child.unref();
|
|
2359
|
+
} catch {
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
|
|
1726
2363
|
// dist/src/hooks/cursor/session-start.js
|
|
1727
2364
|
var log6 = (msg) => log("cursor-session-start", msg);
|
|
1728
2365
|
var __bundleDir = dirname7(fileURLToPath2(import.meta.url));
|
|
@@ -1800,17 +2437,28 @@ async function main() {
|
|
|
1800
2437
|
const current = getInstalledVersion(__bundleDir, ".claude-plugin");
|
|
1801
2438
|
const pluginVersion = current ?? "";
|
|
1802
2439
|
const captureEnabled = process.env.HIVEMIND_CAPTURE !== "false";
|
|
1803
|
-
|
|
2440
|
+
let rulesTasksBlock = "";
|
|
2441
|
+
if (creds?.token) {
|
|
1804
2442
|
try {
|
|
1805
2443
|
const config = loadConfig();
|
|
1806
2444
|
if (config) {
|
|
1807
2445
|
const table = config.tableName;
|
|
1808
2446
|
const sessionsTable = config.sessionsTableName;
|
|
1809
2447
|
const api = new DeeplakeApi(config.token, config.apiUrl, config.orgId, config.workspaceId, table);
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
2448
|
+
if (captureEnabled) {
|
|
2449
|
+
await api.ensureTable();
|
|
2450
|
+
await api.ensureSessionsTable(sessionsTable);
|
|
2451
|
+
await createPlaceholder(api, table, sessionId, cwd, config.userName, config.orgName, config.workspaceId, pluginVersion);
|
|
2452
|
+
log6("placeholder created");
|
|
2453
|
+
} else {
|
|
2454
|
+
log6("placeholder + schema ensure skipped (HIVEMIND_CAPTURE=false)");
|
|
2455
|
+
}
|
|
2456
|
+
rulesTasksBlock = await renderContextBlock((sql) => api.query(sql), {
|
|
2457
|
+
rulesTable: config.rulesTableName,
|
|
2458
|
+
tasksTable: config.tasksTableName,
|
|
2459
|
+
taskEventsTable: config.taskEventsTableName,
|
|
2460
|
+
currentUser: config.userName
|
|
2461
|
+
}, { log: log6 });
|
|
1814
2462
|
}
|
|
1815
2463
|
} catch (e) {
|
|
1816
2464
|
log6(`placeholder failed: ${e.message}`);
|
|
@@ -1825,9 +2473,17 @@ Hivemind v${current}`;
|
|
|
1825
2473
|
const localMined = countLocalManifestEntries();
|
|
1826
2474
|
const localMinedNote = localMined > 0 ? `
|
|
1827
2475
|
${localMined} local skill${localMined === 1 ? "" : "s"} from past 'hivemind skillify mine-local' run(s) live in ~/.claude/skills/. Run 'hivemind login' to start sharing new mining results with your team.` : "";
|
|
1828
|
-
|
|
2476
|
+
if (creds?.token)
|
|
2477
|
+
spawnGraphPullWorker(resolveCwd(input), __bundleDir);
|
|
2478
|
+
const baseContext = creds?.token ? `${context}
|
|
1829
2479
|
Logged in to Deeplake as org: ${creds.orgName ?? creds.orgId} (workspace: ${creds.workspaceId ?? "default"})${versionNotice}` : `${context}
|
|
1830
2480
|
Not logged in to Deeplake. Run: hivemind login${localMinedNote}${versionNotice}`;
|
|
2481
|
+
const baseWithGoals = creds?.token ? `${baseContext}
|
|
2482
|
+
|
|
2483
|
+
${GOALS_INSTRUCTIONS_CLI}` : baseContext;
|
|
2484
|
+
const additionalContext = rulesTasksBlock ? `${baseWithGoals}
|
|
2485
|
+
|
|
2486
|
+
${rulesTasksBlock}` : baseWithGoals;
|
|
1831
2487
|
console.log(JSON.stringify({ additional_context: additionalContext }));
|
|
1832
2488
|
}
|
|
1833
2489
|
main().catch((e) => {
|