@deeplake/hivemind 0.7.21 → 0.7.22
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 +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/bundle/cli.js +4 -2
- package/codex/bundle/capture.js +60 -12
- package/codex/bundle/commands/auth-login.js +4 -2
- package/codex/bundle/pre-tool-use.js +4 -2
- package/codex/bundle/session-start-setup.js +52 -5
- package/codex/bundle/session-start.js +4 -2
- package/codex/bundle/shell/deeplake-shell.js +4 -2
- package/codex/bundle/stop.js +99 -51
- package/codex/bundle/wiki-worker.js +7 -3
- package/cursor/bundle/capture.js +86 -38
- package/cursor/bundle/commands/auth-login.js +4 -2
- package/cursor/bundle/pre-tool-use.js +4 -2
- package/cursor/bundle/session-end.js +77 -33
- package/cursor/bundle/session-start.js +9 -6
- package/cursor/bundle/shell/deeplake-shell.js +4 -2
- package/cursor/bundle/wiki-worker.js +7 -3
- package/hermes/bundle/capture.js +86 -38
- package/hermes/bundle/commands/auth-login.js +4 -2
- package/hermes/bundle/pre-tool-use.js +4 -2
- package/hermes/bundle/session-end.js +77 -33
- package/hermes/bundle/session-start.js +9 -6
- package/hermes/bundle/shell/deeplake-shell.js +4 -2
- package/hermes/bundle/wiki-worker.js +7 -3
- package/mcp/bundle/server.js +4 -2
- package/openclaw/dist/index.js +6 -4
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +17 -2
|
@@ -110,7 +110,7 @@ function tryAcquireLock(sessionId, maxAgeMs = 10 * 60 * 1e3) {
|
|
|
110
110
|
// dist/src/hooks/hermes/spawn-wiki-worker.js
|
|
111
111
|
import { spawn, execSync } from "node:child_process";
|
|
112
112
|
import { fileURLToPath } from "node:url";
|
|
113
|
-
import { dirname, join as
|
|
113
|
+
import { dirname as dirname2, join as join6 } from "node:path";
|
|
114
114
|
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "node:fs";
|
|
115
115
|
import { homedir as homedir4, tmpdir } from "node:os";
|
|
116
116
|
|
|
@@ -132,9 +132,51 @@ function makeWikiLogger(hooksDir, filename = "deeplake-wiki.log") {
|
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
// dist/src/utils/version-check.js
|
|
136
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
137
|
+
import { dirname, join as join5 } from "node:path";
|
|
138
|
+
function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
139
|
+
try {
|
|
140
|
+
const pluginJson = join5(bundleDir, "..", pluginManifestDir, "plugin.json");
|
|
141
|
+
const plugin = JSON.parse(readFileSync3(pluginJson, "utf-8"));
|
|
142
|
+
if (plugin.version)
|
|
143
|
+
return plugin.version;
|
|
144
|
+
} catch {
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
const stamp = readFileSync3(join5(bundleDir, "..", ".hivemind_version"), "utf-8").trim();
|
|
148
|
+
if (stamp)
|
|
149
|
+
return stamp;
|
|
150
|
+
} catch {
|
|
151
|
+
}
|
|
152
|
+
const HIVEMIND_PKG_NAMES = /* @__PURE__ */ new Set([
|
|
153
|
+
"hivemind",
|
|
154
|
+
"hivemind-codex",
|
|
155
|
+
"@deeplake/hivemind",
|
|
156
|
+
"@deeplake/hivemind-codex",
|
|
157
|
+
"@activeloop/hivemind",
|
|
158
|
+
"@activeloop/hivemind-codex"
|
|
159
|
+
]);
|
|
160
|
+
let dir = bundleDir;
|
|
161
|
+
for (let i = 0; i < 5; i++) {
|
|
162
|
+
const candidate = join5(dir, "package.json");
|
|
163
|
+
try {
|
|
164
|
+
const pkg = JSON.parse(readFileSync3(candidate, "utf-8"));
|
|
165
|
+
if (HIVEMIND_PKG_NAMES.has(pkg.name) && pkg.version)
|
|
166
|
+
return pkg.version;
|
|
167
|
+
} catch {
|
|
168
|
+
}
|
|
169
|
+
const parent = dirname(dir);
|
|
170
|
+
if (parent === dir)
|
|
171
|
+
break;
|
|
172
|
+
dir = parent;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
135
177
|
// dist/src/hooks/hermes/spawn-wiki-worker.js
|
|
136
178
|
var HOME = homedir4();
|
|
137
|
-
var wikiLogger = makeWikiLogger(
|
|
179
|
+
var wikiLogger = makeWikiLogger(join6(HOME, ".hermes", "hooks"));
|
|
138
180
|
var WIKI_LOG = wikiLogger.path;
|
|
139
181
|
var WIKI_PROMPT_TEMPLATE = `You are building a personal wiki from a coding session. Your goal is to extract every piece of knowledge \u2014 entities, decisions, relationships, and facts \u2014 into a structured, searchable wiki entry.
|
|
140
182
|
|
|
@@ -196,9 +238,10 @@ function findHermesBin() {
|
|
|
196
238
|
function spawnHermesWikiWorker(opts) {
|
|
197
239
|
const { config, sessionId, cwd, bundleDir, reason } = opts;
|
|
198
240
|
const projectName = cwd.split("/").pop() || "unknown";
|
|
199
|
-
const tmpDir =
|
|
241
|
+
const tmpDir = join6(tmpdir(), `deeplake-wiki-${sessionId}-${Date.now()}`);
|
|
200
242
|
mkdirSync3(tmpDir, { recursive: true });
|
|
201
|
-
const
|
|
243
|
+
const pluginVersion = getInstalledVersion(bundleDir, ".claude-plugin") ?? "";
|
|
244
|
+
const configFile = join6(tmpDir, "config.json");
|
|
202
245
|
writeFileSync2(configFile, JSON.stringify({
|
|
203
246
|
apiUrl: config.apiUrl,
|
|
204
247
|
token: config.token,
|
|
@@ -209,16 +252,17 @@ function spawnHermesWikiWorker(opts) {
|
|
|
209
252
|
sessionId,
|
|
210
253
|
userName: config.userName,
|
|
211
254
|
project: projectName,
|
|
255
|
+
pluginVersion,
|
|
212
256
|
tmpDir,
|
|
213
257
|
hermesBin: findHermesBin(),
|
|
214
258
|
hermesProvider: process.env.HIVEMIND_HERMES_PROVIDER ?? "openrouter",
|
|
215
259
|
hermesModel: process.env.HIVEMIND_HERMES_MODEL ?? "anthropic/claude-haiku-4-5",
|
|
216
260
|
wikiLog: WIKI_LOG,
|
|
217
|
-
hooksDir:
|
|
261
|
+
hooksDir: join6(HOME, ".hermes", "hooks"),
|
|
218
262
|
promptTemplate: WIKI_PROMPT_TEMPLATE
|
|
219
263
|
}));
|
|
220
264
|
wikiLog(`${reason}: spawning summary worker for ${sessionId}`);
|
|
221
|
-
const workerPath =
|
|
265
|
+
const workerPath = join6(bundleDir, "wiki-worker.js");
|
|
222
266
|
spawn("nohup", ["node", workerPath, configFile], {
|
|
223
267
|
detached: true,
|
|
224
268
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -226,13 +270,13 @@ function spawnHermesWikiWorker(opts) {
|
|
|
226
270
|
wikiLog(`${reason}: spawned summary worker for ${sessionId}`);
|
|
227
271
|
}
|
|
228
272
|
function bundleDirFromImportMeta(importMetaUrl) {
|
|
229
|
-
return
|
|
273
|
+
return dirname2(fileURLToPath(importMetaUrl));
|
|
230
274
|
}
|
|
231
275
|
|
|
232
276
|
// dist/src/skillify/spawn-skillify-worker.js
|
|
233
277
|
import { spawn as spawn2 } from "node:child_process";
|
|
234
278
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
235
|
-
import { dirname as
|
|
279
|
+
import { dirname as dirname3, join as join8 } from "node:path";
|
|
236
280
|
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, appendFileSync as appendFileSync3, chmodSync } from "node:fs";
|
|
237
281
|
import { homedir as homedir6, tmpdir as tmpdir2 } from "node:os";
|
|
238
282
|
|
|
@@ -240,7 +284,7 @@ import { homedir as homedir6, tmpdir as tmpdir2 } from "node:os";
|
|
|
240
284
|
import { execFileSync } from "node:child_process";
|
|
241
285
|
import { existsSync as existsSync3 } from "node:fs";
|
|
242
286
|
import { homedir as homedir5 } from "node:os";
|
|
243
|
-
import { join as
|
|
287
|
+
import { join as join7 } from "node:path";
|
|
244
288
|
function findAgentBin(agent) {
|
|
245
289
|
const which = (name) => {
|
|
246
290
|
try {
|
|
@@ -255,24 +299,24 @@ function findAgentBin(agent) {
|
|
|
255
299
|
};
|
|
256
300
|
switch (agent) {
|
|
257
301
|
case "claude_code":
|
|
258
|
-
return which("claude") ??
|
|
302
|
+
return which("claude") ?? join7(homedir5(), ".claude", "local", "claude");
|
|
259
303
|
case "codex":
|
|
260
304
|
return which("codex") ?? "/usr/local/bin/codex";
|
|
261
305
|
case "cursor":
|
|
262
306
|
return which("cursor-agent") ?? "/usr/local/bin/cursor-agent";
|
|
263
307
|
case "hermes":
|
|
264
|
-
return which("hermes") ??
|
|
308
|
+
return which("hermes") ?? join7(homedir5(), ".local", "bin", "hermes");
|
|
265
309
|
case "pi":
|
|
266
|
-
return which("pi") ??
|
|
310
|
+
return which("pi") ?? join7(homedir5(), ".local", "bin", "pi");
|
|
267
311
|
}
|
|
268
312
|
}
|
|
269
313
|
|
|
270
314
|
// dist/src/skillify/spawn-skillify-worker.js
|
|
271
315
|
var HOME2 = homedir6();
|
|
272
|
-
var SKILLIFY_LOG =
|
|
316
|
+
var SKILLIFY_LOG = join8(HOME2, ".claude", "hooks", "skillify.log");
|
|
273
317
|
function skillifyLog(msg) {
|
|
274
318
|
try {
|
|
275
|
-
mkdirSync4(
|
|
319
|
+
mkdirSync4(dirname3(SKILLIFY_LOG), { recursive: true });
|
|
276
320
|
appendFileSync3(SKILLIFY_LOG, `[${utcTimestamp()}] ${msg}
|
|
277
321
|
`);
|
|
278
322
|
} catch {
|
|
@@ -280,10 +324,10 @@ function skillifyLog(msg) {
|
|
|
280
324
|
}
|
|
281
325
|
function spawnSkillifyWorker(opts) {
|
|
282
326
|
const { config, cwd, projectKey, project, bundleDir, agent, scopeConfig, currentSessionId, reason } = opts;
|
|
283
|
-
const tmpDir =
|
|
327
|
+
const tmpDir = join8(tmpdir2(), `deeplake-skillify-${projectKey}-${Date.now()}`);
|
|
284
328
|
mkdirSync4(tmpDir, { recursive: true, mode: 448 });
|
|
285
329
|
const gateBin = findAgentBin(agent);
|
|
286
|
-
const configFile =
|
|
330
|
+
const configFile = join8(tmpDir, "config.json");
|
|
287
331
|
writeFileSync3(configFile, JSON.stringify({
|
|
288
332
|
apiUrl: config.apiUrl,
|
|
289
333
|
token: config.token,
|
|
@@ -314,7 +358,7 @@ function spawnSkillifyWorker(opts) {
|
|
|
314
358
|
} catch {
|
|
315
359
|
}
|
|
316
360
|
skillifyLog(`${reason}: spawning skillify worker for project=${project} key=${projectKey}`);
|
|
317
|
-
const workerPath =
|
|
361
|
+
const workerPath = join8(bundleDir, "skillify-worker.js");
|
|
318
362
|
spawn2("nohup", ["node", workerPath, configFile], {
|
|
319
363
|
detached: true,
|
|
320
364
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -323,25 +367,25 @@ function spawnSkillifyWorker(opts) {
|
|
|
323
367
|
}
|
|
324
368
|
|
|
325
369
|
// dist/src/skillify/state.js
|
|
326
|
-
import { readFileSync as
|
|
370
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, writeSync as writeSync2, mkdirSync as mkdirSync5, renameSync as renameSync3, existsSync as existsSync5, unlinkSync as unlinkSync2, openSync as openSync2, closeSync as closeSync2 } from "node:fs";
|
|
327
371
|
import { execSync as execSync2 } from "node:child_process";
|
|
328
372
|
import { homedir as homedir8 } from "node:os";
|
|
329
373
|
import { createHash } from "node:crypto";
|
|
330
|
-
import { join as
|
|
374
|
+
import { join as join10, basename } from "node:path";
|
|
331
375
|
|
|
332
376
|
// dist/src/skillify/legacy-migration.js
|
|
333
377
|
import { existsSync as existsSync4, renameSync as renameSync2 } from "node:fs";
|
|
334
378
|
import { homedir as homedir7 } from "node:os";
|
|
335
|
-
import { join as
|
|
379
|
+
import { join as join9 } from "node:path";
|
|
336
380
|
var dlog2 = (msg) => log("skillify-migrate", msg);
|
|
337
381
|
var attempted = false;
|
|
338
382
|
function migrateLegacyStateDir() {
|
|
339
383
|
if (attempted)
|
|
340
384
|
return;
|
|
341
385
|
attempted = true;
|
|
342
|
-
const root =
|
|
343
|
-
const legacy =
|
|
344
|
-
const current =
|
|
386
|
+
const root = join9(homedir7(), ".deeplake", "state");
|
|
387
|
+
const legacy = join9(root, "skilify");
|
|
388
|
+
const current = join9(root, "skillify");
|
|
345
389
|
if (!existsSync4(legacy))
|
|
346
390
|
return;
|
|
347
391
|
if (existsSync4(current))
|
|
@@ -361,17 +405,17 @@ function migrateLegacyStateDir() {
|
|
|
361
405
|
|
|
362
406
|
// dist/src/skillify/state.js
|
|
363
407
|
var dlog3 = (msg) => log("skillify-state", msg);
|
|
364
|
-
var STATE_DIR2 =
|
|
408
|
+
var STATE_DIR2 = join10(homedir8(), ".deeplake", "state", "skillify");
|
|
365
409
|
var YIELD_BUF2 = new Int32Array(new SharedArrayBuffer(4));
|
|
366
410
|
var TRIGGER_THRESHOLD = (() => {
|
|
367
411
|
const n = Number(process.env.HIVEMIND_SKILLIFY_EVERY_N_TURNS ?? "");
|
|
368
412
|
return Number.isInteger(n) && n > 0 ? n : 20;
|
|
369
413
|
})();
|
|
370
414
|
function statePath(projectKey) {
|
|
371
|
-
return
|
|
415
|
+
return join10(STATE_DIR2, `${projectKey}.json`);
|
|
372
416
|
}
|
|
373
417
|
function lockPath2(projectKey) {
|
|
374
|
-
return
|
|
418
|
+
return join10(STATE_DIR2, `${projectKey}.lock`);
|
|
375
419
|
}
|
|
376
420
|
var DEFAULT_PORTS = {
|
|
377
421
|
http: "80",
|
|
@@ -420,7 +464,7 @@ function readState(projectKey) {
|
|
|
420
464
|
if (!existsSync5(p))
|
|
421
465
|
return null;
|
|
422
466
|
try {
|
|
423
|
-
return JSON.parse(
|
|
467
|
+
return JSON.parse(readFileSync4(p, "utf-8"));
|
|
424
468
|
} catch {
|
|
425
469
|
return null;
|
|
426
470
|
}
|
|
@@ -482,7 +526,7 @@ function tryAcquireWorkerLock(projectKey, maxAgeMs = 10 * 60 * 1e3) {
|
|
|
482
526
|
const p = lockPath2(projectKey);
|
|
483
527
|
if (existsSync5(p)) {
|
|
484
528
|
try {
|
|
485
|
-
const ageMs = Date.now() - parseInt(
|
|
529
|
+
const ageMs = Date.now() - parseInt(readFileSync4(p, "utf-8"), 10);
|
|
486
530
|
if (Number.isFinite(ageMs) && ageMs < maxAgeMs)
|
|
487
531
|
return false;
|
|
488
532
|
} catch (readErr) {
|
|
@@ -516,18 +560,18 @@ function releaseWorkerLock(projectKey) {
|
|
|
516
560
|
}
|
|
517
561
|
|
|
518
562
|
// dist/src/skillify/scope-config.js
|
|
519
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as
|
|
563
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
520
564
|
import { homedir as homedir9 } from "node:os";
|
|
521
|
-
import { join as
|
|
522
|
-
var STATE_DIR3 =
|
|
523
|
-
var CONFIG_PATH =
|
|
565
|
+
import { join as join11 } from "node:path";
|
|
566
|
+
var STATE_DIR3 = join11(homedir9(), ".deeplake", "state", "skillify");
|
|
567
|
+
var CONFIG_PATH = join11(STATE_DIR3, "config.json");
|
|
524
568
|
var DEFAULT = { scope: "me", team: [], install: "project" };
|
|
525
569
|
function loadScopeConfig() {
|
|
526
570
|
migrateLegacyStateDir();
|
|
527
571
|
if (!existsSync6(CONFIG_PATH))
|
|
528
572
|
return DEFAULT;
|
|
529
573
|
try {
|
|
530
|
-
const raw = JSON.parse(
|
|
574
|
+
const raw = JSON.parse(readFileSync5(CONFIG_PATH, "utf-8"));
|
|
531
575
|
const scope = raw.scope === "team" || raw.scope === "org" ? raw.scope : "me";
|
|
532
576
|
const team = Array.isArray(raw.team) ? raw.team.filter((s) => typeof s === "string") : [];
|
|
533
577
|
const install = raw.install === "global" ? "global" : "project";
|
|
@@ -511,13 +511,14 @@ var DeeplakeApi = class {
|
|
|
511
511
|
const tables = await this.listTables();
|
|
512
512
|
if (!tables.includes(tbl)) {
|
|
513
513
|
log2(`table "${tbl}" not found, creating`);
|
|
514
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
|
|
514
|
+
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
|
|
515
515
|
log2(`table "${tbl}" created`);
|
|
516
516
|
if (!tables.includes(tbl))
|
|
517
517
|
this._tablesCache = [...tables, tbl];
|
|
518
518
|
}
|
|
519
519
|
await this.ensureEmbeddingColumn(tbl, SUMMARY_EMBEDDING_COL);
|
|
520
520
|
await this.ensureColumn(tbl, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
521
|
+
await this.ensureColumn(tbl, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
521
522
|
}
|
|
522
523
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
523
524
|
async ensureSessionsTable(name) {
|
|
@@ -525,13 +526,14 @@ var DeeplakeApi = class {
|
|
|
525
526
|
const tables = await this.listTables();
|
|
526
527
|
if (!tables.includes(safe)) {
|
|
527
528
|
log2(`table "${safe}" not found, creating`);
|
|
528
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
529
|
+
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
529
530
|
log2(`table "${safe}" created`);
|
|
530
531
|
if (!tables.includes(safe))
|
|
531
532
|
this._tablesCache = [...tables, safe];
|
|
532
533
|
}
|
|
533
534
|
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
534
535
|
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
536
|
+
await this.ensureColumn(safe, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
535
537
|
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
536
538
|
}
|
|
537
539
|
/**
|
|
@@ -1315,7 +1317,7 @@ SKILLS (skillify) \u2014 mine + share reusable skills across the org:
|
|
|
1315
1317
|
- hivemind skillify scope <me|team|org> \u2014 sharing scope for new skills
|
|
1316
1318
|
- hivemind skillify install <project|global> \u2014 default install location
|
|
1317
1319
|
- hivemind skillify team add|remove|list <name> \u2014 manage team list`;
|
|
1318
|
-
async function createPlaceholder(api, table, sessionId, cwd, userName, orgName, workspaceId) {
|
|
1320
|
+
async function createPlaceholder(api, table, sessionId, cwd, userName, orgName, workspaceId, pluginVersion) {
|
|
1319
1321
|
const summaryPath = `/summaries/${userName}/${sessionId}.md`;
|
|
1320
1322
|
const existing = await api.query(`SELECT path FROM "${table}" WHERE path = '${sqlStr(summaryPath)}' LIMIT 1`);
|
|
1321
1323
|
if (existing.length > 0)
|
|
@@ -1332,7 +1334,7 @@ async function createPlaceholder(api, table, sessionId, cwd, userName, orgName,
|
|
|
1332
1334
|
""
|
|
1333
1335
|
].join("\n");
|
|
1334
1336
|
const filename = `${sessionId}.md`;
|
|
1335
|
-
await api.query(`INSERT INTO "${table}" (id, path, filename, summary, author, mime_type, size_bytes, project, description, agent, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(summaryPath)}', '${sqlStr(filename)}', E'${sqlStr(content)}', '${sqlStr(userName)}', 'text/markdown', ${Buffer.byteLength(content, "utf-8")}, '${sqlStr(projectName)}', 'in progress', 'hermes', '${now}', '${now}')`);
|
|
1337
|
+
await api.query(`INSERT INTO "${table}" (id, path, filename, summary, author, mime_type, size_bytes, project, description, agent, plugin_version, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(summaryPath)}', '${sqlStr(filename)}', E'${sqlStr(content)}', '${sqlStr(userName)}', 'text/markdown', ${Buffer.byteLength(content, "utf-8")}, '${sqlStr(projectName)}', 'in progress', 'hermes', '${sqlStr(pluginVersion)}', '${now}', '${now}')`);
|
|
1336
1338
|
}
|
|
1337
1339
|
async function main() {
|
|
1338
1340
|
if (process.env.HIVEMIND_WIKI_WORKER === "1")
|
|
@@ -1343,6 +1345,8 @@ async function main() {
|
|
|
1343
1345
|
const creds = loadCredentials();
|
|
1344
1346
|
const captureEnabled = process.env.HIVEMIND_CAPTURE !== "false";
|
|
1345
1347
|
await autoUpdate(creds, { agent: "hermes" });
|
|
1348
|
+
const current = getInstalledVersion(__bundleDir, ".claude-plugin");
|
|
1349
|
+
const pluginVersion = current ?? "";
|
|
1346
1350
|
if (creds?.token && captureEnabled) {
|
|
1347
1351
|
try {
|
|
1348
1352
|
const config = loadConfig();
|
|
@@ -1350,7 +1354,7 @@ async function main() {
|
|
|
1350
1354
|
const api = new DeeplakeApi(config.token, config.apiUrl, config.orgId, config.workspaceId, config.tableName);
|
|
1351
1355
|
await api.ensureTable();
|
|
1352
1356
|
await api.ensureSessionsTable(config.sessionsTableName);
|
|
1353
|
-
await createPlaceholder(api, config.tableName, sessionId, cwd, config.userName, config.orgName, config.workspaceId);
|
|
1357
|
+
await createPlaceholder(api, config.tableName, sessionId, cwd, config.userName, config.orgName, config.workspaceId, pluginVersion);
|
|
1354
1358
|
log5("placeholder created");
|
|
1355
1359
|
}
|
|
1356
1360
|
} catch (e) {
|
|
@@ -1360,7 +1364,6 @@ async function main() {
|
|
|
1360
1364
|
const pullResult = await autoPullSkills();
|
|
1361
1365
|
log5(`autopull: pulled=${pullResult.pulled} skipped=${pullResult.skipped}`);
|
|
1362
1366
|
let versionNotice = "";
|
|
1363
|
-
const current = getInstalledVersion(__bundleDir, ".claude-plugin");
|
|
1364
1367
|
if (current)
|
|
1365
1368
|
versionNotice = `
|
|
1366
1369
|
Hivemind v${current}`;
|
|
@@ -67201,13 +67201,14 @@ var DeeplakeApi = class {
|
|
|
67201
67201
|
const tables = await this.listTables();
|
|
67202
67202
|
if (!tables.includes(tbl)) {
|
|
67203
67203
|
log2(`table "${tbl}" not found, creating`);
|
|
67204
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
|
|
67204
|
+
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
|
|
67205
67205
|
log2(`table "${tbl}" created`);
|
|
67206
67206
|
if (!tables.includes(tbl))
|
|
67207
67207
|
this._tablesCache = [...tables, tbl];
|
|
67208
67208
|
}
|
|
67209
67209
|
await this.ensureEmbeddingColumn(tbl, SUMMARY_EMBEDDING_COL);
|
|
67210
67210
|
await this.ensureColumn(tbl, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
67211
|
+
await this.ensureColumn(tbl, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
67211
67212
|
}
|
|
67212
67213
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
67213
67214
|
async ensureSessionsTable(name) {
|
|
@@ -67215,13 +67216,14 @@ var DeeplakeApi = class {
|
|
|
67215
67216
|
const tables = await this.listTables();
|
|
67216
67217
|
if (!tables.includes(safe)) {
|
|
67217
67218
|
log2(`table "${safe}" not found, creating`);
|
|
67218
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
67219
|
+
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
67219
67220
|
log2(`table "${safe}" created`);
|
|
67220
67221
|
if (!tables.includes(safe))
|
|
67221
67222
|
this._tablesCache = [...tables, safe];
|
|
67222
67223
|
}
|
|
67223
67224
|
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
67224
67225
|
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
67226
|
+
await this.ensureColumn(safe, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
67225
67227
|
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
67226
67228
|
}
|
|
67227
67229
|
/**
|
|
@@ -135,13 +135,16 @@ async function uploadSummary(query2, params) {
|
|
|
135
135
|
const desc = extractDescription(text);
|
|
136
136
|
const sizeBytes = Buffer.byteLength(text);
|
|
137
137
|
const embSql = embeddingSqlLiteral(params.embedding ?? null);
|
|
138
|
+
const pluginVersion = params.pluginVersion;
|
|
138
139
|
const existing = await query2(`SELECT path FROM "${tableName}" WHERE path = '${esc(vpath)}' LIMIT 1`);
|
|
139
140
|
if (existing.length > 0) {
|
|
140
|
-
const
|
|
141
|
+
const pluginVersionSet = pluginVersion === void 0 ? "" : `plugin_version = '${esc(pluginVersion)}', `;
|
|
142
|
+
const sql2 = `UPDATE "${tableName}" SET summary = E'${esc(text)}', summary_embedding = ${embSql}, size_bytes = ${sizeBytes}, description = E'${esc(desc)}', ` + pluginVersionSet + `last_update_date = '${ts}' WHERE path = '${esc(vpath)}'`;
|
|
141
143
|
await query2(sql2);
|
|
142
144
|
return { path: "update", sql: sql2, descLength: desc.length, summaryLength: text.length };
|
|
143
145
|
}
|
|
144
|
-
const
|
|
146
|
+
const pluginVersionForInsert = pluginVersion ?? "";
|
|
147
|
+
const sql = `INSERT INTO "${tableName}" (id, path, filename, summary, summary_embedding, author, mime_type, size_bytes, project, description, agent, plugin_version, creation_date, last_update_date) VALUES ('${randomUUID()}', '${esc(vpath)}', '${esc(fname)}', E'${esc(text)}', ${embSql}, '${esc(userName)}', 'text/markdown', ${sizeBytes}, '${esc(project)}', E'${esc(desc)}', '${esc(agent)}', '${esc(pluginVersionForInsert)}', '${ts}', '${ts}')`;
|
|
145
148
|
await query2(sql);
|
|
146
149
|
return { path: "insert", sql, descLength: desc.length, summaryLength: text.length };
|
|
147
150
|
}
|
|
@@ -544,7 +547,8 @@ async function main() {
|
|
|
544
547
|
agent: "hermes",
|
|
545
548
|
sessionId: cfg.sessionId,
|
|
546
549
|
text,
|
|
547
|
-
embedding
|
|
550
|
+
embedding,
|
|
551
|
+
pluginVersion: cfg.pluginVersion ?? ""
|
|
548
552
|
});
|
|
549
553
|
wlog(`uploaded ${vpath} (summary=${result.summaryLength}, desc=${result.descLength})`);
|
|
550
554
|
try {
|
package/mcp/bundle/server.js
CHANGED
|
@@ -23724,13 +23724,14 @@ var DeeplakeApi = class {
|
|
|
23724
23724
|
const tables = await this.listTables();
|
|
23725
23725
|
if (!tables.includes(tbl)) {
|
|
23726
23726
|
log2(`table "${tbl}" not found, creating`);
|
|
23727
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
|
|
23727
|
+
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
|
|
23728
23728
|
log2(`table "${tbl}" created`);
|
|
23729
23729
|
if (!tables.includes(tbl))
|
|
23730
23730
|
this._tablesCache = [...tables, tbl];
|
|
23731
23731
|
}
|
|
23732
23732
|
await this.ensureEmbeddingColumn(tbl, SUMMARY_EMBEDDING_COL);
|
|
23733
23733
|
await this.ensureColumn(tbl, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
23734
|
+
await this.ensureColumn(tbl, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
23734
23735
|
}
|
|
23735
23736
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
23736
23737
|
async ensureSessionsTable(name) {
|
|
@@ -23738,13 +23739,14 @@ var DeeplakeApi = class {
|
|
|
23738
23739
|
const tables = await this.listTables();
|
|
23739
23740
|
if (!tables.includes(safe)) {
|
|
23740
23741
|
log2(`table "${safe}" not found, creating`);
|
|
23741
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
23742
|
+
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
23742
23743
|
log2(`table "${safe}" created`);
|
|
23743
23744
|
if (!tables.includes(safe))
|
|
23744
23745
|
this._tablesCache = [...tables, safe];
|
|
23745
23746
|
}
|
|
23746
23747
|
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
23747
23748
|
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
23749
|
+
await this.ensureColumn(safe, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
23748
23750
|
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
23749
23751
|
}
|
|
23750
23752
|
/**
|
package/openclaw/dist/index.js
CHANGED
|
@@ -461,7 +461,7 @@ var DeeplakeApi = class {
|
|
|
461
461
|
if (!tables.includes(tbl)) {
|
|
462
462
|
log2(`table "${tbl}" not found, creating`);
|
|
463
463
|
await this.createTableWithRetry(
|
|
464
|
-
`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`,
|
|
464
|
+
`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`,
|
|
465
465
|
tbl
|
|
466
466
|
);
|
|
467
467
|
log2(`table "${tbl}" created`);
|
|
@@ -469,6 +469,7 @@ var DeeplakeApi = class {
|
|
|
469
469
|
}
|
|
470
470
|
await this.ensureEmbeddingColumn(tbl, SUMMARY_EMBEDDING_COL);
|
|
471
471
|
await this.ensureColumn(tbl, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
472
|
+
await this.ensureColumn(tbl, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
472
473
|
}
|
|
473
474
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
474
475
|
async ensureSessionsTable(name) {
|
|
@@ -477,7 +478,7 @@ var DeeplakeApi = class {
|
|
|
477
478
|
if (!tables.includes(safe)) {
|
|
478
479
|
log2(`table "${safe}" not found, creating`);
|
|
479
480
|
await this.createTableWithRetry(
|
|
480
|
-
`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`,
|
|
481
|
+
`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`,
|
|
481
482
|
safe
|
|
482
483
|
);
|
|
483
484
|
log2(`table "${safe}" created`);
|
|
@@ -485,6 +486,7 @@ var DeeplakeApi = class {
|
|
|
485
486
|
}
|
|
486
487
|
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
487
488
|
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
489
|
+
await this.ensureColumn(safe, "plugin_version", "TEXT NOT NULL DEFAULT ''");
|
|
488
490
|
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
489
491
|
}
|
|
490
492
|
/**
|
|
@@ -1071,7 +1073,7 @@ function extractLatestVersion(body) {
|
|
|
1071
1073
|
return typeof v === "string" && v.length > 0 ? v : null;
|
|
1072
1074
|
}
|
|
1073
1075
|
function getInstalledVersion() {
|
|
1074
|
-
return "0.7.
|
|
1076
|
+
return "0.7.22".length > 0 ? "0.7.22" : null;
|
|
1075
1077
|
}
|
|
1076
1078
|
function isNewer(latest, current) {
|
|
1077
1079
|
const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
|
|
@@ -1879,7 +1881,7 @@ One brain for every agent on your team.
|
|
|
1879
1881
|
};
|
|
1880
1882
|
const line = JSON.stringify(entry);
|
|
1881
1883
|
const jsonForSql = line.replace(/'/g, "''");
|
|
1882
|
-
const insertSql = `INSERT INTO "${sessionsTable}" (id, path, filename, message, author, size_bytes, project, description, agent, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(sessionPath)}', '${sqlStr(filename)}', '${jsonForSql}'::jsonb, '${sqlStr(cfg.userName)}', ${Buffer.byteLength(line, "utf-8")}, '${sqlStr(projectName)}', '${sqlStr(msg.role)}', 'openclaw', '${ts}', '${ts}')`;
|
|
1884
|
+
const insertSql = `INSERT INTO "${sessionsTable}" (id, path, filename, message, author, size_bytes, project, description, agent, plugin_version, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(sessionPath)}', '${sqlStr(filename)}', '${jsonForSql}'::jsonb, '${sqlStr(cfg.userName)}', ${Buffer.byteLength(line, "utf-8")}, '${sqlStr(projectName)}', '${sqlStr(msg.role)}', 'openclaw', '${sqlStr(getInstalledVersion() ?? "")}', '${ts}', '${ts}')`;
|
|
1883
1885
|
try {
|
|
1884
1886
|
await dl.query(insertSql);
|
|
1885
1887
|
} catch (e) {
|
package/openclaw/package.json
CHANGED
package/package.json
CHANGED
|
@@ -94,6 +94,20 @@ function loadCreds(): Creds | null {
|
|
|
94
94
|
const MEMORY_TABLE = process.env.HIVEMIND_TABLE ?? "memory";
|
|
95
95
|
const SESSIONS_TABLE = process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions";
|
|
96
96
|
|
|
97
|
+
// Read the hivemind version stamped by `hivemind pi install` into
|
|
98
|
+
// ~/.pi/agent/.hivemind/.hivemind_version. The installer writes this
|
|
99
|
+
// at install time (see src/cli/install-pi.ts), so by the time this
|
|
100
|
+
// extension loads the file should be present. Resolved once and reused
|
|
101
|
+
// — the version doesn't change for the lifetime of a pi process.
|
|
102
|
+
const PLUGIN_VERSION: string = (() => {
|
|
103
|
+
try {
|
|
104
|
+
const stamp = readFileSync(join(homedir(), ".pi", "agent", ".hivemind", ".hivemind_version"), "utf-8").trim();
|
|
105
|
+
return stamp || "";
|
|
106
|
+
} catch {
|
|
107
|
+
return "";
|
|
108
|
+
}
|
|
109
|
+
})();
|
|
110
|
+
|
|
97
111
|
// ---------- SQL escape (matches src/utils/sql.ts) ------------------------------
|
|
98
112
|
|
|
99
113
|
function sqlStr(value: string): string {
|
|
@@ -422,6 +436,7 @@ function spawnWikiWorker(
|
|
|
422
436
|
sessionId,
|
|
423
437
|
userName: creds.userName,
|
|
424
438
|
project,
|
|
439
|
+
pluginVersion: PLUGIN_VERSION,
|
|
425
440
|
tmpDir,
|
|
426
441
|
piBin: findPiBin(),
|
|
427
442
|
piProvider: process.env.HIVEMIND_PI_PROVIDER ?? "google",
|
|
@@ -626,9 +641,9 @@ async function writeSessionRow(
|
|
|
626
641
|
const emb = await embed(line);
|
|
627
642
|
logHm(`writeSessionRow: embed=${emb ? `dims=${emb.length}` : "null"}`);
|
|
628
643
|
const insertSql =
|
|
629
|
-
`INSERT INTO "${SESSIONS_TABLE}" (id, path, filename, message, message_embedding, author, size_bytes, project, description, agent, creation_date, last_update_date) ` +
|
|
644
|
+
`INSERT INTO "${SESSIONS_TABLE}" (id, path, filename, message, message_embedding, author, size_bytes, project, description, agent, plugin_version, creation_date, last_update_date) ` +
|
|
630
645
|
`VALUES ('${crypto.randomUUID()}', '${sqlStr(sessionPath)}', '${sqlStr(filename)}', '${jsonForSql}'::jsonb, ${embedSqlLiteral(emb)}, '${sqlStr(creds.userName)}', ` +
|
|
631
|
-
`${Buffer.byteLength(line, "utf-8")}, '${sqlStr(projectName)}', '${sqlStr(event)}', '${agent}', '${ts}', '${ts}')`;
|
|
646
|
+
`${Buffer.byteLength(line, "utf-8")}, '${sqlStr(projectName)}', '${sqlStr(event)}', '${agent}', '${sqlStr(PLUGIN_VERSION)}', '${ts}', '${ts}')`;
|
|
632
647
|
let lastErr: any = null;
|
|
633
648
|
for (let attempt = 0; attempt <= INSERT_RETRY_BACKOFFS_MS.length; attempt++) {
|
|
634
649
|
try {
|