@deeplake/hivemind 0.7.32 → 0.7.34
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 +332 -189
- 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 +229 -87
- package/codex/bundle/shell/deeplake-shell.js +328 -295
- package/codex/bundle/skillify-worker.js +26 -18
- package/codex/bundle/stop.js +450 -394
- package/codex/bundle/wiki-worker.js +174 -292
- package/cursor/bundle/capture.js +448 -392
- package/cursor/bundle/commands/auth-login.js +163 -30
- package/cursor/bundle/pre-tool-use.js +324 -291
- package/cursor/bundle/session-end.js +43 -20
- package/cursor/bundle/session-start.js +272 -130
- package/cursor/bundle/shell/deeplake-shell.js +328 -295
- package/cursor/bundle/skillify-worker.js +26 -18
- package/cursor/bundle/wiki-worker.js +174 -292
- package/hermes/bundle/capture.js +448 -392
- package/hermes/bundle/commands/auth-login.js +163 -30
- package/hermes/bundle/pre-tool-use.js +324 -291
- package/hermes/bundle/session-end.js +43 -20
- package/hermes/bundle/session-start.js +269 -127
- package/hermes/bundle/shell/deeplake-shell.js +328 -295
- package/hermes/bundle/skillify-worker.js +26 -18
- package/hermes/bundle/wiki-worker.js +174 -292
- package/mcp/bundle/server.js +190 -57
- package/openclaw/dist/index.js +160 -32
- package/openclaw/dist/skillify-worker.js +26 -18
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
package/codex/bundle/stop.js
CHANGED
|
@@ -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, readFileSync 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({
|
|
@@ -53,9 +53,9 @@ var init_index_marker_store = __esm({
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
// dist/src/hooks/codex/stop.js
|
|
56
|
-
import { readFileSync as
|
|
56
|
+
import { readFileSync as readFileSync11, existsSync as existsSync10 } from "node:fs";
|
|
57
57
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
58
|
-
import { dirname as
|
|
58
|
+
import { dirname as dirname6, join as join19 } from "node:path";
|
|
59
59
|
|
|
60
60
|
// dist/src/utils/stdin.js
|
|
61
61
|
function readStdin() {
|
|
@@ -152,6 +152,125 @@ function deeplakeClientHeader() {
|
|
|
152
152
|
return { [DEEPLAKE_CLIENT_HEADER]: deeplakeClientValue() };
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
// dist/src/notifications/queue.js
|
|
156
|
+
import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
157
|
+
import { join as join3, resolve } from "node:path";
|
|
158
|
+
import { homedir as homedir3 } from "node:os";
|
|
159
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
160
|
+
var log2 = (msg) => log("notifications-queue", msg);
|
|
161
|
+
var LOCK_RETRY_MAX = 50;
|
|
162
|
+
var LOCK_RETRY_BASE_MS = 5;
|
|
163
|
+
var LOCK_STALE_MS = 5e3;
|
|
164
|
+
function queuePath() {
|
|
165
|
+
return join3(homedir3(), ".deeplake", "notifications-queue.json");
|
|
166
|
+
}
|
|
167
|
+
function lockPath() {
|
|
168
|
+
return `${queuePath()}.lock`;
|
|
169
|
+
}
|
|
170
|
+
function readQueue() {
|
|
171
|
+
try {
|
|
172
|
+
const raw = readFileSync2(queuePath(), "utf-8");
|
|
173
|
+
const parsed = JSON.parse(raw);
|
|
174
|
+
if (!parsed || !Array.isArray(parsed.queue)) {
|
|
175
|
+
log2(`queue malformed \u2192 treating as empty`);
|
|
176
|
+
return { queue: [] };
|
|
177
|
+
}
|
|
178
|
+
return { queue: parsed.queue };
|
|
179
|
+
} catch {
|
|
180
|
+
return { queue: [] };
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function _isQueuePathInsideHome(path, home) {
|
|
184
|
+
const r = resolve(path);
|
|
185
|
+
const h = resolve(home);
|
|
186
|
+
return r.startsWith(h + "/") || r === h;
|
|
187
|
+
}
|
|
188
|
+
function writeQueue(q) {
|
|
189
|
+
const path = queuePath();
|
|
190
|
+
const home = resolve(homedir3());
|
|
191
|
+
if (!_isQueuePathInsideHome(path, home)) {
|
|
192
|
+
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
|
|
193
|
+
}
|
|
194
|
+
mkdirSync(join3(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
195
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
196
|
+
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
197
|
+
renameSync(tmp, path);
|
|
198
|
+
}
|
|
199
|
+
async function withQueueLock(fn) {
|
|
200
|
+
const path = lockPath();
|
|
201
|
+
mkdirSync(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
|
|
202
|
+
let fd = null;
|
|
203
|
+
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
204
|
+
try {
|
|
205
|
+
fd = openSync(path, "wx", 384);
|
|
206
|
+
break;
|
|
207
|
+
} catch (e) {
|
|
208
|
+
const code = e.code;
|
|
209
|
+
if (code !== "EEXIST")
|
|
210
|
+
throw e;
|
|
211
|
+
try {
|
|
212
|
+
const age = Date.now() - statSync(path).mtimeMs;
|
|
213
|
+
if (age > LOCK_STALE_MS) {
|
|
214
|
+
unlinkSync(path);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
} catch {
|
|
218
|
+
}
|
|
219
|
+
const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
|
|
220
|
+
await sleep(delay);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (fd === null) {
|
|
224
|
+
log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
|
|
225
|
+
return fn();
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
return fn();
|
|
229
|
+
} finally {
|
|
230
|
+
try {
|
|
231
|
+
closeSync(fd);
|
|
232
|
+
} catch {
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
unlinkSync(path);
|
|
236
|
+
} catch {
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function sameDedupKey(a, b) {
|
|
241
|
+
if (a.id !== b.id)
|
|
242
|
+
return false;
|
|
243
|
+
return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
|
|
244
|
+
}
|
|
245
|
+
async function enqueueNotification(n) {
|
|
246
|
+
await withQueueLock(() => {
|
|
247
|
+
const q = readQueue();
|
|
248
|
+
if (q.queue.some((existing) => sameDedupKey(existing, n))) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
q.queue.push(n);
|
|
252
|
+
writeQueue(q);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// dist/src/commands/auth-creds.js
|
|
257
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
258
|
+
import { join as join4 } from "node:path";
|
|
259
|
+
import { homedir as homedir4 } from "node:os";
|
|
260
|
+
function configDir() {
|
|
261
|
+
return join4(homedir4(), ".deeplake");
|
|
262
|
+
}
|
|
263
|
+
function credsPath() {
|
|
264
|
+
return join4(configDir(), "credentials.json");
|
|
265
|
+
}
|
|
266
|
+
function loadCredentials() {
|
|
267
|
+
try {
|
|
268
|
+
return JSON.parse(readFileSync3(credsPath(), "utf-8"));
|
|
269
|
+
} catch {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
155
274
|
// dist/src/deeplake-api.js
|
|
156
275
|
var indexMarkerStorePromise = null;
|
|
157
276
|
function getIndexMarkerStore() {
|
|
@@ -159,7 +278,7 @@ function getIndexMarkerStore() {
|
|
|
159
278
|
indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
|
|
160
279
|
return indexMarkerStorePromise;
|
|
161
280
|
}
|
|
162
|
-
var
|
|
281
|
+
var log3 = (msg) => log("sdk", msg);
|
|
163
282
|
function summarizeSql(sql, maxLen = 220) {
|
|
164
283
|
const compact = sql.replace(/\s+/g, " ").trim();
|
|
165
284
|
return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
|
|
@@ -171,7 +290,38 @@ function traceSql(msg) {
|
|
|
171
290
|
process.stderr.write(`[deeplake-sql] ${msg}
|
|
172
291
|
`);
|
|
173
292
|
if (process.env.HIVEMIND_DEBUG === "1")
|
|
174
|
-
|
|
293
|
+
log3(msg);
|
|
294
|
+
}
|
|
295
|
+
var _signalledBalanceExhausted = false;
|
|
296
|
+
function maybeSignalBalanceExhausted(status, bodyText) {
|
|
297
|
+
if (status !== 402)
|
|
298
|
+
return;
|
|
299
|
+
if (!bodyText.includes("balance_cents"))
|
|
300
|
+
return;
|
|
301
|
+
if (_signalledBalanceExhausted)
|
|
302
|
+
return;
|
|
303
|
+
_signalledBalanceExhausted = true;
|
|
304
|
+
log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
|
|
305
|
+
enqueueNotification({
|
|
306
|
+
id: "balance-exhausted",
|
|
307
|
+
severity: "warn",
|
|
308
|
+
transient: true,
|
|
309
|
+
title: "Hivemind credits exhausted \u2014 top up to keep capturing",
|
|
310
|
+
body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
|
|
311
|
+
dedupKey: { reason: "balance-zero" }
|
|
312
|
+
}).catch((e) => {
|
|
313
|
+
log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function billingUrl() {
|
|
317
|
+
try {
|
|
318
|
+
const c = loadCredentials();
|
|
319
|
+
if (c?.orgName && c?.workspaceId) {
|
|
320
|
+
return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
|
|
321
|
+
}
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
324
|
+
return "https://deeplake.ai";
|
|
175
325
|
}
|
|
176
326
|
var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
177
327
|
var MAX_RETRIES = 3;
|
|
@@ -180,7 +330,7 @@ var MAX_CONCURRENCY = 5;
|
|
|
180
330
|
function getQueryTimeoutMs() {
|
|
181
331
|
return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
|
|
182
332
|
}
|
|
183
|
-
function
|
|
333
|
+
function sleep2(ms) {
|
|
184
334
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
185
335
|
}
|
|
186
336
|
function isTimeoutError(error) {
|
|
@@ -282,8 +432,8 @@ var DeeplakeApi = class {
|
|
|
282
432
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
283
433
|
if (attempt < MAX_RETRIES) {
|
|
284
434
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
285
|
-
|
|
286
|
-
await
|
|
435
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
|
|
436
|
+
await sleep2(delay);
|
|
287
437
|
continue;
|
|
288
438
|
}
|
|
289
439
|
throw lastError;
|
|
@@ -299,10 +449,11 @@ var DeeplakeApi = class {
|
|
|
299
449
|
const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
|
|
300
450
|
if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
|
|
301
451
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
302
|
-
|
|
303
|
-
await
|
|
452
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
|
|
453
|
+
await sleep2(delay);
|
|
304
454
|
continue;
|
|
305
455
|
}
|
|
456
|
+
maybeSignalBalanceExhausted(resp.status, text);
|
|
306
457
|
throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
|
|
307
458
|
}
|
|
308
459
|
throw lastError ?? new Error("Query failed: max retries exceeded");
|
|
@@ -323,7 +474,7 @@ var DeeplakeApi = class {
|
|
|
323
474
|
const chunk = rows.slice(i, i + CONCURRENCY);
|
|
324
475
|
await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
|
|
325
476
|
}
|
|
326
|
-
|
|
477
|
+
log3(`commit: ${rows.length} rows`);
|
|
327
478
|
}
|
|
328
479
|
async upsertRowSql(row) {
|
|
329
480
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -379,7 +530,7 @@ var DeeplakeApi = class {
|
|
|
379
530
|
markers.writeIndexMarker(markerPath);
|
|
380
531
|
return;
|
|
381
532
|
}
|
|
382
|
-
|
|
533
|
+
log3(`index "${indexName}" skipped: ${e.message}`);
|
|
383
534
|
}
|
|
384
535
|
}
|
|
385
536
|
/**
|
|
@@ -469,13 +620,13 @@ var DeeplakeApi = class {
|
|
|
469
620
|
};
|
|
470
621
|
}
|
|
471
622
|
if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
|
|
472
|
-
await
|
|
623
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
|
|
473
624
|
continue;
|
|
474
625
|
}
|
|
475
626
|
return { tables: [], cacheable: false };
|
|
476
627
|
} catch {
|
|
477
628
|
if (attempt < MAX_RETRIES) {
|
|
478
|
-
await
|
|
629
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
|
|
479
630
|
continue;
|
|
480
631
|
}
|
|
481
632
|
return { tables: [], cacheable: false };
|
|
@@ -503,9 +654,9 @@ var DeeplakeApi = class {
|
|
|
503
654
|
} catch (err) {
|
|
504
655
|
lastErr = err;
|
|
505
656
|
const msg = err instanceof Error ? err.message : String(err);
|
|
506
|
-
|
|
657
|
+
log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
|
|
507
658
|
if (attempt < OUTER_BACKOFFS_MS.length) {
|
|
508
|
-
await
|
|
659
|
+
await sleep2(OUTER_BACKOFFS_MS[attempt]);
|
|
509
660
|
}
|
|
510
661
|
}
|
|
511
662
|
}
|
|
@@ -516,9 +667,9 @@ var DeeplakeApi = class {
|
|
|
516
667
|
const tbl = sqlIdent(name ?? this.tableName);
|
|
517
668
|
const tables = await this.listTables();
|
|
518
669
|
if (!tables.includes(tbl)) {
|
|
519
|
-
|
|
670
|
+
log3(`table "${tbl}" not found, creating`);
|
|
520
671
|
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);
|
|
521
|
-
|
|
672
|
+
log3(`table "${tbl}" created`);
|
|
522
673
|
if (!tables.includes(tbl))
|
|
523
674
|
this._tablesCache = [...tables, tbl];
|
|
524
675
|
}
|
|
@@ -531,9 +682,9 @@ var DeeplakeApi = class {
|
|
|
531
682
|
const safe = sqlIdent(name);
|
|
532
683
|
const tables = await this.listTables();
|
|
533
684
|
if (!tables.includes(safe)) {
|
|
534
|
-
|
|
685
|
+
log3(`table "${safe}" not found, creating`);
|
|
535
686
|
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);
|
|
536
|
-
|
|
687
|
+
log3(`table "${safe}" created`);
|
|
537
688
|
if (!tables.includes(safe))
|
|
538
689
|
this._tablesCache = [...tables, safe];
|
|
539
690
|
}
|
|
@@ -556,9 +707,9 @@ var DeeplakeApi = class {
|
|
|
556
707
|
const safe = sqlIdent(name);
|
|
557
708
|
const tables = await this.listTables();
|
|
558
709
|
if (!tables.includes(safe)) {
|
|
559
|
-
|
|
710
|
+
log3(`table "${safe}" not found, creating`);
|
|
560
711
|
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);
|
|
561
|
-
|
|
712
|
+
log3(`table "${safe}" created`);
|
|
562
713
|
if (!tables.includes(safe))
|
|
563
714
|
this._tablesCache = [...tables, safe];
|
|
564
715
|
}
|
|
@@ -569,20 +720,20 @@ var DeeplakeApi = class {
|
|
|
569
720
|
// dist/src/hooks/codex/spawn-wiki-worker.js
|
|
570
721
|
import { spawn, execSync } from "node:child_process";
|
|
571
722
|
import { fileURLToPath } from "node:url";
|
|
572
|
-
import { dirname as dirname2, join as
|
|
573
|
-
import { writeFileSync as
|
|
574
|
-
import { homedir as
|
|
723
|
+
import { dirname as dirname2, join as join8 } from "node:path";
|
|
724
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "node:fs";
|
|
725
|
+
import { homedir as homedir5, tmpdir as tmpdir2 } from "node:os";
|
|
575
726
|
|
|
576
727
|
// dist/src/utils/wiki-log.js
|
|
577
|
-
import { mkdirSync as
|
|
578
|
-
import { join as
|
|
728
|
+
import { mkdirSync as mkdirSync4, appendFileSync as appendFileSync2 } from "node:fs";
|
|
729
|
+
import { join as join6 } from "node:path";
|
|
579
730
|
function makeWikiLogger(hooksDir, filename = "deeplake-wiki.log") {
|
|
580
|
-
const path =
|
|
731
|
+
const path = join6(hooksDir, filename);
|
|
581
732
|
return {
|
|
582
733
|
path,
|
|
583
734
|
log(msg) {
|
|
584
735
|
try {
|
|
585
|
-
|
|
736
|
+
mkdirSync4(hooksDir, { recursive: true });
|
|
586
737
|
appendFileSync2(path, `[${utcTimestamp()}] ${msg}
|
|
587
738
|
`);
|
|
588
739
|
} catch {
|
|
@@ -592,18 +743,18 @@ function makeWikiLogger(hooksDir, filename = "deeplake-wiki.log") {
|
|
|
592
743
|
}
|
|
593
744
|
|
|
594
745
|
// dist/src/utils/version-check.js
|
|
595
|
-
import { readFileSync as
|
|
596
|
-
import { dirname, join as
|
|
746
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
747
|
+
import { dirname, join as join7 } from "node:path";
|
|
597
748
|
function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
598
749
|
try {
|
|
599
|
-
const pluginJson =
|
|
600
|
-
const plugin = JSON.parse(
|
|
750
|
+
const pluginJson = join7(bundleDir, "..", pluginManifestDir, "plugin.json");
|
|
751
|
+
const plugin = JSON.parse(readFileSync5(pluginJson, "utf-8"));
|
|
601
752
|
if (plugin.version)
|
|
602
753
|
return plugin.version;
|
|
603
754
|
} catch {
|
|
604
755
|
}
|
|
605
756
|
try {
|
|
606
|
-
const stamp =
|
|
757
|
+
const stamp = readFileSync5(join7(bundleDir, "..", ".hivemind_version"), "utf-8").trim();
|
|
607
758
|
if (stamp)
|
|
608
759
|
return stamp;
|
|
609
760
|
} catch {
|
|
@@ -618,9 +769,9 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
|
618
769
|
]);
|
|
619
770
|
let dir = bundleDir;
|
|
620
771
|
for (let i = 0; i < 5; i++) {
|
|
621
|
-
const candidate =
|
|
772
|
+
const candidate = join7(dir, "package.json");
|
|
622
773
|
try {
|
|
623
|
-
const pkg = JSON.parse(
|
|
774
|
+
const pkg = JSON.parse(readFileSync5(candidate, "utf-8"));
|
|
624
775
|
if (HIVEMIND_PKG_NAMES.has(pkg.name) && pkg.version)
|
|
625
776
|
return pkg.version;
|
|
626
777
|
} catch {
|
|
@@ -634,8 +785,8 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
|
634
785
|
}
|
|
635
786
|
|
|
636
787
|
// dist/src/hooks/codex/spawn-wiki-worker.js
|
|
637
|
-
var HOME =
|
|
638
|
-
var wikiLogger = makeWikiLogger(
|
|
788
|
+
var HOME = homedir5();
|
|
789
|
+
var wikiLogger = makeWikiLogger(join8(HOME, ".codex", "hooks"));
|
|
639
790
|
var WIKI_LOG = wikiLogger.path;
|
|
640
791
|
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.
|
|
641
792
|
|
|
@@ -697,11 +848,11 @@ function findCodexBin() {
|
|
|
697
848
|
function spawnCodexWikiWorker(opts) {
|
|
698
849
|
const { config, sessionId, cwd, bundleDir, reason } = opts;
|
|
699
850
|
const projectName = cwd.split("/").pop() || "unknown";
|
|
700
|
-
const tmpDir =
|
|
701
|
-
|
|
851
|
+
const tmpDir = join8(tmpdir2(), `deeplake-wiki-${sessionId}-${Date.now()}`);
|
|
852
|
+
mkdirSync5(tmpDir, { recursive: true });
|
|
702
853
|
const pluginVersion = getInstalledVersion(bundleDir, ".codex-plugin") ?? "";
|
|
703
|
-
const configFile =
|
|
704
|
-
|
|
854
|
+
const configFile = join8(tmpDir, "config.json");
|
|
855
|
+
writeFileSync4(configFile, JSON.stringify({
|
|
705
856
|
apiUrl: config.apiUrl,
|
|
706
857
|
token: config.token,
|
|
707
858
|
orgId: config.orgId,
|
|
@@ -715,11 +866,11 @@ function spawnCodexWikiWorker(opts) {
|
|
|
715
866
|
tmpDir,
|
|
716
867
|
codexBin: findCodexBin(),
|
|
717
868
|
wikiLog: WIKI_LOG,
|
|
718
|
-
hooksDir:
|
|
869
|
+
hooksDir: join8(HOME, ".codex", "hooks"),
|
|
719
870
|
promptTemplate: WIKI_PROMPT_TEMPLATE
|
|
720
871
|
}));
|
|
721
872
|
wikiLog(`${reason}: spawning summary worker for ${sessionId}`);
|
|
722
|
-
const workerPath =
|
|
873
|
+
const workerPath = join8(bundleDir, "wiki-worker.js");
|
|
723
874
|
spawn("nohup", ["node", workerPath, configFile], {
|
|
724
875
|
detached: true,
|
|
725
876
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -733,15 +884,15 @@ function bundleDirFromImportMeta(importMetaUrl) {
|
|
|
733
884
|
// dist/src/skillify/spawn-skillify-worker.js
|
|
734
885
|
import { spawn as spawn2 } from "node:child_process";
|
|
735
886
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
736
|
-
import { dirname as dirname3, join as
|
|
737
|
-
import { writeFileSync as
|
|
738
|
-
import { homedir as
|
|
887
|
+
import { dirname as dirname3, join as join10 } from "node:path";
|
|
888
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, appendFileSync as appendFileSync3, chmodSync } from "node:fs";
|
|
889
|
+
import { homedir as homedir7, tmpdir as tmpdir3 } from "node:os";
|
|
739
890
|
|
|
740
891
|
// dist/src/skillify/gate-runner.js
|
|
741
892
|
import { existsSync as existsSync3 } from "node:fs";
|
|
742
893
|
import { createRequire } from "node:module";
|
|
743
|
-
import { homedir as
|
|
744
|
-
import { join as
|
|
894
|
+
import { homedir as homedir6 } from "node:os";
|
|
895
|
+
import { join as join9 } from "node:path";
|
|
745
896
|
var requireForCp = createRequire(import.meta.url);
|
|
746
897
|
var { execFileSync: runChildProcess } = requireForCp("node:child_process");
|
|
747
898
|
var inheritedEnv = process;
|
|
@@ -753,7 +904,7 @@ function firstExistingPath(candidates) {
|
|
|
753
904
|
return null;
|
|
754
905
|
}
|
|
755
906
|
function findAgentBin(agent) {
|
|
756
|
-
const home =
|
|
907
|
+
const home = homedir6();
|
|
757
908
|
switch (agent) {
|
|
758
909
|
// /usr/bin/<name> is included in every candidate list — that's the
|
|
759
910
|
// common Linux package-manager install path (apt, dnf, pacman). Old
|
|
@@ -762,54 +913,54 @@ function findAgentBin(agent) {
|
|
|
762
913
|
// #170 caught the gap.
|
|
763
914
|
case "claude_code":
|
|
764
915
|
return firstExistingPath([
|
|
765
|
-
|
|
916
|
+
join9(home, ".claude", "local", "claude"),
|
|
766
917
|
"/usr/local/bin/claude",
|
|
767
918
|
"/usr/bin/claude",
|
|
768
|
-
|
|
769
|
-
|
|
919
|
+
join9(home, ".npm-global", "bin", "claude"),
|
|
920
|
+
join9(home, ".local", "bin", "claude"),
|
|
770
921
|
"/opt/homebrew/bin/claude"
|
|
771
|
-
]) ??
|
|
922
|
+
]) ?? join9(home, ".claude", "local", "claude");
|
|
772
923
|
case "codex":
|
|
773
924
|
return firstExistingPath([
|
|
774
925
|
"/usr/local/bin/codex",
|
|
775
926
|
"/usr/bin/codex",
|
|
776
|
-
|
|
777
|
-
|
|
927
|
+
join9(home, ".npm-global", "bin", "codex"),
|
|
928
|
+
join9(home, ".local", "bin", "codex"),
|
|
778
929
|
"/opt/homebrew/bin/codex"
|
|
779
930
|
]) ?? "/usr/local/bin/codex";
|
|
780
931
|
case "cursor":
|
|
781
932
|
return firstExistingPath([
|
|
782
933
|
"/usr/local/bin/cursor-agent",
|
|
783
934
|
"/usr/bin/cursor-agent",
|
|
784
|
-
|
|
785
|
-
|
|
935
|
+
join9(home, ".npm-global", "bin", "cursor-agent"),
|
|
936
|
+
join9(home, ".local", "bin", "cursor-agent"),
|
|
786
937
|
"/opt/homebrew/bin/cursor-agent"
|
|
787
938
|
]) ?? "/usr/local/bin/cursor-agent";
|
|
788
939
|
case "hermes":
|
|
789
940
|
return firstExistingPath([
|
|
790
|
-
|
|
941
|
+
join9(home, ".local", "bin", "hermes"),
|
|
791
942
|
"/usr/local/bin/hermes",
|
|
792
943
|
"/usr/bin/hermes",
|
|
793
|
-
|
|
944
|
+
join9(home, ".npm-global", "bin", "hermes"),
|
|
794
945
|
"/opt/homebrew/bin/hermes"
|
|
795
|
-
]) ??
|
|
946
|
+
]) ?? join9(home, ".local", "bin", "hermes");
|
|
796
947
|
case "pi":
|
|
797
948
|
return firstExistingPath([
|
|
798
|
-
|
|
949
|
+
join9(home, ".local", "bin", "pi"),
|
|
799
950
|
"/usr/local/bin/pi",
|
|
800
951
|
"/usr/bin/pi",
|
|
801
|
-
|
|
952
|
+
join9(home, ".npm-global", "bin", "pi"),
|
|
802
953
|
"/opt/homebrew/bin/pi"
|
|
803
|
-
]) ??
|
|
954
|
+
]) ?? join9(home, ".local", "bin", "pi");
|
|
804
955
|
}
|
|
805
956
|
}
|
|
806
957
|
|
|
807
958
|
// dist/src/skillify/spawn-skillify-worker.js
|
|
808
|
-
var HOME2 =
|
|
809
|
-
var SKILLIFY_LOG =
|
|
959
|
+
var HOME2 = homedir7();
|
|
960
|
+
var SKILLIFY_LOG = join10(HOME2, ".claude", "hooks", "skillify.log");
|
|
810
961
|
function skillifyLog(msg) {
|
|
811
962
|
try {
|
|
812
|
-
|
|
963
|
+
mkdirSync6(dirname3(SKILLIFY_LOG), { recursive: true });
|
|
813
964
|
appendFileSync3(SKILLIFY_LOG, `[${utcTimestamp()}] ${msg}
|
|
814
965
|
`);
|
|
815
966
|
} catch {
|
|
@@ -817,11 +968,11 @@ function skillifyLog(msg) {
|
|
|
817
968
|
}
|
|
818
969
|
function spawnSkillifyWorker(opts) {
|
|
819
970
|
const { config, cwd, projectKey, project, bundleDir, agent, scopeConfig, currentSessionId, reason } = opts;
|
|
820
|
-
const tmpDir =
|
|
821
|
-
|
|
971
|
+
const tmpDir = join10(tmpdir3(), `deeplake-skillify-${projectKey}-${Date.now()}`);
|
|
972
|
+
mkdirSync6(tmpDir, { recursive: true, mode: 448 });
|
|
822
973
|
const gateBin = findAgentBin(agent);
|
|
823
|
-
const configFile =
|
|
824
|
-
|
|
974
|
+
const configFile = join10(tmpDir, "config.json");
|
|
975
|
+
writeFileSync5(configFile, JSON.stringify({
|
|
825
976
|
apiUrl: config.apiUrl,
|
|
826
977
|
token: config.token,
|
|
827
978
|
orgId: config.orgId,
|
|
@@ -851,7 +1002,7 @@ function spawnSkillifyWorker(opts) {
|
|
|
851
1002
|
} catch {
|
|
852
1003
|
}
|
|
853
1004
|
skillifyLog(`${reason}: spawning skillify worker for project=${project} key=${projectKey}`);
|
|
854
|
-
const workerPath =
|
|
1005
|
+
const workerPath = join10(bundleDir, "skillify-worker.js");
|
|
855
1006
|
spawn2("nohup", ["node", workerPath, configFile], {
|
|
856
1007
|
detached: true,
|
|
857
1008
|
stdio: ["ignore", "ignore", "ignore"]
|
|
@@ -860,36 +1011,45 @@ function spawnSkillifyWorker(opts) {
|
|
|
860
1011
|
}
|
|
861
1012
|
|
|
862
1013
|
// dist/src/skillify/state.js
|
|
863
|
-
import { readFileSync as
|
|
1014
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, writeSync, mkdirSync as mkdirSync7, renameSync as renameSync3, rmdirSync, existsSync as existsSync5, lstatSync, unlinkSync as unlinkSync3, openSync as openSync2, closeSync as closeSync2 } from "node:fs";
|
|
864
1015
|
import { execSync as execSync2 } from "node:child_process";
|
|
865
|
-
import { homedir as homedir7 } from "node:os";
|
|
866
1016
|
import { createHash } from "node:crypto";
|
|
867
|
-
import { join as
|
|
1017
|
+
import { join as join13, basename } from "node:path";
|
|
1018
|
+
|
|
1019
|
+
// dist/src/skillify/legacy-migration.js
|
|
1020
|
+
import { existsSync as existsSync4, renameSync as renameSync2 } from "node:fs";
|
|
1021
|
+
import { dirname as dirname4, join as join12 } from "node:path";
|
|
1022
|
+
|
|
1023
|
+
// dist/src/skillify/state-dir.js
|
|
1024
|
+
import { homedir as homedir8 } from "node:os";
|
|
1025
|
+
import { join as join11 } from "node:path";
|
|
1026
|
+
function getStateDir() {
|
|
1027
|
+
const override = process.env.HIVEMIND_STATE_DIR?.trim();
|
|
1028
|
+
return override && override.length > 0 ? override : join11(homedir8(), ".deeplake", "state", "skillify");
|
|
1029
|
+
}
|
|
868
1030
|
|
|
869
1031
|
// dist/src/skillify/legacy-migration.js
|
|
870
|
-
import { existsSync as existsSync4, renameSync } from "node:fs";
|
|
871
|
-
import { homedir as homedir6 } from "node:os";
|
|
872
|
-
import { join as join9 } from "node:path";
|
|
873
1032
|
var dlog = (msg) => log("skillify-migrate", msg);
|
|
874
1033
|
var attempted = false;
|
|
875
1034
|
function migrateLegacyStateDir() {
|
|
1035
|
+
if (process.env.HIVEMIND_STATE_DIR?.trim())
|
|
1036
|
+
return;
|
|
876
1037
|
if (attempted)
|
|
877
1038
|
return;
|
|
878
1039
|
attempted = true;
|
|
879
|
-
const
|
|
880
|
-
const legacy =
|
|
881
|
-
const current = join9(root, "skillify");
|
|
1040
|
+
const current = getStateDir();
|
|
1041
|
+
const legacy = join12(dirname4(current), "skilify");
|
|
882
1042
|
if (!existsSync4(legacy))
|
|
883
1043
|
return;
|
|
884
1044
|
if (existsSync4(current))
|
|
885
1045
|
return;
|
|
886
1046
|
try {
|
|
887
|
-
|
|
1047
|
+
renameSync2(legacy, current);
|
|
888
1048
|
dlog(`migrated ${legacy} -> ${current}`);
|
|
889
1049
|
} catch (err) {
|
|
890
1050
|
const code = err.code;
|
|
891
|
-
if (code === "EXDEV" || code === "EPERM") {
|
|
892
|
-
dlog(`migration
|
|
1051
|
+
if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
|
|
1052
|
+
dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
|
|
893
1053
|
return;
|
|
894
1054
|
}
|
|
895
1055
|
throw err;
|
|
@@ -898,17 +1058,16 @@ function migrateLegacyStateDir() {
|
|
|
898
1058
|
|
|
899
1059
|
// dist/src/skillify/state.js
|
|
900
1060
|
var dlog2 = (msg) => log("skillify-state", msg);
|
|
901
|
-
var STATE_DIR = join10(homedir7(), ".deeplake", "state", "skillify");
|
|
902
1061
|
var YIELD_BUF = new Int32Array(new SharedArrayBuffer(4));
|
|
903
1062
|
var TRIGGER_THRESHOLD = (() => {
|
|
904
1063
|
const n = Number(process.env.HIVEMIND_SKILLIFY_EVERY_N_TURNS ?? "");
|
|
905
1064
|
return Number.isInteger(n) && n > 0 ? n : 20;
|
|
906
1065
|
})();
|
|
907
1066
|
function statePath(projectKey) {
|
|
908
|
-
return
|
|
1067
|
+
return join13(getStateDir(), `${projectKey}.json`);
|
|
909
1068
|
}
|
|
910
|
-
function
|
|
911
|
-
return
|
|
1069
|
+
function lockPath2(projectKey) {
|
|
1070
|
+
return join13(getStateDir(), `${projectKey}.lock`);
|
|
912
1071
|
}
|
|
913
1072
|
var DEFAULT_PORTS = {
|
|
914
1073
|
http: "80",
|
|
@@ -957,35 +1116,35 @@ function readState(projectKey) {
|
|
|
957
1116
|
if (!existsSync5(p))
|
|
958
1117
|
return null;
|
|
959
1118
|
try {
|
|
960
|
-
return JSON.parse(
|
|
1119
|
+
return JSON.parse(readFileSync6(p, "utf-8"));
|
|
961
1120
|
} catch {
|
|
962
1121
|
return null;
|
|
963
1122
|
}
|
|
964
1123
|
}
|
|
965
1124
|
function writeState(projectKey, state) {
|
|
966
1125
|
migrateLegacyStateDir();
|
|
967
|
-
|
|
1126
|
+
mkdirSync7(getStateDir(), { recursive: true });
|
|
968
1127
|
const p = statePath(projectKey);
|
|
969
1128
|
const tmp = `${p}.${process.pid}.${Date.now()}.tmp`;
|
|
970
|
-
|
|
971
|
-
|
|
1129
|
+
writeFileSync6(tmp, JSON.stringify(state, null, 2));
|
|
1130
|
+
renameSync3(tmp, p);
|
|
972
1131
|
}
|
|
973
1132
|
function withRmwLock(projectKey, fn) {
|
|
974
1133
|
migrateLegacyStateDir();
|
|
975
|
-
|
|
976
|
-
const rmw =
|
|
1134
|
+
mkdirSync7(getStateDir(), { recursive: true });
|
|
1135
|
+
const rmw = lockPath2(projectKey) + ".rmw";
|
|
977
1136
|
const deadline = Date.now() + 2e3;
|
|
978
1137
|
let fd = null;
|
|
979
1138
|
while (fd === null) {
|
|
980
1139
|
try {
|
|
981
|
-
fd =
|
|
1140
|
+
fd = openSync2(rmw, "wx");
|
|
982
1141
|
} catch (e) {
|
|
983
1142
|
if (e.code !== "EEXIST")
|
|
984
1143
|
throw e;
|
|
985
1144
|
if (Date.now() > deadline) {
|
|
986
1145
|
dlog2(`rmw lock deadline exceeded for ${projectKey}, reclaiming stale lock`);
|
|
987
1146
|
try {
|
|
988
|
-
|
|
1147
|
+
unlinkSync3(rmw);
|
|
989
1148
|
} catch (unlinkErr) {
|
|
990
1149
|
dlog2(`stale rmw lock unlink failed for ${projectKey}: ${unlinkErr.message}`);
|
|
991
1150
|
}
|
|
@@ -997,9 +1156,9 @@ function withRmwLock(projectKey, fn) {
|
|
|
997
1156
|
try {
|
|
998
1157
|
return fn();
|
|
999
1158
|
} finally {
|
|
1000
|
-
|
|
1159
|
+
closeSync2(fd);
|
|
1001
1160
|
try {
|
|
1002
|
-
|
|
1161
|
+
unlinkSync3(rmw);
|
|
1003
1162
|
} catch (unlinkErr) {
|
|
1004
1163
|
dlog2(`rmw lock cleanup failed for ${projectKey}: ${unlinkErr.message}`);
|
|
1005
1164
|
}
|
|
@@ -1015,29 +1174,43 @@ function resetCounter(projectKey) {
|
|
|
1015
1174
|
}
|
|
1016
1175
|
function tryAcquireWorkerLock(projectKey, maxAgeMs = 10 * 60 * 1e3) {
|
|
1017
1176
|
migrateLegacyStateDir();
|
|
1018
|
-
|
|
1019
|
-
const p =
|
|
1177
|
+
mkdirSync7(getStateDir(), { recursive: true });
|
|
1178
|
+
const p = lockPath2(projectKey);
|
|
1020
1179
|
if (existsSync5(p)) {
|
|
1021
1180
|
try {
|
|
1022
|
-
const ageMs = Date.now() - parseInt(
|
|
1181
|
+
const ageMs = Date.now() - parseInt(readFileSync6(p, "utf-8"), 10);
|
|
1023
1182
|
if (Number.isFinite(ageMs) && ageMs < maxAgeMs)
|
|
1024
1183
|
return false;
|
|
1025
1184
|
} catch (readErr) {
|
|
1026
1185
|
dlog2(`worker lock unreadable for ${projectKey}, treating as stale: ${readErr.message}`);
|
|
1027
1186
|
}
|
|
1028
1187
|
try {
|
|
1029
|
-
|
|
1188
|
+
unlinkSync3(p);
|
|
1030
1189
|
} catch (unlinkErr) {
|
|
1031
|
-
|
|
1032
|
-
|
|
1190
|
+
if (unlinkErr?.code !== "EISDIR" && unlinkErr?.code !== "EPERM" && unlinkErr?.code !== "ENOENT") {
|
|
1191
|
+
dlog2(`could not unlink stale worker lock for ${projectKey}: ${unlinkErr.message}`);
|
|
1192
|
+
return false;
|
|
1193
|
+
}
|
|
1194
|
+
let isDir = false;
|
|
1195
|
+
try {
|
|
1196
|
+
isDir = lstatSync(p).isDirectory();
|
|
1197
|
+
} catch {
|
|
1198
|
+
}
|
|
1199
|
+
if (isDir) {
|
|
1200
|
+
try {
|
|
1201
|
+
rmdirSync(p);
|
|
1202
|
+
} catch (rmErr) {
|
|
1203
|
+
dlog2(`rmdir stale lock skipped for ${projectKey}: ${rmErr.message}`);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1033
1206
|
}
|
|
1034
1207
|
}
|
|
1035
1208
|
try {
|
|
1036
|
-
const fd =
|
|
1209
|
+
const fd = openSync2(p, "wx");
|
|
1037
1210
|
try {
|
|
1038
1211
|
writeSync(fd, String(Date.now()));
|
|
1039
1212
|
} finally {
|
|
1040
|
-
|
|
1213
|
+
closeSync2(fd);
|
|
1041
1214
|
}
|
|
1042
1215
|
return true;
|
|
1043
1216
|
} catch {
|
|
@@ -1045,26 +1218,27 @@ function tryAcquireWorkerLock(projectKey, maxAgeMs = 10 * 60 * 1e3) {
|
|
|
1045
1218
|
}
|
|
1046
1219
|
}
|
|
1047
1220
|
function releaseWorkerLock(projectKey) {
|
|
1048
|
-
const p =
|
|
1221
|
+
const p = lockPath2(projectKey);
|
|
1049
1222
|
try {
|
|
1050
|
-
|
|
1223
|
+
unlinkSync3(p);
|
|
1051
1224
|
} catch {
|
|
1052
1225
|
}
|
|
1053
1226
|
}
|
|
1054
1227
|
|
|
1055
1228
|
// dist/src/skillify/scope-config.js
|
|
1056
|
-
import { existsSync as existsSync6, mkdirSync as
|
|
1057
|
-
import {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1229
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
1230
|
+
import { join as join14 } from "node:path";
|
|
1231
|
+
function configPath() {
|
|
1232
|
+
return join14(getStateDir(), "config.json");
|
|
1233
|
+
}
|
|
1061
1234
|
var DEFAULT = { scope: "me", team: [], install: "project" };
|
|
1062
1235
|
function loadScopeConfig() {
|
|
1063
1236
|
migrateLegacyStateDir();
|
|
1237
|
+
const CONFIG_PATH = configPath();
|
|
1064
1238
|
if (!existsSync6(CONFIG_PATH))
|
|
1065
1239
|
return DEFAULT;
|
|
1066
1240
|
try {
|
|
1067
|
-
const raw = JSON.parse(
|
|
1241
|
+
const raw = JSON.parse(readFileSync7(CONFIG_PATH, "utf-8"));
|
|
1068
1242
|
const scope = raw.scope === "team" ? "team" : raw.scope === "org" ? "team" : "me";
|
|
1069
1243
|
const team = Array.isArray(raw.team) ? raw.team.filter((s) => typeof s === "string") : [];
|
|
1070
1244
|
const install = raw.install === "global" ? "global" : "project";
|
|
@@ -1115,39 +1289,39 @@ function forceSessionEndTrigger(opts) {
|
|
|
1115
1289
|
}
|
|
1116
1290
|
|
|
1117
1291
|
// dist/src/hooks/summary-state.js
|
|
1118
|
-
import { readFileSync as
|
|
1292
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync8, writeSync as writeSync2, mkdirSync as mkdirSync9, renameSync as renameSync4, existsSync as existsSync7, unlinkSync as unlinkSync4, openSync as openSync3, closeSync as closeSync3 } from "node:fs";
|
|
1119
1293
|
import { homedir as homedir9 } from "node:os";
|
|
1120
|
-
import { join as
|
|
1294
|
+
import { join as join15 } from "node:path";
|
|
1121
1295
|
var dlog3 = (msg) => log("summary-state", msg);
|
|
1122
|
-
var
|
|
1296
|
+
var STATE_DIR = join15(homedir9(), ".claude", "hooks", "summary-state");
|
|
1123
1297
|
var YIELD_BUF2 = new Int32Array(new SharedArrayBuffer(4));
|
|
1124
|
-
function
|
|
1125
|
-
return
|
|
1298
|
+
function lockPath3(sessionId) {
|
|
1299
|
+
return join15(STATE_DIR, `${sessionId}.lock`);
|
|
1126
1300
|
}
|
|
1127
1301
|
function tryAcquireLock(sessionId, maxAgeMs = 10 * 60 * 1e3) {
|
|
1128
|
-
|
|
1129
|
-
const p =
|
|
1302
|
+
mkdirSync9(STATE_DIR, { recursive: true });
|
|
1303
|
+
const p = lockPath3(sessionId);
|
|
1130
1304
|
if (existsSync7(p)) {
|
|
1131
1305
|
try {
|
|
1132
|
-
const ageMs = Date.now() - parseInt(
|
|
1306
|
+
const ageMs = Date.now() - parseInt(readFileSync8(p, "utf-8"), 10);
|
|
1133
1307
|
if (Number.isFinite(ageMs) && ageMs < maxAgeMs)
|
|
1134
1308
|
return false;
|
|
1135
1309
|
} catch (readErr) {
|
|
1136
1310
|
dlog3(`lock file unreadable for ${sessionId}, treating as stale: ${readErr.message}`);
|
|
1137
1311
|
}
|
|
1138
1312
|
try {
|
|
1139
|
-
|
|
1313
|
+
unlinkSync4(p);
|
|
1140
1314
|
} catch (unlinkErr) {
|
|
1141
1315
|
dlog3(`could not unlink stale lock for ${sessionId}: ${unlinkErr.message}`);
|
|
1142
1316
|
return false;
|
|
1143
1317
|
}
|
|
1144
1318
|
}
|
|
1145
1319
|
try {
|
|
1146
|
-
const fd =
|
|
1320
|
+
const fd = openSync3(p, "wx");
|
|
1147
1321
|
try {
|
|
1148
1322
|
writeSync2(fd, String(Date.now()));
|
|
1149
1323
|
} finally {
|
|
1150
|
-
|
|
1324
|
+
closeSync3(fd);
|
|
1151
1325
|
}
|
|
1152
1326
|
return true;
|
|
1153
1327
|
} catch (e) {
|
|
@@ -1158,7 +1332,7 @@ function tryAcquireLock(sessionId, maxAgeMs = 10 * 60 * 1e3) {
|
|
|
1158
1332
|
}
|
|
1159
1333
|
function releaseLock(sessionId) {
|
|
1160
1334
|
try {
|
|
1161
|
-
|
|
1335
|
+
unlinkSync4(lockPath3(sessionId));
|
|
1162
1336
|
} catch (e) {
|
|
1163
1337
|
if (e?.code !== "ENOENT") {
|
|
1164
1338
|
dlog3(`releaseLock unlink failed for ${sessionId}: ${e.message}`);
|
|
@@ -1175,8 +1349,8 @@ function buildSessionPath(config, sessionId) {
|
|
|
1175
1349
|
// dist/src/embeddings/client.js
|
|
1176
1350
|
import { connect } from "node:net";
|
|
1177
1351
|
import { spawn as spawn3 } from "node:child_process";
|
|
1178
|
-
import { openSync as openSync4, closeSync as closeSync4, writeSync as writeSync3, unlinkSync as
|
|
1179
|
-
import { homedir as
|
|
1352
|
+
import { openSync as openSync4, closeSync as closeSync4, writeSync as writeSync3, unlinkSync as unlinkSync5, existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
|
|
1353
|
+
import { homedir as homedir10 } from "node:os";
|
|
1180
1354
|
import { join as join16 } from "node:path";
|
|
1181
1355
|
|
|
1182
1356
|
// dist/src/embeddings/protocol.js
|
|
@@ -1190,233 +1364,13 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
|
|
|
1190
1364
|
return `${dir}/hivemind-embed-${uid}.pid`;
|
|
1191
1365
|
}
|
|
1192
1366
|
|
|
1193
|
-
// dist/src/notifications/queue.js
|
|
1194
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, renameSync as renameSync4, mkdirSync as mkdirSync8, openSync as openSync3, closeSync as closeSync3, unlinkSync as unlinkSync3, statSync } from "node:fs";
|
|
1195
|
-
import { join as join13, resolve } from "node:path";
|
|
1196
|
-
import { homedir as homedir10 } from "node:os";
|
|
1197
|
-
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
1198
|
-
var log3 = (msg) => log("notifications-queue", msg);
|
|
1199
|
-
var LOCK_RETRY_MAX = 50;
|
|
1200
|
-
var LOCK_RETRY_BASE_MS = 5;
|
|
1201
|
-
var LOCK_STALE_MS = 5e3;
|
|
1202
|
-
function queuePath() {
|
|
1203
|
-
return join13(homedir10(), ".deeplake", "notifications-queue.json");
|
|
1204
|
-
}
|
|
1205
|
-
function lockPath3() {
|
|
1206
|
-
return `${queuePath()}.lock`;
|
|
1207
|
-
}
|
|
1208
|
-
function readQueue() {
|
|
1209
|
-
try {
|
|
1210
|
-
const raw = readFileSync7(queuePath(), "utf-8");
|
|
1211
|
-
const parsed = JSON.parse(raw);
|
|
1212
|
-
if (!parsed || !Array.isArray(parsed.queue)) {
|
|
1213
|
-
log3(`queue malformed \u2192 treating as empty`);
|
|
1214
|
-
return { queue: [] };
|
|
1215
|
-
}
|
|
1216
|
-
return { queue: parsed.queue };
|
|
1217
|
-
} catch {
|
|
1218
|
-
return { queue: [] };
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
function _isQueuePathInsideHome(path, home) {
|
|
1222
|
-
const r = resolve(path);
|
|
1223
|
-
const h = resolve(home);
|
|
1224
|
-
return r.startsWith(h + "/") || r === h;
|
|
1225
|
-
}
|
|
1226
|
-
function writeQueue(q) {
|
|
1227
|
-
const path = queuePath();
|
|
1228
|
-
const home = resolve(homedir10());
|
|
1229
|
-
if (!_isQueuePathInsideHome(path, home)) {
|
|
1230
|
-
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
|
|
1231
|
-
}
|
|
1232
|
-
mkdirSync8(join13(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
1233
|
-
const tmp = `${path}.${process.pid}.tmp`;
|
|
1234
|
-
writeFileSync7(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
1235
|
-
renameSync4(tmp, path);
|
|
1236
|
-
}
|
|
1237
|
-
async function withQueueLock(fn) {
|
|
1238
|
-
const path = lockPath3();
|
|
1239
|
-
mkdirSync8(join13(homedir10(), ".deeplake"), { recursive: true, mode: 448 });
|
|
1240
|
-
let fd = null;
|
|
1241
|
-
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
1242
|
-
try {
|
|
1243
|
-
fd = openSync3(path, "wx", 384);
|
|
1244
|
-
break;
|
|
1245
|
-
} catch (e) {
|
|
1246
|
-
const code = e.code;
|
|
1247
|
-
if (code !== "EEXIST")
|
|
1248
|
-
throw e;
|
|
1249
|
-
try {
|
|
1250
|
-
const age = Date.now() - statSync(path).mtimeMs;
|
|
1251
|
-
if (age > LOCK_STALE_MS) {
|
|
1252
|
-
unlinkSync3(path);
|
|
1253
|
-
continue;
|
|
1254
|
-
}
|
|
1255
|
-
} catch {
|
|
1256
|
-
}
|
|
1257
|
-
const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
|
|
1258
|
-
await sleep2(delay);
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
if (fd === null) {
|
|
1262
|
-
log3(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
|
|
1263
|
-
return fn();
|
|
1264
|
-
}
|
|
1265
|
-
try {
|
|
1266
|
-
return fn();
|
|
1267
|
-
} finally {
|
|
1268
|
-
try {
|
|
1269
|
-
closeSync3(fd);
|
|
1270
|
-
} catch {
|
|
1271
|
-
}
|
|
1272
|
-
try {
|
|
1273
|
-
unlinkSync3(path);
|
|
1274
|
-
} catch {
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
function sameDedupKey(a, b) {
|
|
1279
|
-
if (a.id !== b.id)
|
|
1280
|
-
return false;
|
|
1281
|
-
return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
|
|
1282
|
-
}
|
|
1283
|
-
async function enqueueNotification(n) {
|
|
1284
|
-
await withQueueLock(() => {
|
|
1285
|
-
const q = readQueue();
|
|
1286
|
-
if (q.queue.some((existing) => sameDedupKey(existing, n))) {
|
|
1287
|
-
return;
|
|
1288
|
-
}
|
|
1289
|
-
q.queue.push(n);
|
|
1290
|
-
writeQueue(q);
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
// dist/src/embeddings/disable.js
|
|
1295
|
-
import { createRequire as createRequire2 } from "node:module";
|
|
1296
|
-
import { homedir as homedir12 } from "node:os";
|
|
1297
|
-
import { join as join15 } from "node:path";
|
|
1298
|
-
import { pathToFileURL } from "node:url";
|
|
1299
|
-
|
|
1300
|
-
// dist/src/user-config.js
|
|
1301
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync9, readFileSync as readFileSync8, renameSync as renameSync5, writeFileSync as writeFileSync8 } from "node:fs";
|
|
1302
|
-
import { homedir as homedir11 } from "node:os";
|
|
1303
|
-
import { dirname as dirname4, join as join14 } from "node:path";
|
|
1304
|
-
var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join14(homedir11(), ".deeplake", "config.json");
|
|
1305
|
-
var _cache = null;
|
|
1306
|
-
var _migrated = false;
|
|
1307
|
-
function readUserConfig() {
|
|
1308
|
-
if (_cache !== null)
|
|
1309
|
-
return _cache;
|
|
1310
|
-
const path = _configPath();
|
|
1311
|
-
if (!existsSync8(path)) {
|
|
1312
|
-
_cache = {};
|
|
1313
|
-
return _cache;
|
|
1314
|
-
}
|
|
1315
|
-
try {
|
|
1316
|
-
const raw = readFileSync8(path, "utf-8");
|
|
1317
|
-
const parsed = JSON.parse(raw);
|
|
1318
|
-
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1319
|
-
} catch {
|
|
1320
|
-
_cache = {};
|
|
1321
|
-
}
|
|
1322
|
-
return _cache;
|
|
1323
|
-
}
|
|
1324
|
-
function writeUserConfig(patch) {
|
|
1325
|
-
const current = readUserConfig();
|
|
1326
|
-
const merged = deepMerge(current, patch);
|
|
1327
|
-
const path = _configPath();
|
|
1328
|
-
const dir = dirname4(path);
|
|
1329
|
-
if (!existsSync8(dir))
|
|
1330
|
-
mkdirSync9(dir, { recursive: true });
|
|
1331
|
-
const tmp = `${path}.tmp.${process.pid}`;
|
|
1332
|
-
writeFileSync8(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1333
|
-
renameSync5(tmp, path);
|
|
1334
|
-
_cache = merged;
|
|
1335
|
-
return merged;
|
|
1336
|
-
}
|
|
1337
|
-
function getEmbeddingsEnabled() {
|
|
1338
|
-
const cfg = readUserConfig();
|
|
1339
|
-
if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
|
|
1340
|
-
return cfg.embeddings.enabled;
|
|
1341
|
-
}
|
|
1342
|
-
if (_migrated) {
|
|
1343
|
-
return migrationValueFromEnv();
|
|
1344
|
-
}
|
|
1345
|
-
_migrated = true;
|
|
1346
|
-
const enabled = migrationValueFromEnv();
|
|
1347
|
-
try {
|
|
1348
|
-
writeUserConfig({ embeddings: { enabled } });
|
|
1349
|
-
} catch {
|
|
1350
|
-
_cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
|
|
1351
|
-
}
|
|
1352
|
-
return enabled;
|
|
1353
|
-
}
|
|
1354
|
-
function migrationValueFromEnv() {
|
|
1355
|
-
const raw = process.env.HIVEMIND_EMBEDDINGS;
|
|
1356
|
-
if (raw === void 0)
|
|
1357
|
-
return false;
|
|
1358
|
-
if (raw === "false")
|
|
1359
|
-
return false;
|
|
1360
|
-
return true;
|
|
1361
|
-
}
|
|
1362
|
-
function isPlainObject(value) {
|
|
1363
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1364
|
-
}
|
|
1365
|
-
function deepMerge(base, patch) {
|
|
1366
|
-
const out = { ...base };
|
|
1367
|
-
for (const key of Object.keys(patch)) {
|
|
1368
|
-
const patchVal = patch[key];
|
|
1369
|
-
const baseVal = base[key];
|
|
1370
|
-
if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
|
|
1371
|
-
out[key] = { ...baseVal, ...patchVal };
|
|
1372
|
-
} else if (patchVal !== void 0) {
|
|
1373
|
-
out[key] = patchVal;
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
return out;
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
// dist/src/embeddings/disable.js
|
|
1380
|
-
var cachedStatus = null;
|
|
1381
|
-
function defaultResolveTransformers() {
|
|
1382
|
-
const sharedDir = join15(homedir12(), ".hivemind", "embed-deps");
|
|
1383
|
-
try {
|
|
1384
|
-
createRequire2(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
|
|
1385
|
-
return;
|
|
1386
|
-
} catch {
|
|
1387
|
-
}
|
|
1388
|
-
createRequire2(import.meta.url).resolve("@huggingface/transformers");
|
|
1389
|
-
}
|
|
1390
|
-
var _resolve = defaultResolveTransformers;
|
|
1391
|
-
var _readEnabled = getEmbeddingsEnabled;
|
|
1392
|
-
function detectStatus() {
|
|
1393
|
-
if (!_readEnabled())
|
|
1394
|
-
return "user-disabled";
|
|
1395
|
-
try {
|
|
1396
|
-
_resolve();
|
|
1397
|
-
return "enabled";
|
|
1398
|
-
} catch {
|
|
1399
|
-
return "no-transformers";
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
function embeddingsStatus() {
|
|
1403
|
-
if (cachedStatus !== null)
|
|
1404
|
-
return cachedStatus;
|
|
1405
|
-
cachedStatus = detectStatus();
|
|
1406
|
-
return cachedStatus;
|
|
1407
|
-
}
|
|
1408
|
-
function embeddingsDisabled() {
|
|
1409
|
-
return embeddingsStatus() !== "enabled";
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
1367
|
// dist/src/embeddings/client.js
|
|
1413
|
-
var SHARED_DAEMON_PATH = join16(
|
|
1368
|
+
var SHARED_DAEMON_PATH = join16(homedir10(), ".hivemind", "embed-deps", "embed-daemon.js");
|
|
1414
1369
|
var log4 = (m) => log("embed-client", m);
|
|
1415
1370
|
function getUid() {
|
|
1416
1371
|
const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
|
|
1417
1372
|
return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
|
|
1418
1373
|
}
|
|
1419
|
-
var _signalledMissingDeps = false;
|
|
1420
1374
|
var _recycledStuckDaemon = false;
|
|
1421
1375
|
var EmbedClient = class {
|
|
1422
1376
|
socketPath;
|
|
@@ -1433,7 +1387,7 @@ var EmbedClient = class {
|
|
|
1433
1387
|
this.socketPath = socketPathFor(uid, dir);
|
|
1434
1388
|
this.pidPath = pidPathFor(uid, dir);
|
|
1435
1389
|
this.timeoutMs = opts.timeoutMs ?? DEFAULT_CLIENT_TIMEOUT_MS;
|
|
1436
|
-
this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (
|
|
1390
|
+
this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync8(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
|
|
1437
1391
|
this.autoSpawn = opts.autoSpawn ?? true;
|
|
1438
1392
|
this.spawnWaitMs = opts.spawnWaitMs ?? 5e3;
|
|
1439
1393
|
}
|
|
@@ -1514,7 +1468,7 @@ var EmbedClient = class {
|
|
|
1514
1468
|
async waitForDaemonReady() {
|
|
1515
1469
|
const deadline = Date.now() + this.spawnWaitMs;
|
|
1516
1470
|
while (Date.now() < deadline) {
|
|
1517
|
-
if (
|
|
1471
|
+
if (existsSync8(this.socketPath))
|
|
1518
1472
|
return;
|
|
1519
1473
|
await new Promise((r) => setTimeout(r, 50));
|
|
1520
1474
|
}
|
|
@@ -1557,7 +1511,7 @@ var EmbedClient = class {
|
|
|
1557
1511
|
this.recycleDaemon(hello.pid);
|
|
1558
1512
|
return true;
|
|
1559
1513
|
}
|
|
1560
|
-
if (hello.daemonPath !== this.daemonEntry && !
|
|
1514
|
+
if (hello.daemonPath !== this.daemonEntry && !existsSync8(hello.daemonPath)) {
|
|
1561
1515
|
_recycledStuckDaemon = true;
|
|
1562
1516
|
log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
|
|
1563
1517
|
this.recycleDaemon(hello.pid);
|
|
@@ -1569,37 +1523,21 @@ var EmbedClient = class {
|
|
|
1569
1523
|
/**
|
|
1570
1524
|
* On a transformers-missing error from the daemon, SIGTERM the stuck
|
|
1571
1525
|
* daemon (the bundle daemon that can't find its deps) and clear
|
|
1572
|
-
* sock/pid so the next call spawns fresh.
|
|
1573
|
-
*
|
|
1574
|
-
*
|
|
1575
|
-
*
|
|
1576
|
-
*
|
|
1526
|
+
* sock/pid so the next call spawns fresh.
|
|
1527
|
+
*
|
|
1528
|
+
* Previously this also enqueued a user-visible "Hivemind embeddings
|
|
1529
|
+
* disabled — deps missing" notification telling the user to run
|
|
1530
|
+
* `hivemind embeddings install`. The notification was removed because
|
|
1531
|
+
* (a) the recycle alone often fixes the issue silently, and (b) the
|
|
1532
|
+
* warning kept stacking on top of the primary session-start banner
|
|
1533
|
+
* which clashed with the single-slot priority model. The `detail`
|
|
1534
|
+
* argument is retained for future telemetry / debug logging.
|
|
1577
1535
|
*/
|
|
1578
|
-
handleTransformersMissing(
|
|
1536
|
+
handleTransformersMissing(_detail) {
|
|
1579
1537
|
if (!_recycledStuckDaemon) {
|
|
1580
1538
|
_recycledStuckDaemon = true;
|
|
1581
1539
|
this.recycleDaemon(null);
|
|
1582
1540
|
}
|
|
1583
|
-
if (_signalledMissingDeps)
|
|
1584
|
-
return;
|
|
1585
|
-
_signalledMissingDeps = true;
|
|
1586
|
-
let status;
|
|
1587
|
-
try {
|
|
1588
|
-
status = embeddingsStatus();
|
|
1589
|
-
} catch {
|
|
1590
|
-
status = "enabled";
|
|
1591
|
-
}
|
|
1592
|
-
if (status === "user-disabled")
|
|
1593
|
-
return;
|
|
1594
|
-
enqueueNotification({
|
|
1595
|
-
id: "embed-deps-missing",
|
|
1596
|
-
severity: "warn",
|
|
1597
|
-
title: "Hivemind embeddings disabled \u2014 deps missing",
|
|
1598
|
-
body: `Semantic memory search is off because @huggingface/transformers is not installed where the daemon can find it. Run \`hivemind embeddings install\` to enable.`,
|
|
1599
|
-
dedupKey: { reason: "transformers-missing", detail: detail.slice(0, 200) }
|
|
1600
|
-
}).catch((e) => {
|
|
1601
|
-
log4(`enqueue embed-deps-missing failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
1602
|
-
});
|
|
1603
1541
|
}
|
|
1604
1542
|
/**
|
|
1605
1543
|
* Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
|
|
@@ -1622,7 +1560,7 @@ var EmbedClient = class {
|
|
|
1622
1560
|
} catch {
|
|
1623
1561
|
}
|
|
1624
1562
|
}
|
|
1625
|
-
if (Number.isFinite(pid) && pid !== null && pid > 0 &&
|
|
1563
|
+
if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync8(this.socketPath)) {
|
|
1626
1564
|
try {
|
|
1627
1565
|
process.kill(pid, "SIGTERM");
|
|
1628
1566
|
} catch {
|
|
@@ -1631,11 +1569,11 @@ var EmbedClient = class {
|
|
|
1631
1569
|
log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
|
|
1632
1570
|
}
|
|
1633
1571
|
try {
|
|
1634
|
-
|
|
1572
|
+
unlinkSync5(this.socketPath);
|
|
1635
1573
|
} catch {
|
|
1636
1574
|
}
|
|
1637
1575
|
try {
|
|
1638
|
-
|
|
1576
|
+
unlinkSync5(this.pidPath);
|
|
1639
1577
|
} catch {
|
|
1640
1578
|
}
|
|
1641
1579
|
}
|
|
@@ -1686,7 +1624,7 @@ var EmbedClient = class {
|
|
|
1686
1624
|
} catch (e) {
|
|
1687
1625
|
if (this.isPidFileStale()) {
|
|
1688
1626
|
try {
|
|
1689
|
-
|
|
1627
|
+
unlinkSync5(this.pidPath);
|
|
1690
1628
|
} catch {
|
|
1691
1629
|
}
|
|
1692
1630
|
try {
|
|
@@ -1699,11 +1637,11 @@ var EmbedClient = class {
|
|
|
1699
1637
|
return;
|
|
1700
1638
|
}
|
|
1701
1639
|
}
|
|
1702
|
-
if (!this.daemonEntry || !
|
|
1640
|
+
if (!this.daemonEntry || !existsSync8(this.daemonEntry)) {
|
|
1703
1641
|
log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
|
|
1704
1642
|
try {
|
|
1705
1643
|
closeSync4(fd);
|
|
1706
|
-
|
|
1644
|
+
unlinkSync5(this.pidPath);
|
|
1707
1645
|
} catch {
|
|
1708
1646
|
}
|
|
1709
1647
|
return;
|
|
@@ -1742,7 +1680,7 @@ var EmbedClient = class {
|
|
|
1742
1680
|
while (Date.now() < deadline) {
|
|
1743
1681
|
await sleep3(delay);
|
|
1744
1682
|
delay = Math.min(delay * 1.5, 300);
|
|
1745
|
-
if (!
|
|
1683
|
+
if (!existsSync8(this.socketPath))
|
|
1746
1684
|
continue;
|
|
1747
1685
|
try {
|
|
1748
1686
|
return await this.connectOnce();
|
|
@@ -1806,12 +1744,130 @@ function embeddingSqlLiteral(vec) {
|
|
|
1806
1744
|
return `ARRAY[${parts.join(",")}]::float4[]`;
|
|
1807
1745
|
}
|
|
1808
1746
|
|
|
1747
|
+
// dist/src/embeddings/disable.js
|
|
1748
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
1749
|
+
import { homedir as homedir12 } from "node:os";
|
|
1750
|
+
import { join as join18 } from "node:path";
|
|
1751
|
+
import { pathToFileURL } from "node:url";
|
|
1752
|
+
|
|
1753
|
+
// dist/src/user-config.js
|
|
1754
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "node:fs";
|
|
1755
|
+
import { homedir as homedir11 } from "node:os";
|
|
1756
|
+
import { dirname as dirname5, join as join17 } from "node:path";
|
|
1757
|
+
var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join17(homedir11(), ".deeplake", "config.json");
|
|
1758
|
+
var _cache = null;
|
|
1759
|
+
var _migrated = false;
|
|
1760
|
+
function readUserConfig() {
|
|
1761
|
+
if (_cache !== null)
|
|
1762
|
+
return _cache;
|
|
1763
|
+
const path = _configPath();
|
|
1764
|
+
if (!existsSync9(path)) {
|
|
1765
|
+
_cache = {};
|
|
1766
|
+
return _cache;
|
|
1767
|
+
}
|
|
1768
|
+
try {
|
|
1769
|
+
const raw = readFileSync10(path, "utf-8");
|
|
1770
|
+
const parsed = JSON.parse(raw);
|
|
1771
|
+
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1772
|
+
} catch {
|
|
1773
|
+
_cache = {};
|
|
1774
|
+
}
|
|
1775
|
+
return _cache;
|
|
1776
|
+
}
|
|
1777
|
+
function writeUserConfig(patch) {
|
|
1778
|
+
const current = readUserConfig();
|
|
1779
|
+
const merged = deepMerge(current, patch);
|
|
1780
|
+
const path = _configPath();
|
|
1781
|
+
const dir = dirname5(path);
|
|
1782
|
+
if (!existsSync9(dir))
|
|
1783
|
+
mkdirSync10(dir, { recursive: true });
|
|
1784
|
+
const tmp = `${path}.tmp.${process.pid}`;
|
|
1785
|
+
writeFileSync9(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1786
|
+
renameSync5(tmp, path);
|
|
1787
|
+
_cache = merged;
|
|
1788
|
+
return merged;
|
|
1789
|
+
}
|
|
1790
|
+
function getEmbeddingsEnabled() {
|
|
1791
|
+
const cfg = readUserConfig();
|
|
1792
|
+
if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
|
|
1793
|
+
return cfg.embeddings.enabled;
|
|
1794
|
+
}
|
|
1795
|
+
if (_migrated) {
|
|
1796
|
+
return migrationValueFromEnv();
|
|
1797
|
+
}
|
|
1798
|
+
_migrated = true;
|
|
1799
|
+
const enabled = migrationValueFromEnv();
|
|
1800
|
+
try {
|
|
1801
|
+
writeUserConfig({ embeddings: { enabled } });
|
|
1802
|
+
} catch {
|
|
1803
|
+
_cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
|
|
1804
|
+
}
|
|
1805
|
+
return enabled;
|
|
1806
|
+
}
|
|
1807
|
+
function migrationValueFromEnv() {
|
|
1808
|
+
const raw = process.env.HIVEMIND_EMBEDDINGS;
|
|
1809
|
+
if (raw === void 0)
|
|
1810
|
+
return false;
|
|
1811
|
+
if (raw === "false")
|
|
1812
|
+
return false;
|
|
1813
|
+
return true;
|
|
1814
|
+
}
|
|
1815
|
+
function isPlainObject(value) {
|
|
1816
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1817
|
+
}
|
|
1818
|
+
function deepMerge(base, patch) {
|
|
1819
|
+
const out = { ...base };
|
|
1820
|
+
for (const key of Object.keys(patch)) {
|
|
1821
|
+
const patchVal = patch[key];
|
|
1822
|
+
const baseVal = base[key];
|
|
1823
|
+
if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
|
|
1824
|
+
out[key] = { ...baseVal, ...patchVal };
|
|
1825
|
+
} else if (patchVal !== void 0) {
|
|
1826
|
+
out[key] = patchVal;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
return out;
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
// dist/src/embeddings/disable.js
|
|
1833
|
+
var cachedStatus = null;
|
|
1834
|
+
function defaultResolveTransformers() {
|
|
1835
|
+
const sharedDir = join18(homedir12(), ".hivemind", "embed-deps");
|
|
1836
|
+
try {
|
|
1837
|
+
createRequire2(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
|
|
1838
|
+
return;
|
|
1839
|
+
} catch {
|
|
1840
|
+
}
|
|
1841
|
+
createRequire2(import.meta.url).resolve("@huggingface/transformers");
|
|
1842
|
+
}
|
|
1843
|
+
var _resolve = defaultResolveTransformers;
|
|
1844
|
+
var _readEnabled = getEmbeddingsEnabled;
|
|
1845
|
+
function detectStatus() {
|
|
1846
|
+
if (!_readEnabled())
|
|
1847
|
+
return "user-disabled";
|
|
1848
|
+
try {
|
|
1849
|
+
_resolve();
|
|
1850
|
+
return "enabled";
|
|
1851
|
+
} catch {
|
|
1852
|
+
return "no-transformers";
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
function embeddingsStatus() {
|
|
1856
|
+
if (cachedStatus !== null)
|
|
1857
|
+
return cachedStatus;
|
|
1858
|
+
cachedStatus = detectStatus();
|
|
1859
|
+
return cachedStatus;
|
|
1860
|
+
}
|
|
1861
|
+
function embeddingsDisabled() {
|
|
1862
|
+
return embeddingsStatus() !== "enabled";
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1809
1865
|
// dist/src/hooks/codex/stop.js
|
|
1810
1866
|
var log5 = (msg) => log("codex-stop", msg);
|
|
1811
1867
|
function resolveEmbedDaemonPath() {
|
|
1812
|
-
return
|
|
1868
|
+
return join19(dirname6(fileURLToPath3(import.meta.url)), "embeddings", "embed-daemon.js");
|
|
1813
1869
|
}
|
|
1814
|
-
var __bundleDir =
|
|
1870
|
+
var __bundleDir = dirname6(fileURLToPath3(import.meta.url));
|
|
1815
1871
|
var PLUGIN_VERSION = getInstalledVersion(__bundleDir, ".codex-plugin") ?? "";
|
|
1816
1872
|
var CAPTURE = process.env.HIVEMIND_CAPTURE !== "false";
|
|
1817
1873
|
async function main() {
|
|
@@ -1836,7 +1892,7 @@ async function main() {
|
|
|
1836
1892
|
try {
|
|
1837
1893
|
const transcriptPath = input.transcript_path;
|
|
1838
1894
|
if (existsSync10(transcriptPath)) {
|
|
1839
|
-
const transcript =
|
|
1895
|
+
const transcript = readFileSync11(transcriptPath, "utf-8");
|
|
1840
1896
|
const lines = transcript.trim().split("\n").reverse();
|
|
1841
1897
|
for (const line2 of lines) {
|
|
1842
1898
|
try {
|