@deeplake/hivemind 0.7.31 → 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 +594 -267
- package/codex/bundle/capture.js +585 -124
- package/codex/bundle/commands/auth-login.js +163 -30
- package/codex/bundle/embeddings/embed-daemon.js +55 -4
- package/codex/bundle/pre-tool-use.js +475 -85
- package/codex/bundle/session-start-setup.js +193 -60
- package/codex/bundle/session-start.js +221 -88
- package/codex/bundle/shell/deeplake-shell.js +458 -68
- package/codex/bundle/stop.js +565 -175
- package/codex/bundle/wiki-worker.js +258 -19
- package/cursor/bundle/capture.js +660 -199
- package/cursor/bundle/commands/auth-login.js +163 -30
- package/cursor/bundle/embeddings/embed-daemon.js +55 -4
- package/cursor/bundle/pre-tool-use.js +460 -70
- package/cursor/bundle/session-start.js +271 -131
- package/cursor/bundle/shell/deeplake-shell.js +458 -68
- package/cursor/bundle/wiki-worker.js +258 -19
- package/hermes/bundle/capture.js +661 -200
- package/hermes/bundle/commands/auth-login.js +163 -30
- package/hermes/bundle/embeddings/embed-daemon.js +55 -4
- package/hermes/bundle/pre-tool-use.js +459 -69
- package/hermes/bundle/session-start.js +268 -128
- package/hermes/bundle/shell/deeplake-shell.js +458 -68
- package/hermes/bundle/wiki-worker.js +258 -19
- 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
|
@@ -16,21 +16,21 @@ __export(index_marker_store_exports, {
|
|
|
16
16
|
hasFreshIndexMarker: () => hasFreshIndexMarker,
|
|
17
17
|
writeIndexMarker: () => writeIndexMarker
|
|
18
18
|
});
|
|
19
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync as
|
|
20
|
-
import { join as
|
|
19
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
20
|
+
import { join as join5 } from "node:path";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
22
|
function getIndexMarkerDir() {
|
|
23
|
-
return process.env.HIVEMIND_INDEX_MARKER_DIR ??
|
|
23
|
+
return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join5(tmpdir(), "hivemind-deeplake-indexes");
|
|
24
24
|
}
|
|
25
25
|
function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
|
|
26
26
|
const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
27
|
-
return
|
|
27
|
+
return join5(getIndexMarkerDir(), `${markerKey}.json`);
|
|
28
28
|
}
|
|
29
29
|
function hasFreshIndexMarker(markerPath) {
|
|
30
30
|
if (!existsSync2(markerPath))
|
|
31
31
|
return false;
|
|
32
32
|
try {
|
|
33
|
-
const raw = JSON.parse(
|
|
33
|
+
const raw = JSON.parse(readFileSync4(markerPath, "utf-8"));
|
|
34
34
|
const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
|
|
35
35
|
if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
|
|
36
36
|
return false;
|
|
@@ -40,8 +40,8 @@ function hasFreshIndexMarker(markerPath) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function writeIndexMarker(markerPath) {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
mkdirSync3(getIndexMarkerDir(), { recursive: true });
|
|
44
|
+
writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
|
|
45
45
|
}
|
|
46
46
|
var INDEX_MARKER_TTL_MS;
|
|
47
47
|
var init_index_marker_store = __esm({
|
|
@@ -53,13 +53,13 @@ var init_index_marker_store = __esm({
|
|
|
53
53
|
|
|
54
54
|
// dist/src/utils/stdin.js
|
|
55
55
|
function readStdin() {
|
|
56
|
-
return new Promise((
|
|
56
|
+
return new Promise((resolve2, reject) => {
|
|
57
57
|
let data = "";
|
|
58
58
|
process.stdin.setEncoding("utf-8");
|
|
59
59
|
process.stdin.on("data", (chunk) => data += chunk);
|
|
60
60
|
process.stdin.on("end", () => {
|
|
61
61
|
try {
|
|
62
|
-
|
|
62
|
+
resolve2(JSON.parse(data));
|
|
63
63
|
} catch (err) {
|
|
64
64
|
reject(new Error(`Failed to parse hook input: ${err}`));
|
|
65
65
|
}
|
|
@@ -146,6 +146,125 @@ function deeplakeClientHeader() {
|
|
|
146
146
|
return { [DEEPLAKE_CLIENT_HEADER]: deeplakeClientValue() };
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
// dist/src/notifications/queue.js
|
|
150
|
+
import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
151
|
+
import { join as join3, resolve } from "node:path";
|
|
152
|
+
import { homedir as homedir3 } from "node:os";
|
|
153
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
154
|
+
var log2 = (msg) => log("notifications-queue", msg);
|
|
155
|
+
var LOCK_RETRY_MAX = 50;
|
|
156
|
+
var LOCK_RETRY_BASE_MS = 5;
|
|
157
|
+
var LOCK_STALE_MS = 5e3;
|
|
158
|
+
function queuePath() {
|
|
159
|
+
return join3(homedir3(), ".deeplake", "notifications-queue.json");
|
|
160
|
+
}
|
|
161
|
+
function lockPath() {
|
|
162
|
+
return `${queuePath()}.lock`;
|
|
163
|
+
}
|
|
164
|
+
function readQueue() {
|
|
165
|
+
try {
|
|
166
|
+
const raw = readFileSync2(queuePath(), "utf-8");
|
|
167
|
+
const parsed = JSON.parse(raw);
|
|
168
|
+
if (!parsed || !Array.isArray(parsed.queue)) {
|
|
169
|
+
log2(`queue malformed \u2192 treating as empty`);
|
|
170
|
+
return { queue: [] };
|
|
171
|
+
}
|
|
172
|
+
return { queue: parsed.queue };
|
|
173
|
+
} catch {
|
|
174
|
+
return { queue: [] };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function _isQueuePathInsideHome(path, home) {
|
|
178
|
+
const r = resolve(path);
|
|
179
|
+
const h = resolve(home);
|
|
180
|
+
return r.startsWith(h + "/") || r === h;
|
|
181
|
+
}
|
|
182
|
+
function writeQueue(q) {
|
|
183
|
+
const path = queuePath();
|
|
184
|
+
const home = resolve(homedir3());
|
|
185
|
+
if (!_isQueuePathInsideHome(path, home)) {
|
|
186
|
+
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
|
|
187
|
+
}
|
|
188
|
+
mkdirSync(join3(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
189
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
190
|
+
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
191
|
+
renameSync(tmp, path);
|
|
192
|
+
}
|
|
193
|
+
async function withQueueLock(fn) {
|
|
194
|
+
const path = lockPath();
|
|
195
|
+
mkdirSync(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
|
|
196
|
+
let fd = null;
|
|
197
|
+
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
198
|
+
try {
|
|
199
|
+
fd = openSync(path, "wx", 384);
|
|
200
|
+
break;
|
|
201
|
+
} catch (e) {
|
|
202
|
+
const code = e.code;
|
|
203
|
+
if (code !== "EEXIST")
|
|
204
|
+
throw e;
|
|
205
|
+
try {
|
|
206
|
+
const age = Date.now() - statSync(path).mtimeMs;
|
|
207
|
+
if (age > LOCK_STALE_MS) {
|
|
208
|
+
unlinkSync(path);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
} catch {
|
|
212
|
+
}
|
|
213
|
+
const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
|
|
214
|
+
await sleep(delay);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (fd === null) {
|
|
218
|
+
log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
|
|
219
|
+
return fn();
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
return fn();
|
|
223
|
+
} finally {
|
|
224
|
+
try {
|
|
225
|
+
closeSync(fd);
|
|
226
|
+
} catch {
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
unlinkSync(path);
|
|
230
|
+
} catch {
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function sameDedupKey(a, b) {
|
|
235
|
+
if (a.id !== b.id)
|
|
236
|
+
return false;
|
|
237
|
+
return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
|
|
238
|
+
}
|
|
239
|
+
async function enqueueNotification(n) {
|
|
240
|
+
await withQueueLock(() => {
|
|
241
|
+
const q = readQueue();
|
|
242
|
+
if (q.queue.some((existing) => sameDedupKey(existing, n))) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
q.queue.push(n);
|
|
246
|
+
writeQueue(q);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// dist/src/commands/auth-creds.js
|
|
251
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
252
|
+
import { join as join4 } from "node:path";
|
|
253
|
+
import { homedir as homedir4 } from "node:os";
|
|
254
|
+
function configDir() {
|
|
255
|
+
return join4(homedir4(), ".deeplake");
|
|
256
|
+
}
|
|
257
|
+
function credsPath() {
|
|
258
|
+
return join4(configDir(), "credentials.json");
|
|
259
|
+
}
|
|
260
|
+
function loadCredentials() {
|
|
261
|
+
try {
|
|
262
|
+
return JSON.parse(readFileSync3(credsPath(), "utf-8"));
|
|
263
|
+
} catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
149
268
|
// dist/src/deeplake-api.js
|
|
150
269
|
var indexMarkerStorePromise = null;
|
|
151
270
|
function getIndexMarkerStore() {
|
|
@@ -153,7 +272,7 @@ function getIndexMarkerStore() {
|
|
|
153
272
|
indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
|
|
154
273
|
return indexMarkerStorePromise;
|
|
155
274
|
}
|
|
156
|
-
var
|
|
275
|
+
var log3 = (msg) => log("sdk", msg);
|
|
157
276
|
function summarizeSql(sql, maxLen = 220) {
|
|
158
277
|
const compact = sql.replace(/\s+/g, " ").trim();
|
|
159
278
|
return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
|
|
@@ -165,7 +284,38 @@ function traceSql(msg) {
|
|
|
165
284
|
process.stderr.write(`[deeplake-sql] ${msg}
|
|
166
285
|
`);
|
|
167
286
|
if (process.env.HIVEMIND_DEBUG === "1")
|
|
168
|
-
|
|
287
|
+
log3(msg);
|
|
288
|
+
}
|
|
289
|
+
var _signalledBalanceExhausted = false;
|
|
290
|
+
function maybeSignalBalanceExhausted(status, bodyText) {
|
|
291
|
+
if (status !== 402)
|
|
292
|
+
return;
|
|
293
|
+
if (!bodyText.includes("balance_cents"))
|
|
294
|
+
return;
|
|
295
|
+
if (_signalledBalanceExhausted)
|
|
296
|
+
return;
|
|
297
|
+
_signalledBalanceExhausted = true;
|
|
298
|
+
log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
|
|
299
|
+
enqueueNotification({
|
|
300
|
+
id: "balance-exhausted",
|
|
301
|
+
severity: "warn",
|
|
302
|
+
transient: true,
|
|
303
|
+
title: "Hivemind credits exhausted \u2014 top up to keep capturing",
|
|
304
|
+
body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
|
|
305
|
+
dedupKey: { reason: "balance-zero" }
|
|
306
|
+
}).catch((e) => {
|
|
307
|
+
log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
function billingUrl() {
|
|
311
|
+
try {
|
|
312
|
+
const c = loadCredentials();
|
|
313
|
+
if (c?.orgName && c?.workspaceId) {
|
|
314
|
+
return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
|
|
315
|
+
}
|
|
316
|
+
} catch {
|
|
317
|
+
}
|
|
318
|
+
return "https://deeplake.ai";
|
|
169
319
|
}
|
|
170
320
|
var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
171
321
|
var MAX_RETRIES = 3;
|
|
@@ -174,8 +324,8 @@ var MAX_CONCURRENCY = 5;
|
|
|
174
324
|
function getQueryTimeoutMs() {
|
|
175
325
|
return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
|
|
176
326
|
}
|
|
177
|
-
function
|
|
178
|
-
return new Promise((
|
|
327
|
+
function sleep2(ms) {
|
|
328
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
179
329
|
}
|
|
180
330
|
function isTimeoutError(error) {
|
|
181
331
|
const name = error instanceof Error ? error.name.toLowerCase() : "";
|
|
@@ -205,7 +355,7 @@ var Semaphore = class {
|
|
|
205
355
|
this.active++;
|
|
206
356
|
return;
|
|
207
357
|
}
|
|
208
|
-
await new Promise((
|
|
358
|
+
await new Promise((resolve2) => this.waiting.push(resolve2));
|
|
209
359
|
}
|
|
210
360
|
release() {
|
|
211
361
|
this.active--;
|
|
@@ -276,8 +426,8 @@ var DeeplakeApi = class {
|
|
|
276
426
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
277
427
|
if (attempt < MAX_RETRIES) {
|
|
278
428
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
279
|
-
|
|
280
|
-
await
|
|
429
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
|
|
430
|
+
await sleep2(delay);
|
|
281
431
|
continue;
|
|
282
432
|
}
|
|
283
433
|
throw lastError;
|
|
@@ -293,10 +443,11 @@ var DeeplakeApi = class {
|
|
|
293
443
|
const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
|
|
294
444
|
if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
|
|
295
445
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
296
|
-
|
|
297
|
-
await
|
|
446
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
|
|
447
|
+
await sleep2(delay);
|
|
298
448
|
continue;
|
|
299
449
|
}
|
|
450
|
+
maybeSignalBalanceExhausted(resp.status, text);
|
|
300
451
|
throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
|
|
301
452
|
}
|
|
302
453
|
throw lastError ?? new Error("Query failed: max retries exceeded");
|
|
@@ -317,7 +468,7 @@ var DeeplakeApi = class {
|
|
|
317
468
|
const chunk = rows.slice(i, i + CONCURRENCY);
|
|
318
469
|
await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
|
|
319
470
|
}
|
|
320
|
-
|
|
471
|
+
log3(`commit: ${rows.length} rows`);
|
|
321
472
|
}
|
|
322
473
|
async upsertRowSql(row) {
|
|
323
474
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -373,7 +524,7 @@ var DeeplakeApi = class {
|
|
|
373
524
|
markers.writeIndexMarker(markerPath);
|
|
374
525
|
return;
|
|
375
526
|
}
|
|
376
|
-
|
|
527
|
+
log3(`index "${indexName}" skipped: ${e.message}`);
|
|
377
528
|
}
|
|
378
529
|
}
|
|
379
530
|
/**
|
|
@@ -463,13 +614,13 @@ var DeeplakeApi = class {
|
|
|
463
614
|
};
|
|
464
615
|
}
|
|
465
616
|
if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
|
|
466
|
-
await
|
|
617
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
|
|
467
618
|
continue;
|
|
468
619
|
}
|
|
469
620
|
return { tables: [], cacheable: false };
|
|
470
621
|
} catch {
|
|
471
622
|
if (attempt < MAX_RETRIES) {
|
|
472
|
-
await
|
|
623
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
|
|
473
624
|
continue;
|
|
474
625
|
}
|
|
475
626
|
return { tables: [], cacheable: false };
|
|
@@ -497,9 +648,9 @@ var DeeplakeApi = class {
|
|
|
497
648
|
} catch (err) {
|
|
498
649
|
lastErr = err;
|
|
499
650
|
const msg = err instanceof Error ? err.message : String(err);
|
|
500
|
-
|
|
651
|
+
log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
|
|
501
652
|
if (attempt < OUTER_BACKOFFS_MS.length) {
|
|
502
|
-
await
|
|
653
|
+
await sleep2(OUTER_BACKOFFS_MS[attempt]);
|
|
503
654
|
}
|
|
504
655
|
}
|
|
505
656
|
}
|
|
@@ -510,9 +661,9 @@ var DeeplakeApi = class {
|
|
|
510
661
|
const tbl = sqlIdent(name ?? this.tableName);
|
|
511
662
|
const tables = await this.listTables();
|
|
512
663
|
if (!tables.includes(tbl)) {
|
|
513
|
-
|
|
664
|
+
log3(`table "${tbl}" not found, creating`);
|
|
514
665
|
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
|
-
|
|
666
|
+
log3(`table "${tbl}" created`);
|
|
516
667
|
if (!tables.includes(tbl))
|
|
517
668
|
this._tablesCache = [...tables, tbl];
|
|
518
669
|
}
|
|
@@ -525,9 +676,9 @@ var DeeplakeApi = class {
|
|
|
525
676
|
const safe = sqlIdent(name);
|
|
526
677
|
const tables = await this.listTables();
|
|
527
678
|
if (!tables.includes(safe)) {
|
|
528
|
-
|
|
679
|
+
log3(`table "${safe}" not found, creating`);
|
|
529
680
|
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);
|
|
530
|
-
|
|
681
|
+
log3(`table "${safe}" created`);
|
|
531
682
|
if (!tables.includes(safe))
|
|
532
683
|
this._tablesCache = [...tables, safe];
|
|
533
684
|
}
|
|
@@ -550,9 +701,9 @@ var DeeplakeApi = class {
|
|
|
550
701
|
const safe = sqlIdent(name);
|
|
551
702
|
const tables = await this.listTables();
|
|
552
703
|
if (!tables.includes(safe)) {
|
|
553
|
-
|
|
704
|
+
log3(`table "${safe}" not found, creating`);
|
|
554
705
|
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);
|
|
555
|
-
|
|
706
|
+
log3(`table "${safe}" created`);
|
|
556
707
|
if (!tables.includes(safe))
|
|
557
708
|
this._tablesCache = [...tables, safe];
|
|
558
709
|
}
|
|
@@ -1042,9 +1193,9 @@ function capOutputForClaude(output, options = {}) {
|
|
|
1042
1193
|
// dist/src/embeddings/client.js
|
|
1043
1194
|
import { connect } from "node:net";
|
|
1044
1195
|
import { spawn } from "node:child_process";
|
|
1045
|
-
import { openSync, closeSync, writeSync, unlinkSync, existsSync as existsSync3, readFileSync as
|
|
1046
|
-
import { homedir as
|
|
1047
|
-
import { join as
|
|
1196
|
+
import { openSync as openSync2, closeSync as closeSync2, writeSync, unlinkSync as unlinkSync3, existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
|
|
1197
|
+
import { homedir as homedir5 } from "node:os";
|
|
1198
|
+
import { join as join6 } from "node:path";
|
|
1048
1199
|
|
|
1049
1200
|
// dist/src/embeddings/protocol.js
|
|
1050
1201
|
var DEFAULT_SOCKET_DIR = "/tmp";
|
|
@@ -1058,12 +1209,13 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
|
|
|
1058
1209
|
}
|
|
1059
1210
|
|
|
1060
1211
|
// dist/src/embeddings/client.js
|
|
1061
|
-
var SHARED_DAEMON_PATH =
|
|
1062
|
-
var
|
|
1212
|
+
var SHARED_DAEMON_PATH = join6(homedir5(), ".hivemind", "embed-deps", "embed-daemon.js");
|
|
1213
|
+
var log4 = (m) => log("embed-client", m);
|
|
1063
1214
|
function getUid() {
|
|
1064
1215
|
const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
|
|
1065
1216
|
return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
|
|
1066
1217
|
}
|
|
1218
|
+
var _recycledStuckDaemon = false;
|
|
1067
1219
|
var EmbedClient = class {
|
|
1068
1220
|
socketPath;
|
|
1069
1221
|
pidPath;
|
|
@@ -1072,6 +1224,7 @@ var EmbedClient = class {
|
|
|
1072
1224
|
autoSpawn;
|
|
1073
1225
|
spawnWaitMs;
|
|
1074
1226
|
nextId = 0;
|
|
1227
|
+
helloVerified = false;
|
|
1075
1228
|
constructor(opts = {}) {
|
|
1076
1229
|
const uid = getUid();
|
|
1077
1230
|
const dir = opts.socketDir ?? "/tmp";
|
|
@@ -1088,8 +1241,33 @@ var EmbedClient = class {
|
|
|
1088
1241
|
*
|
|
1089
1242
|
* Fire-and-forget spawn on miss: if the daemon isn't up, this call returns
|
|
1090
1243
|
* null AND kicks off a background spawn. The next call finds a ready daemon.
|
|
1244
|
+
*
|
|
1245
|
+
* Stuck-daemon recycle: if the daemon returns a transformers-missing
|
|
1246
|
+
* error (typical after a marketplace upgrade left an older daemon process
|
|
1247
|
+
* alive but with no node_modules accessible from its bundle path), we
|
|
1248
|
+
* SIGTERM it and clear its sock/pid so the very next call spawns a fresh
|
|
1249
|
+
* daemon from the current bundle. Without this, the stuck daemon would
|
|
1250
|
+
* keep poisoning every session until its 10-minute idle-out fires.
|
|
1091
1251
|
*/
|
|
1092
1252
|
async embed(text, kind = "document") {
|
|
1253
|
+
const v = await this.embedAttempt(text, kind);
|
|
1254
|
+
if (v !== "recycled")
|
|
1255
|
+
return v;
|
|
1256
|
+
if (!this.autoSpawn)
|
|
1257
|
+
return null;
|
|
1258
|
+
this.trySpawnDaemon();
|
|
1259
|
+
await this.waitForDaemonReady();
|
|
1260
|
+
const retry = await this.embedAttempt(text, kind);
|
|
1261
|
+
return retry === "recycled" ? null : retry;
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* One round-trip: connect → verify → embed. Returns:
|
|
1265
|
+
* - number[] : embedding vector (happy path)
|
|
1266
|
+
* - null : timeout / daemon error / transformers-missing
|
|
1267
|
+
* - "recycled": verifyDaemonOnce killed the daemon mid-call;
|
|
1268
|
+
* caller should respawn and retry once.
|
|
1269
|
+
*/
|
|
1270
|
+
async embedAttempt(text, kind) {
|
|
1093
1271
|
let sock;
|
|
1094
1272
|
try {
|
|
1095
1273
|
sock = await this.connectOnce();
|
|
@@ -1099,17 +1277,25 @@ var EmbedClient = class {
|
|
|
1099
1277
|
return null;
|
|
1100
1278
|
}
|
|
1101
1279
|
try {
|
|
1280
|
+
const recycled = await this.verifyDaemonOnce(sock);
|
|
1281
|
+
if (recycled) {
|
|
1282
|
+
return "recycled";
|
|
1283
|
+
}
|
|
1102
1284
|
const id = String(++this.nextId);
|
|
1103
1285
|
const req = { op: "embed", id, kind, text };
|
|
1104
1286
|
const resp = await this.sendAndWait(sock, req);
|
|
1105
1287
|
if (resp.error || !("embedding" in resp) || !resp.embedding) {
|
|
1106
|
-
|
|
1288
|
+
const err = resp.error ?? "no embedding";
|
|
1289
|
+
log4(`embed err: ${err}`);
|
|
1290
|
+
if (isTransformersMissingError(err)) {
|
|
1291
|
+
this.handleTransformersMissing(err);
|
|
1292
|
+
}
|
|
1107
1293
|
return null;
|
|
1108
1294
|
}
|
|
1109
1295
|
return resp.embedding;
|
|
1110
1296
|
} catch (e) {
|
|
1111
1297
|
const err = e instanceof Error ? e.message : String(e);
|
|
1112
|
-
|
|
1298
|
+
log4(`embed failed: ${err}`);
|
|
1113
1299
|
return null;
|
|
1114
1300
|
} finally {
|
|
1115
1301
|
try {
|
|
@@ -1118,6 +1304,123 @@ var EmbedClient = class {
|
|
|
1118
1304
|
}
|
|
1119
1305
|
}
|
|
1120
1306
|
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Poll for the sock file to come back after `trySpawnDaemon` — used by
|
|
1309
|
+
* the recycle retry path. Best-effort: caps at `spawnWaitMs` and
|
|
1310
|
+
* returns regardless so the retry attempt can run.
|
|
1311
|
+
*/
|
|
1312
|
+
async waitForDaemonReady() {
|
|
1313
|
+
const deadline = Date.now() + this.spawnWaitMs;
|
|
1314
|
+
while (Date.now() < deadline) {
|
|
1315
|
+
if (existsSync3(this.socketPath))
|
|
1316
|
+
return;
|
|
1317
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Send a `hello` on first successful connect per EmbedClient instance.
|
|
1322
|
+
* If the daemon answers with a path that doesn't match our configured
|
|
1323
|
+
* daemonEntry — typical after a marketplace upgrade replaced the bundle
|
|
1324
|
+
* — SIGTERM the daemon + clear sock/pid so the next call spawns from the
|
|
1325
|
+
* current bundle.
|
|
1326
|
+
*
|
|
1327
|
+
* `helloVerified` is set ONLY after we've seen a compatible response,
|
|
1328
|
+
* so a transient probe failure or a recycle-triggering mismatch leaves
|
|
1329
|
+
* the flag false; the next reconnect re-runs verification against
|
|
1330
|
+
* whatever daemon is then live (typically the fresh spawn).
|
|
1331
|
+
*/
|
|
1332
|
+
async verifyDaemonOnce(sock) {
|
|
1333
|
+
if (this.helloVerified)
|
|
1334
|
+
return false;
|
|
1335
|
+
if (!this.daemonEntry) {
|
|
1336
|
+
this.helloVerified = true;
|
|
1337
|
+
return false;
|
|
1338
|
+
}
|
|
1339
|
+
const id = String(++this.nextId);
|
|
1340
|
+
const req = { op: "hello", id };
|
|
1341
|
+
let resp;
|
|
1342
|
+
try {
|
|
1343
|
+
resp = await this.sendAndWait(sock, req);
|
|
1344
|
+
} catch (e) {
|
|
1345
|
+
log4(`hello probe failed (inconclusive, will retry next connect): ${e instanceof Error ? e.message : String(e)}`);
|
|
1346
|
+
return false;
|
|
1347
|
+
}
|
|
1348
|
+
const hello = resp;
|
|
1349
|
+
if (_recycledStuckDaemon) {
|
|
1350
|
+
return false;
|
|
1351
|
+
}
|
|
1352
|
+
if (!hello.daemonPath) {
|
|
1353
|
+
_recycledStuckDaemon = true;
|
|
1354
|
+
log4(`daemon does not implement hello (older protocol); recycling`);
|
|
1355
|
+
this.recycleDaemon(hello.pid);
|
|
1356
|
+
return true;
|
|
1357
|
+
}
|
|
1358
|
+
if (hello.daemonPath !== this.daemonEntry && !existsSync3(hello.daemonPath)) {
|
|
1359
|
+
_recycledStuckDaemon = true;
|
|
1360
|
+
log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
|
|
1361
|
+
this.recycleDaemon(hello.pid);
|
|
1362
|
+
return true;
|
|
1363
|
+
}
|
|
1364
|
+
this.helloVerified = true;
|
|
1365
|
+
return false;
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* On a transformers-missing error from the daemon, SIGTERM the stuck
|
|
1369
|
+
* daemon (the bundle daemon that can't find its deps) and clear
|
|
1370
|
+
* sock/pid so the next call spawns fresh.
|
|
1371
|
+
*
|
|
1372
|
+
* Previously this also enqueued a user-visible "Hivemind embeddings
|
|
1373
|
+
* disabled — deps missing" notification telling the user to run
|
|
1374
|
+
* `hivemind embeddings install`. The notification was removed because
|
|
1375
|
+
* (a) the recycle alone often fixes the issue silently, and (b) the
|
|
1376
|
+
* warning kept stacking on top of the primary session-start banner
|
|
1377
|
+
* which clashed with the single-slot priority model. The `detail`
|
|
1378
|
+
* argument is retained for future telemetry / debug logging.
|
|
1379
|
+
*/
|
|
1380
|
+
handleTransformersMissing(_detail) {
|
|
1381
|
+
if (!_recycledStuckDaemon) {
|
|
1382
|
+
_recycledStuckDaemon = true;
|
|
1383
|
+
this.recycleDaemon(null);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
|
|
1388
|
+
* combination and dead-PID cases.
|
|
1389
|
+
*
|
|
1390
|
+
* Identity check: gate the SIGTERM on the daemon's socket file still
|
|
1391
|
+
* existing. We know the daemon was alive moments ago (we either just
|
|
1392
|
+
* got a hello response or the caller saw a transformers-missing error
|
|
1393
|
+
* the daemon emitted), but if the socket file is gone by the time we
|
|
1394
|
+
* try to kill, the daemon process is also gone and the PID we
|
|
1395
|
+
* captured may already have been recycled by the OS to an unrelated
|
|
1396
|
+
* user process. Mirrors the gate added to `killEmbedDaemon` in the
|
|
1397
|
+
* CLI — same failure mode, rarer trigger.
|
|
1398
|
+
*/
|
|
1399
|
+
recycleDaemon(reportedPid) {
|
|
1400
|
+
let pid = reportedPid;
|
|
1401
|
+
if (pid === null) {
|
|
1402
|
+
try {
|
|
1403
|
+
pid = Number.parseInt(readFileSync5(this.pidPath, "utf-8").trim(), 10);
|
|
1404
|
+
} catch {
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync3(this.socketPath)) {
|
|
1408
|
+
try {
|
|
1409
|
+
process.kill(pid, "SIGTERM");
|
|
1410
|
+
} catch {
|
|
1411
|
+
}
|
|
1412
|
+
} else if (pid !== null) {
|
|
1413
|
+
log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
|
|
1414
|
+
}
|
|
1415
|
+
try {
|
|
1416
|
+
unlinkSync3(this.socketPath);
|
|
1417
|
+
} catch {
|
|
1418
|
+
}
|
|
1419
|
+
try {
|
|
1420
|
+
unlinkSync3(this.pidPath);
|
|
1421
|
+
} catch {
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1121
1424
|
/**
|
|
1122
1425
|
* Wait up to spawnWaitMs for the daemon to accept connections, spawning if
|
|
1123
1426
|
* necessary. Meant for SessionStart / long-running batches — not the hot path.
|
|
@@ -1141,7 +1444,7 @@ var EmbedClient = class {
|
|
|
1141
1444
|
}
|
|
1142
1445
|
}
|
|
1143
1446
|
connectOnce() {
|
|
1144
|
-
return new Promise((
|
|
1447
|
+
return new Promise((resolve2, reject) => {
|
|
1145
1448
|
const sock = connect(this.socketPath);
|
|
1146
1449
|
const to = setTimeout(() => {
|
|
1147
1450
|
sock.destroy();
|
|
@@ -1149,7 +1452,7 @@ var EmbedClient = class {
|
|
|
1149
1452
|
}, this.timeoutMs);
|
|
1150
1453
|
sock.once("connect", () => {
|
|
1151
1454
|
clearTimeout(to);
|
|
1152
|
-
|
|
1455
|
+
resolve2(sock);
|
|
1153
1456
|
});
|
|
1154
1457
|
sock.once("error", (e) => {
|
|
1155
1458
|
clearTimeout(to);
|
|
@@ -1160,16 +1463,16 @@ var EmbedClient = class {
|
|
|
1160
1463
|
trySpawnDaemon() {
|
|
1161
1464
|
let fd;
|
|
1162
1465
|
try {
|
|
1163
|
-
fd =
|
|
1466
|
+
fd = openSync2(this.pidPath, "wx", 384);
|
|
1164
1467
|
writeSync(fd, String(process.pid));
|
|
1165
1468
|
} catch (e) {
|
|
1166
1469
|
if (this.isPidFileStale()) {
|
|
1167
1470
|
try {
|
|
1168
|
-
|
|
1471
|
+
unlinkSync3(this.pidPath);
|
|
1169
1472
|
} catch {
|
|
1170
1473
|
}
|
|
1171
1474
|
try {
|
|
1172
|
-
fd =
|
|
1475
|
+
fd = openSync2(this.pidPath, "wx", 384);
|
|
1173
1476
|
writeSync(fd, String(process.pid));
|
|
1174
1477
|
} catch {
|
|
1175
1478
|
return;
|
|
@@ -1179,10 +1482,10 @@ var EmbedClient = class {
|
|
|
1179
1482
|
}
|
|
1180
1483
|
}
|
|
1181
1484
|
if (!this.daemonEntry || !existsSync3(this.daemonEntry)) {
|
|
1182
|
-
|
|
1485
|
+
log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
|
|
1183
1486
|
try {
|
|
1184
|
-
|
|
1185
|
-
|
|
1487
|
+
closeSync2(fd);
|
|
1488
|
+
unlinkSync3(this.pidPath);
|
|
1186
1489
|
} catch {
|
|
1187
1490
|
}
|
|
1188
1491
|
return;
|
|
@@ -1194,14 +1497,14 @@ var EmbedClient = class {
|
|
|
1194
1497
|
env: process.env
|
|
1195
1498
|
});
|
|
1196
1499
|
child.unref();
|
|
1197
|
-
|
|
1500
|
+
log4(`spawned daemon pid=${child.pid}`);
|
|
1198
1501
|
} finally {
|
|
1199
|
-
|
|
1502
|
+
closeSync2(fd);
|
|
1200
1503
|
}
|
|
1201
1504
|
}
|
|
1202
1505
|
isPidFileStale() {
|
|
1203
1506
|
try {
|
|
1204
|
-
const raw =
|
|
1507
|
+
const raw = readFileSync5(this.pidPath, "utf-8").trim();
|
|
1205
1508
|
const pid = Number(raw);
|
|
1206
1509
|
if (!pid || Number.isNaN(pid))
|
|
1207
1510
|
return true;
|
|
@@ -1219,7 +1522,7 @@ var EmbedClient = class {
|
|
|
1219
1522
|
const deadline = Date.now() + this.spawnWaitMs;
|
|
1220
1523
|
let delay = 30;
|
|
1221
1524
|
while (Date.now() < deadline) {
|
|
1222
|
-
await
|
|
1525
|
+
await sleep3(delay);
|
|
1223
1526
|
delay = Math.min(delay * 1.5, 300);
|
|
1224
1527
|
if (!existsSync3(this.socketPath))
|
|
1225
1528
|
continue;
|
|
@@ -1231,7 +1534,7 @@ var EmbedClient = class {
|
|
|
1231
1534
|
throw new Error("daemon did not become ready within spawnWaitMs");
|
|
1232
1535
|
}
|
|
1233
1536
|
sendAndWait(sock, req) {
|
|
1234
|
-
return new Promise((
|
|
1537
|
+
return new Promise((resolve2, reject) => {
|
|
1235
1538
|
let buf = "";
|
|
1236
1539
|
const to = setTimeout(() => {
|
|
1237
1540
|
sock.destroy();
|
|
@@ -1246,7 +1549,7 @@ var EmbedClient = class {
|
|
|
1246
1549
|
const line = buf.slice(0, nl);
|
|
1247
1550
|
clearTimeout(to);
|
|
1248
1551
|
try {
|
|
1249
|
-
|
|
1552
|
+
resolve2(JSON.parse(line));
|
|
1250
1553
|
} catch (e) {
|
|
1251
1554
|
reject(e);
|
|
1252
1555
|
}
|
|
@@ -1263,29 +1566,116 @@ var EmbedClient = class {
|
|
|
1263
1566
|
});
|
|
1264
1567
|
}
|
|
1265
1568
|
};
|
|
1266
|
-
function
|
|
1569
|
+
function sleep3(ms) {
|
|
1267
1570
|
return new Promise((r) => setTimeout(r, ms));
|
|
1268
1571
|
}
|
|
1572
|
+
function isTransformersMissingError(err) {
|
|
1573
|
+
if (/hivemind embeddings install/i.test(err))
|
|
1574
|
+
return true;
|
|
1575
|
+
return /@huggingface\/transformers/i.test(err);
|
|
1576
|
+
}
|
|
1269
1577
|
|
|
1270
1578
|
// dist/src/embeddings/disable.js
|
|
1271
1579
|
import { createRequire } from "node:module";
|
|
1272
|
-
import { homedir as
|
|
1273
|
-
import { join as
|
|
1580
|
+
import { homedir as homedir7 } from "node:os";
|
|
1581
|
+
import { join as join8 } from "node:path";
|
|
1274
1582
|
import { pathToFileURL } from "node:url";
|
|
1583
|
+
|
|
1584
|
+
// dist/src/user-config.js
|
|
1585
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1586
|
+
import { homedir as homedir6 } from "node:os";
|
|
1587
|
+
import { dirname, join as join7 } from "node:path";
|
|
1588
|
+
var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join7(homedir6(), ".deeplake", "config.json");
|
|
1589
|
+
var _cache = null;
|
|
1590
|
+
var _migrated = false;
|
|
1591
|
+
function readUserConfig() {
|
|
1592
|
+
if (_cache !== null)
|
|
1593
|
+
return _cache;
|
|
1594
|
+
const path = _configPath();
|
|
1595
|
+
if (!existsSync4(path)) {
|
|
1596
|
+
_cache = {};
|
|
1597
|
+
return _cache;
|
|
1598
|
+
}
|
|
1599
|
+
try {
|
|
1600
|
+
const raw = readFileSync6(path, "utf-8");
|
|
1601
|
+
const parsed = JSON.parse(raw);
|
|
1602
|
+
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1603
|
+
} catch {
|
|
1604
|
+
_cache = {};
|
|
1605
|
+
}
|
|
1606
|
+
return _cache;
|
|
1607
|
+
}
|
|
1608
|
+
function writeUserConfig(patch) {
|
|
1609
|
+
const current = readUserConfig();
|
|
1610
|
+
const merged = deepMerge(current, patch);
|
|
1611
|
+
const path = _configPath();
|
|
1612
|
+
const dir = dirname(path);
|
|
1613
|
+
if (!existsSync4(dir))
|
|
1614
|
+
mkdirSync4(dir, { recursive: true });
|
|
1615
|
+
const tmp = `${path}.tmp.${process.pid}`;
|
|
1616
|
+
writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1617
|
+
renameSync2(tmp, path);
|
|
1618
|
+
_cache = merged;
|
|
1619
|
+
return merged;
|
|
1620
|
+
}
|
|
1621
|
+
function getEmbeddingsEnabled() {
|
|
1622
|
+
const cfg = readUserConfig();
|
|
1623
|
+
if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
|
|
1624
|
+
return cfg.embeddings.enabled;
|
|
1625
|
+
}
|
|
1626
|
+
if (_migrated) {
|
|
1627
|
+
return migrationValueFromEnv();
|
|
1628
|
+
}
|
|
1629
|
+
_migrated = true;
|
|
1630
|
+
const enabled = migrationValueFromEnv();
|
|
1631
|
+
try {
|
|
1632
|
+
writeUserConfig({ embeddings: { enabled } });
|
|
1633
|
+
} catch {
|
|
1634
|
+
_cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
|
|
1635
|
+
}
|
|
1636
|
+
return enabled;
|
|
1637
|
+
}
|
|
1638
|
+
function migrationValueFromEnv() {
|
|
1639
|
+
const raw = process.env.HIVEMIND_EMBEDDINGS;
|
|
1640
|
+
if (raw === void 0)
|
|
1641
|
+
return false;
|
|
1642
|
+
if (raw === "false")
|
|
1643
|
+
return false;
|
|
1644
|
+
return true;
|
|
1645
|
+
}
|
|
1646
|
+
function isPlainObject(value) {
|
|
1647
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1648
|
+
}
|
|
1649
|
+
function deepMerge(base, patch) {
|
|
1650
|
+
const out = { ...base };
|
|
1651
|
+
for (const key of Object.keys(patch)) {
|
|
1652
|
+
const patchVal = patch[key];
|
|
1653
|
+
const baseVal = base[key];
|
|
1654
|
+
if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
|
|
1655
|
+
out[key] = { ...baseVal, ...patchVal };
|
|
1656
|
+
} else if (patchVal !== void 0) {
|
|
1657
|
+
out[key] = patchVal;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return out;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
// dist/src/embeddings/disable.js
|
|
1275
1664
|
var cachedStatus = null;
|
|
1276
1665
|
function defaultResolveTransformers() {
|
|
1666
|
+
const sharedDir = join8(homedir7(), ".hivemind", "embed-deps");
|
|
1277
1667
|
try {
|
|
1278
|
-
createRequire(
|
|
1668
|
+
createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
|
|
1279
1669
|
return;
|
|
1280
1670
|
} catch {
|
|
1281
1671
|
}
|
|
1282
|
-
|
|
1283
|
-
createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
|
|
1672
|
+
createRequire(import.meta.url).resolve("@huggingface/transformers");
|
|
1284
1673
|
}
|
|
1285
1674
|
var _resolve = defaultResolveTransformers;
|
|
1675
|
+
var _readEnabled = getEmbeddingsEnabled;
|
|
1286
1676
|
function detectStatus() {
|
|
1287
|
-
if (
|
|
1288
|
-
return "
|
|
1677
|
+
if (!_readEnabled())
|
|
1678
|
+
return "user-disabled";
|
|
1289
1679
|
try {
|
|
1290
1680
|
_resolve();
|
|
1291
1681
|
return "enabled";
|
|
@@ -1305,11 +1695,11 @@ function embeddingsDisabled() {
|
|
|
1305
1695
|
|
|
1306
1696
|
// dist/src/hooks/grep-direct.js
|
|
1307
1697
|
import { fileURLToPath } from "node:url";
|
|
1308
|
-
import { dirname, join as
|
|
1698
|
+
import { dirname as dirname2, join as join9 } from "node:path";
|
|
1309
1699
|
var SEMANTIC_ENABLED = process.env.HIVEMIND_SEMANTIC_SEARCH !== "false" && !embeddingsDisabled();
|
|
1310
1700
|
var SEMANTIC_TIMEOUT_MS = Number(process.env.HIVEMIND_SEMANTIC_EMBED_TIMEOUT_MS ?? "500");
|
|
1311
1701
|
function resolveDaemonPath() {
|
|
1312
|
-
return
|
|
1702
|
+
return join9(dirname2(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
|
|
1313
1703
|
}
|
|
1314
1704
|
var sharedEmbedClient = null;
|
|
1315
1705
|
function getEmbedClient() {
|
|
@@ -1662,9 +2052,9 @@ async function handleGrepDirect(api, table, sessionsTable, params) {
|
|
|
1662
2052
|
}
|
|
1663
2053
|
|
|
1664
2054
|
// dist/src/hooks/memory-path-utils.js
|
|
1665
|
-
import { homedir as
|
|
1666
|
-
import { join as
|
|
1667
|
-
var MEMORY_PATH =
|
|
2055
|
+
import { homedir as homedir8 } from "node:os";
|
|
2056
|
+
import { join as join10 } from "node:path";
|
|
2057
|
+
var MEMORY_PATH = join10(homedir8(), ".deeplake", "memory");
|
|
1668
2058
|
var TILDE_PATH = "~/.deeplake/memory";
|
|
1669
2059
|
var HOME_VAR_PATH = "$HOME/.deeplake/memory";
|
|
1670
2060
|
function touchesMemory(p) {
|
|
@@ -1675,7 +2065,7 @@ function rewritePaths(cmd) {
|
|
|
1675
2065
|
}
|
|
1676
2066
|
|
|
1677
2067
|
// dist/src/hooks/hermes/pre-tool-use.js
|
|
1678
|
-
var
|
|
2068
|
+
var log5 = (msg) => log("hermes-pre-tool-use", msg);
|
|
1679
2069
|
async function main() {
|
|
1680
2070
|
const input = await readStdin();
|
|
1681
2071
|
if (input.tool_name !== "terminal")
|
|
@@ -1692,7 +2082,7 @@ async function main() {
|
|
|
1692
2082
|
return;
|
|
1693
2083
|
const config = loadConfig();
|
|
1694
2084
|
if (!config) {
|
|
1695
|
-
|
|
2085
|
+
log5("no config \u2014 falling through to Hermes");
|
|
1696
2086
|
return;
|
|
1697
2087
|
}
|
|
1698
2088
|
const api = new DeeplakeApi(config.token, config.apiUrl, config.orgId, config.workspaceId, config.tableName);
|
|
@@ -1700,7 +2090,7 @@ async function main() {
|
|
|
1700
2090
|
const result = await handleGrepDirect(api, config.tableName, config.sessionsTableName, grepParams);
|
|
1701
2091
|
if (result === null)
|
|
1702
2092
|
return;
|
|
1703
|
-
|
|
2093
|
+
log5(`intercepted ${command.slice(0, 80)} \u2192 ${result.length} chars from SQL fast-path`);
|
|
1704
2094
|
const message = [
|
|
1705
2095
|
result,
|
|
1706
2096
|
"",
|
|
@@ -1709,10 +2099,10 @@ async function main() {
|
|
|
1709
2099
|
process.stdout.write(JSON.stringify({ action: "block", message }));
|
|
1710
2100
|
} catch (err) {
|
|
1711
2101
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1712
|
-
|
|
2102
|
+
log5(`fast-path failed, falling through: ${msg}`);
|
|
1713
2103
|
}
|
|
1714
2104
|
}
|
|
1715
2105
|
main().catch((e) => {
|
|
1716
|
-
|
|
2106
|
+
log5(`fatal: ${e.message}`);
|
|
1717
2107
|
process.exit(0);
|
|
1718
2108
|
});
|