@deeplake/hivemind 0.7.32 → 0.7.33
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 +304 -171
- package/codex/bundle/capture.js +365 -332
- package/codex/bundle/commands/auth-login.js +163 -30
- package/codex/bundle/pre-tool-use.js +334 -301
- package/codex/bundle/session-start-setup.js +193 -60
- package/codex/bundle/session-start.js +221 -88
- package/codex/bundle/shell/deeplake-shell.js +328 -295
- package/codex/bundle/stop.js +424 -391
- package/codex/bundle/wiki-worker.js +174 -292
- package/cursor/bundle/capture.js +420 -387
- package/cursor/bundle/commands/auth-login.js +163 -30
- package/cursor/bundle/pre-tool-use.js +324 -291
- package/cursor/bundle/session-start.js +263 -130
- package/cursor/bundle/shell/deeplake-shell.js +328 -295
- package/cursor/bundle/wiki-worker.js +174 -292
- package/hermes/bundle/capture.js +420 -387
- package/hermes/bundle/commands/auth-login.js +163 -30
- package/hermes/bundle/pre-tool-use.js +324 -291
- package/hermes/bundle/session-start.js +260 -127
- package/hermes/bundle/shell/deeplake-shell.js +328 -295
- package/hermes/bundle/wiki-worker.js +174 -292
- package/mcp/bundle/server.js +190 -57
- package/openclaw/dist/index.js +160 -32
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
|
@@ -17,21 +17,21 @@ __export(index_marker_store_exports, {
|
|
|
17
17
|
hasFreshIndexMarker: () => hasFreshIndexMarker,
|
|
18
18
|
writeIndexMarker: () => writeIndexMarker
|
|
19
19
|
});
|
|
20
|
-
import { existsSync as existsSync2, mkdirSync as
|
|
21
|
-
import { join as
|
|
20
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
21
|
+
import { join as join5 } from "node:path";
|
|
22
22
|
import { tmpdir } from "node:os";
|
|
23
23
|
function getIndexMarkerDir() {
|
|
24
|
-
return process.env.HIVEMIND_INDEX_MARKER_DIR ??
|
|
24
|
+
return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join5(tmpdir(), "hivemind-deeplake-indexes");
|
|
25
25
|
}
|
|
26
26
|
function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
|
|
27
27
|
const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
28
|
-
return
|
|
28
|
+
return join5(getIndexMarkerDir(), `${markerKey}.json`);
|
|
29
29
|
}
|
|
30
30
|
function hasFreshIndexMarker(markerPath) {
|
|
31
31
|
if (!existsSync2(markerPath))
|
|
32
32
|
return false;
|
|
33
33
|
try {
|
|
34
|
-
const raw = JSON.parse(
|
|
34
|
+
const raw = JSON.parse(readFileSync4(markerPath, "utf-8"));
|
|
35
35
|
const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
|
|
36
36
|
if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
|
|
37
37
|
return false;
|
|
@@ -41,8 +41,8 @@ function hasFreshIndexMarker(markerPath) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
function writeIndexMarker(markerPath) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
mkdirSync3(getIndexMarkerDir(), { recursive: true });
|
|
45
|
+
writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
|
|
46
46
|
}
|
|
47
47
|
var INDEX_MARKER_TTL_MS;
|
|
48
48
|
var init_index_marker_store = __esm({
|
|
@@ -337,6 +337,107 @@ function sqlIdent(name) {
|
|
|
337
337
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
338
338
|
var MESSAGE_EMBEDDING_COL = "message_embedding";
|
|
339
339
|
|
|
340
|
+
// dist/src/notifications/queue.js
|
|
341
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync, mkdirSync as mkdirSync2, openSync, closeSync, unlinkSync as unlinkSync2, statSync } from "node:fs";
|
|
342
|
+
import { join as join4, resolve } from "node:path";
|
|
343
|
+
import { homedir as homedir4 } from "node:os";
|
|
344
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
345
|
+
var log2 = (msg) => log("notifications-queue", msg);
|
|
346
|
+
var LOCK_RETRY_MAX = 50;
|
|
347
|
+
var LOCK_RETRY_BASE_MS = 5;
|
|
348
|
+
var LOCK_STALE_MS = 5e3;
|
|
349
|
+
function queuePath() {
|
|
350
|
+
return join4(homedir4(), ".deeplake", "notifications-queue.json");
|
|
351
|
+
}
|
|
352
|
+
function lockPath() {
|
|
353
|
+
return `${queuePath()}.lock`;
|
|
354
|
+
}
|
|
355
|
+
function readQueue() {
|
|
356
|
+
try {
|
|
357
|
+
const raw = readFileSync3(queuePath(), "utf-8");
|
|
358
|
+
const parsed = JSON.parse(raw);
|
|
359
|
+
if (!parsed || !Array.isArray(parsed.queue)) {
|
|
360
|
+
log2(`queue malformed \u2192 treating as empty`);
|
|
361
|
+
return { queue: [] };
|
|
362
|
+
}
|
|
363
|
+
return { queue: parsed.queue };
|
|
364
|
+
} catch {
|
|
365
|
+
return { queue: [] };
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
function _isQueuePathInsideHome(path, home) {
|
|
369
|
+
const r = resolve(path);
|
|
370
|
+
const h = resolve(home);
|
|
371
|
+
return r.startsWith(h + "/") || r === h;
|
|
372
|
+
}
|
|
373
|
+
function writeQueue(q) {
|
|
374
|
+
const path = queuePath();
|
|
375
|
+
const home = resolve(homedir4());
|
|
376
|
+
if (!_isQueuePathInsideHome(path, home)) {
|
|
377
|
+
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
|
|
378
|
+
}
|
|
379
|
+
mkdirSync2(join4(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
380
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
381
|
+
writeFileSync2(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
382
|
+
renameSync(tmp, path);
|
|
383
|
+
}
|
|
384
|
+
async function withQueueLock(fn) {
|
|
385
|
+
const path = lockPath();
|
|
386
|
+
mkdirSync2(join4(homedir4(), ".deeplake"), { recursive: true, mode: 448 });
|
|
387
|
+
let fd = null;
|
|
388
|
+
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
389
|
+
try {
|
|
390
|
+
fd = openSync(path, "wx", 384);
|
|
391
|
+
break;
|
|
392
|
+
} catch (e) {
|
|
393
|
+
const code = e.code;
|
|
394
|
+
if (code !== "EEXIST")
|
|
395
|
+
throw e;
|
|
396
|
+
try {
|
|
397
|
+
const age = Date.now() - statSync(path).mtimeMs;
|
|
398
|
+
if (age > LOCK_STALE_MS) {
|
|
399
|
+
unlinkSync2(path);
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
} catch {
|
|
403
|
+
}
|
|
404
|
+
const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
|
|
405
|
+
await sleep(delay);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (fd === null) {
|
|
409
|
+
log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
|
|
410
|
+
return fn();
|
|
411
|
+
}
|
|
412
|
+
try {
|
|
413
|
+
return fn();
|
|
414
|
+
} finally {
|
|
415
|
+
try {
|
|
416
|
+
closeSync(fd);
|
|
417
|
+
} catch {
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
unlinkSync2(path);
|
|
421
|
+
} catch {
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function sameDedupKey(a, b) {
|
|
426
|
+
if (a.id !== b.id)
|
|
427
|
+
return false;
|
|
428
|
+
return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
|
|
429
|
+
}
|
|
430
|
+
async function enqueueNotification(n) {
|
|
431
|
+
await withQueueLock(() => {
|
|
432
|
+
const q = readQueue();
|
|
433
|
+
if (q.queue.some((existing) => sameDedupKey(existing, n))) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
q.queue.push(n);
|
|
437
|
+
writeQueue(q);
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
340
441
|
// dist/src/deeplake-api.js
|
|
341
442
|
var indexMarkerStorePromise = null;
|
|
342
443
|
function getIndexMarkerStore() {
|
|
@@ -344,7 +445,7 @@ function getIndexMarkerStore() {
|
|
|
344
445
|
indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
|
|
345
446
|
return indexMarkerStorePromise;
|
|
346
447
|
}
|
|
347
|
-
var
|
|
448
|
+
var log3 = (msg) => log("sdk", msg);
|
|
348
449
|
function summarizeSql(sql, maxLen = 220) {
|
|
349
450
|
const compact = sql.replace(/\s+/g, " ").trim();
|
|
350
451
|
return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
|
|
@@ -356,7 +457,38 @@ function traceSql(msg) {
|
|
|
356
457
|
process.stderr.write(`[deeplake-sql] ${msg}
|
|
357
458
|
`);
|
|
358
459
|
if (process.env.HIVEMIND_DEBUG === "1")
|
|
359
|
-
|
|
460
|
+
log3(msg);
|
|
461
|
+
}
|
|
462
|
+
var _signalledBalanceExhausted = false;
|
|
463
|
+
function maybeSignalBalanceExhausted(status, bodyText) {
|
|
464
|
+
if (status !== 402)
|
|
465
|
+
return;
|
|
466
|
+
if (!bodyText.includes("balance_cents"))
|
|
467
|
+
return;
|
|
468
|
+
if (_signalledBalanceExhausted)
|
|
469
|
+
return;
|
|
470
|
+
_signalledBalanceExhausted = true;
|
|
471
|
+
log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
|
|
472
|
+
enqueueNotification({
|
|
473
|
+
id: "balance-exhausted",
|
|
474
|
+
severity: "warn",
|
|
475
|
+
transient: true,
|
|
476
|
+
title: "Hivemind credits exhausted \u2014 top up to keep capturing",
|
|
477
|
+
body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
|
|
478
|
+
dedupKey: { reason: "balance-zero" }
|
|
479
|
+
}).catch((e) => {
|
|
480
|
+
log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
function billingUrl() {
|
|
484
|
+
try {
|
|
485
|
+
const c = loadCredentials();
|
|
486
|
+
if (c?.orgName && c?.workspaceId) {
|
|
487
|
+
return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
|
|
488
|
+
}
|
|
489
|
+
} catch {
|
|
490
|
+
}
|
|
491
|
+
return "https://deeplake.ai";
|
|
360
492
|
}
|
|
361
493
|
var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
362
494
|
var MAX_RETRIES = 3;
|
|
@@ -365,8 +497,8 @@ var MAX_CONCURRENCY = 5;
|
|
|
365
497
|
function getQueryTimeoutMs() {
|
|
366
498
|
return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
|
|
367
499
|
}
|
|
368
|
-
function
|
|
369
|
-
return new Promise((
|
|
500
|
+
function sleep2(ms) {
|
|
501
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
370
502
|
}
|
|
371
503
|
function isTimeoutError(error) {
|
|
372
504
|
const name = error instanceof Error ? error.name.toLowerCase() : "";
|
|
@@ -396,7 +528,7 @@ var Semaphore = class {
|
|
|
396
528
|
this.active++;
|
|
397
529
|
return;
|
|
398
530
|
}
|
|
399
|
-
await new Promise((
|
|
531
|
+
await new Promise((resolve2) => this.waiting.push(resolve2));
|
|
400
532
|
}
|
|
401
533
|
release() {
|
|
402
534
|
this.active--;
|
|
@@ -467,8 +599,8 @@ var DeeplakeApi = class {
|
|
|
467
599
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
468
600
|
if (attempt < MAX_RETRIES) {
|
|
469
601
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
470
|
-
|
|
471
|
-
await
|
|
602
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
|
|
603
|
+
await sleep2(delay);
|
|
472
604
|
continue;
|
|
473
605
|
}
|
|
474
606
|
throw lastError;
|
|
@@ -484,10 +616,11 @@ var DeeplakeApi = class {
|
|
|
484
616
|
const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
|
|
485
617
|
if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
|
|
486
618
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
487
|
-
|
|
488
|
-
await
|
|
619
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
|
|
620
|
+
await sleep2(delay);
|
|
489
621
|
continue;
|
|
490
622
|
}
|
|
623
|
+
maybeSignalBalanceExhausted(resp.status, text);
|
|
491
624
|
throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
|
|
492
625
|
}
|
|
493
626
|
throw lastError ?? new Error("Query failed: max retries exceeded");
|
|
@@ -508,7 +641,7 @@ var DeeplakeApi = class {
|
|
|
508
641
|
const chunk = rows.slice(i, i + CONCURRENCY);
|
|
509
642
|
await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
|
|
510
643
|
}
|
|
511
|
-
|
|
644
|
+
log3(`commit: ${rows.length} rows`);
|
|
512
645
|
}
|
|
513
646
|
async upsertRowSql(row) {
|
|
514
647
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -564,7 +697,7 @@ var DeeplakeApi = class {
|
|
|
564
697
|
markers.writeIndexMarker(markerPath);
|
|
565
698
|
return;
|
|
566
699
|
}
|
|
567
|
-
|
|
700
|
+
log3(`index "${indexName}" skipped: ${e.message}`);
|
|
568
701
|
}
|
|
569
702
|
}
|
|
570
703
|
/**
|
|
@@ -654,13 +787,13 @@ var DeeplakeApi = class {
|
|
|
654
787
|
};
|
|
655
788
|
}
|
|
656
789
|
if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
|
|
657
|
-
await
|
|
790
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
|
|
658
791
|
continue;
|
|
659
792
|
}
|
|
660
793
|
return { tables: [], cacheable: false };
|
|
661
794
|
} catch {
|
|
662
795
|
if (attempt < MAX_RETRIES) {
|
|
663
|
-
await
|
|
796
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
|
|
664
797
|
continue;
|
|
665
798
|
}
|
|
666
799
|
return { tables: [], cacheable: false };
|
|
@@ -688,9 +821,9 @@ var DeeplakeApi = class {
|
|
|
688
821
|
} catch (err) {
|
|
689
822
|
lastErr = err;
|
|
690
823
|
const msg = err instanceof Error ? err.message : String(err);
|
|
691
|
-
|
|
824
|
+
log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
|
|
692
825
|
if (attempt < OUTER_BACKOFFS_MS.length) {
|
|
693
|
-
await
|
|
826
|
+
await sleep2(OUTER_BACKOFFS_MS[attempt]);
|
|
694
827
|
}
|
|
695
828
|
}
|
|
696
829
|
}
|
|
@@ -701,9 +834,9 @@ var DeeplakeApi = class {
|
|
|
701
834
|
const tbl = sqlIdent(name ?? this.tableName);
|
|
702
835
|
const tables = await this.listTables();
|
|
703
836
|
if (!tables.includes(tbl)) {
|
|
704
|
-
|
|
837
|
+
log3(`table "${tbl}" not found, creating`);
|
|
705
838
|
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);
|
|
706
|
-
|
|
839
|
+
log3(`table "${tbl}" created`);
|
|
707
840
|
if (!tables.includes(tbl))
|
|
708
841
|
this._tablesCache = [...tables, tbl];
|
|
709
842
|
}
|
|
@@ -716,9 +849,9 @@ var DeeplakeApi = class {
|
|
|
716
849
|
const safe = sqlIdent(name);
|
|
717
850
|
const tables = await this.listTables();
|
|
718
851
|
if (!tables.includes(safe)) {
|
|
719
|
-
|
|
852
|
+
log3(`table "${safe}" not found, creating`);
|
|
720
853
|
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);
|
|
721
|
-
|
|
854
|
+
log3(`table "${safe}" created`);
|
|
722
855
|
if (!tables.includes(safe))
|
|
723
856
|
this._tablesCache = [...tables, safe];
|
|
724
857
|
}
|
|
@@ -741,9 +874,9 @@ var DeeplakeApi = class {
|
|
|
741
874
|
const safe = sqlIdent(name);
|
|
742
875
|
const tables = await this.listTables();
|
|
743
876
|
if (!tables.includes(safe)) {
|
|
744
|
-
|
|
877
|
+
log3(`table "${safe}" not found, creating`);
|
|
745
878
|
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', name TEXT NOT NULL DEFAULT '', project TEXT NOT NULL DEFAULT '', project_key TEXT NOT NULL DEFAULT '', local_path TEXT NOT NULL DEFAULT '', install TEXT NOT NULL DEFAULT 'project', source_sessions TEXT NOT NULL DEFAULT '[]', source_agent TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'me', author TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', trigger_text TEXT NOT NULL DEFAULT '', body TEXT NOT NULL DEFAULT '', version BIGINT NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT '', updated_at TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
746
|
-
|
|
879
|
+
log3(`table "${safe}" created`);
|
|
747
880
|
if (!tables.includes(safe))
|
|
748
881
|
this._tablesCache = [...tables, safe];
|
|
749
882
|
}
|
|
@@ -774,10 +907,10 @@ function parseArgs(argv) {
|
|
|
774
907
|
}
|
|
775
908
|
function confirm(message) {
|
|
776
909
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
777
|
-
return new Promise((
|
|
910
|
+
return new Promise((resolve2) => {
|
|
778
911
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
779
912
|
rl.close();
|
|
780
|
-
|
|
913
|
+
resolve2(answer.trim().toLowerCase() === "y");
|
|
781
914
|
});
|
|
782
915
|
});
|
|
783
916
|
}
|