@deeplake/hivemind 0.7.32 → 0.7.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 readFileSync2, writeFileSync } from "node:fs";
21
- import { join as join3 } from "node:path";
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 ?? join3(tmpdir(), "hivemind-deeplake-indexes");
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 join3(getIndexMarkerDir(), `${markerKey}.json`);
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(readFileSync2(markerPath, "utf-8"));
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
- mkdirSync(getIndexMarkerDir(), { recursive: true });
45
- writeFileSync(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
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 readFileSync10, existsSync as existsSync10 } from "node:fs";
56
+ import { readFileSync as readFileSync11, existsSync as existsSync10 } from "node:fs";
57
57
  import { fileURLToPath as fileURLToPath3 } from "node:url";
58
- import { dirname as dirname5, join as join17 } from "node:path";
58
+ import { dirname as dirname5, join as join18 } 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 log2 = (msg) => log("sdk", msg);
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
- log2(msg);
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 sleep(ms) {
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
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
286
- await sleep(delay);
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
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
303
- await sleep(delay);
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
- log2(`commit: ${rows.length} rows`);
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
- log2(`index "${indexName}" skipped: ${e.message}`);
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 sleep(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
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 sleep(BASE_DELAY_MS * Math.pow(2, attempt));
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
- log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
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 sleep(OUTER_BACKOFFS_MS[attempt]);
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
- log2(`table "${tbl}" not found, creating`);
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
- log2(`table "${tbl}" created`);
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
- log2(`table "${safe}" not found, creating`);
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
- log2(`table "${safe}" created`);
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
- log2(`table "${safe}" not found, creating`);
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
- log2(`table "${safe}" created`);
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 join6 } from "node:path";
573
- import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "node:fs";
574
- import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
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 mkdirSync2, appendFileSync as appendFileSync2 } from "node:fs";
578
- import { join as join4 } from "node:path";
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 = join4(hooksDir, filename);
731
+ const path = join6(hooksDir, filename);
581
732
  return {
582
733
  path,
583
734
  log(msg) {
584
735
  try {
585
- mkdirSync2(hooksDir, { recursive: true });
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 readFileSync3 } from "node:fs";
596
- import { dirname, join as join5 } from "node:path";
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 = join5(bundleDir, "..", pluginManifestDir, "plugin.json");
600
- const plugin = JSON.parse(readFileSync3(pluginJson, "utf-8"));
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 = readFileSync3(join5(bundleDir, "..", ".hivemind_version"), "utf-8").trim();
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 = join5(dir, "package.json");
772
+ const candidate = join7(dir, "package.json");
622
773
  try {
623
- const pkg = JSON.parse(readFileSync3(candidate, "utf-8"));
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 = homedir3();
638
- var wikiLogger = makeWikiLogger(join6(HOME, ".codex", "hooks"));
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 = join6(tmpdir2(), `deeplake-wiki-${sessionId}-${Date.now()}`);
701
- mkdirSync3(tmpDir, { recursive: true });
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 = join6(tmpDir, "config.json");
704
- writeFileSync2(configFile, JSON.stringify({
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: join6(HOME, ".codex", "hooks"),
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 = join6(bundleDir, "wiki-worker.js");
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 join8 } from "node:path";
737
- import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, appendFileSync as appendFileSync3, chmodSync } from "node:fs";
738
- import { homedir as homedir5, tmpdir as tmpdir3 } from "node:os";
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 homedir4 } from "node:os";
744
- import { join as join7 } from "node:path";
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 = homedir4();
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
- join7(home, ".claude", "local", "claude"),
916
+ join9(home, ".claude", "local", "claude"),
766
917
  "/usr/local/bin/claude",
767
918
  "/usr/bin/claude",
768
- join7(home, ".npm-global", "bin", "claude"),
769
- join7(home, ".local", "bin", "claude"),
919
+ join9(home, ".npm-global", "bin", "claude"),
920
+ join9(home, ".local", "bin", "claude"),
770
921
  "/opt/homebrew/bin/claude"
771
- ]) ?? join7(home, ".claude", "local", "claude");
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
- join7(home, ".npm-global", "bin", "codex"),
777
- join7(home, ".local", "bin", "codex"),
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
- join7(home, ".npm-global", "bin", "cursor-agent"),
785
- join7(home, ".local", "bin", "cursor-agent"),
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
- join7(home, ".local", "bin", "hermes"),
941
+ join9(home, ".local", "bin", "hermes"),
791
942
  "/usr/local/bin/hermes",
792
943
  "/usr/bin/hermes",
793
- join7(home, ".npm-global", "bin", "hermes"),
944
+ join9(home, ".npm-global", "bin", "hermes"),
794
945
  "/opt/homebrew/bin/hermes"
795
- ]) ?? join7(home, ".local", "bin", "hermes");
946
+ ]) ?? join9(home, ".local", "bin", "hermes");
796
947
  case "pi":
797
948
  return firstExistingPath([
798
- join7(home, ".local", "bin", "pi"),
949
+ join9(home, ".local", "bin", "pi"),
799
950
  "/usr/local/bin/pi",
800
951
  "/usr/bin/pi",
801
- join7(home, ".npm-global", "bin", "pi"),
952
+ join9(home, ".npm-global", "bin", "pi"),
802
953
  "/opt/homebrew/bin/pi"
803
- ]) ?? join7(home, ".local", "bin", "pi");
954
+ ]) ?? join9(home, ".local", "bin", "pi");
804
955
  }
805
956
  }
806
957
 
807
958
  // dist/src/skillify/spawn-skillify-worker.js
808
- var HOME2 = homedir5();
809
- var SKILLIFY_LOG = join8(HOME2, ".claude", "hooks", "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
- mkdirSync4(dirname3(SKILLIFY_LOG), { recursive: true });
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 = join8(tmpdir3(), `deeplake-skillify-${projectKey}-${Date.now()}`);
821
- mkdirSync4(tmpDir, { recursive: true, mode: 448 });
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 = join8(tmpDir, "config.json");
824
- writeFileSync3(configFile, JSON.stringify({
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 = join8(bundleDir, "skillify-worker.js");
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,31 +1011,31 @@ function spawnSkillifyWorker(opts) {
860
1011
  }
861
1012
 
862
1013
  // dist/src/skillify/state.js
863
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, writeSync, mkdirSync as mkdirSync5, renameSync as renameSync2, existsSync as existsSync5, unlinkSync, openSync, closeSync } from "node:fs";
1014
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, writeSync, mkdirSync as mkdirSync7, renameSync as renameSync3, existsSync as existsSync5, 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";
1016
+ import { homedir as homedir9 } from "node:os";
866
1017
  import { createHash } from "node:crypto";
867
- import { join as join10, basename } from "node:path";
1018
+ import { join as join12, basename } from "node:path";
868
1019
 
869
1020
  // 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";
1021
+ import { existsSync as existsSync4, renameSync as renameSync2 } from "node:fs";
1022
+ import { homedir as homedir8 } from "node:os";
1023
+ import { join as join11 } from "node:path";
873
1024
  var dlog = (msg) => log("skillify-migrate", msg);
874
1025
  var attempted = false;
875
1026
  function migrateLegacyStateDir() {
876
1027
  if (attempted)
877
1028
  return;
878
1029
  attempted = true;
879
- const root = join9(homedir6(), ".deeplake", "state");
880
- const legacy = join9(root, "skilify");
881
- const current = join9(root, "skillify");
1030
+ const root = join11(homedir8(), ".deeplake", "state");
1031
+ const legacy = join11(root, "skilify");
1032
+ const current = join11(root, "skillify");
882
1033
  if (!existsSync4(legacy))
883
1034
  return;
884
1035
  if (existsSync4(current))
885
1036
  return;
886
1037
  try {
887
- renameSync(legacy, current);
1038
+ renameSync2(legacy, current);
888
1039
  dlog(`migrated ${legacy} -> ${current}`);
889
1040
  } catch (err) {
890
1041
  const code = err.code;
@@ -898,17 +1049,17 @@ function migrateLegacyStateDir() {
898
1049
 
899
1050
  // dist/src/skillify/state.js
900
1051
  var dlog2 = (msg) => log("skillify-state", msg);
901
- var STATE_DIR = join10(homedir7(), ".deeplake", "state", "skillify");
1052
+ var STATE_DIR = join12(homedir9(), ".deeplake", "state", "skillify");
902
1053
  var YIELD_BUF = new Int32Array(new SharedArrayBuffer(4));
903
1054
  var TRIGGER_THRESHOLD = (() => {
904
1055
  const n = Number(process.env.HIVEMIND_SKILLIFY_EVERY_N_TURNS ?? "");
905
1056
  return Number.isInteger(n) && n > 0 ? n : 20;
906
1057
  })();
907
1058
  function statePath(projectKey) {
908
- return join10(STATE_DIR, `${projectKey}.json`);
1059
+ return join12(STATE_DIR, `${projectKey}.json`);
909
1060
  }
910
- function lockPath(projectKey) {
911
- return join10(STATE_DIR, `${projectKey}.lock`);
1061
+ function lockPath2(projectKey) {
1062
+ return join12(STATE_DIR, `${projectKey}.lock`);
912
1063
  }
913
1064
  var DEFAULT_PORTS = {
914
1065
  http: "80",
@@ -957,35 +1108,35 @@ function readState(projectKey) {
957
1108
  if (!existsSync5(p))
958
1109
  return null;
959
1110
  try {
960
- return JSON.parse(readFileSync4(p, "utf-8"));
1111
+ return JSON.parse(readFileSync6(p, "utf-8"));
961
1112
  } catch {
962
1113
  return null;
963
1114
  }
964
1115
  }
965
1116
  function writeState(projectKey, state) {
966
1117
  migrateLegacyStateDir();
967
- mkdirSync5(STATE_DIR, { recursive: true });
1118
+ mkdirSync7(STATE_DIR, { recursive: true });
968
1119
  const p = statePath(projectKey);
969
1120
  const tmp = `${p}.${process.pid}.${Date.now()}.tmp`;
970
- writeFileSync4(tmp, JSON.stringify(state, null, 2));
971
- renameSync2(tmp, p);
1121
+ writeFileSync6(tmp, JSON.stringify(state, null, 2));
1122
+ renameSync3(tmp, p);
972
1123
  }
973
1124
  function withRmwLock(projectKey, fn) {
974
1125
  migrateLegacyStateDir();
975
- mkdirSync5(STATE_DIR, { recursive: true });
976
- const rmw = lockPath(projectKey) + ".rmw";
1126
+ mkdirSync7(STATE_DIR, { recursive: true });
1127
+ const rmw = lockPath2(projectKey) + ".rmw";
977
1128
  const deadline = Date.now() + 2e3;
978
1129
  let fd = null;
979
1130
  while (fd === null) {
980
1131
  try {
981
- fd = openSync(rmw, "wx");
1132
+ fd = openSync2(rmw, "wx");
982
1133
  } catch (e) {
983
1134
  if (e.code !== "EEXIST")
984
1135
  throw e;
985
1136
  if (Date.now() > deadline) {
986
1137
  dlog2(`rmw lock deadline exceeded for ${projectKey}, reclaiming stale lock`);
987
1138
  try {
988
- unlinkSync(rmw);
1139
+ unlinkSync3(rmw);
989
1140
  } catch (unlinkErr) {
990
1141
  dlog2(`stale rmw lock unlink failed for ${projectKey}: ${unlinkErr.message}`);
991
1142
  }
@@ -997,9 +1148,9 @@ function withRmwLock(projectKey, fn) {
997
1148
  try {
998
1149
  return fn();
999
1150
  } finally {
1000
- closeSync(fd);
1151
+ closeSync2(fd);
1001
1152
  try {
1002
- unlinkSync(rmw);
1153
+ unlinkSync3(rmw);
1003
1154
  } catch (unlinkErr) {
1004
1155
  dlog2(`rmw lock cleanup failed for ${projectKey}: ${unlinkErr.message}`);
1005
1156
  }
@@ -1015,29 +1166,29 @@ function resetCounter(projectKey) {
1015
1166
  }
1016
1167
  function tryAcquireWorkerLock(projectKey, maxAgeMs = 10 * 60 * 1e3) {
1017
1168
  migrateLegacyStateDir();
1018
- mkdirSync5(STATE_DIR, { recursive: true });
1019
- const p = lockPath(projectKey);
1169
+ mkdirSync7(STATE_DIR, { recursive: true });
1170
+ const p = lockPath2(projectKey);
1020
1171
  if (existsSync5(p)) {
1021
1172
  try {
1022
- const ageMs = Date.now() - parseInt(readFileSync4(p, "utf-8"), 10);
1173
+ const ageMs = Date.now() - parseInt(readFileSync6(p, "utf-8"), 10);
1023
1174
  if (Number.isFinite(ageMs) && ageMs < maxAgeMs)
1024
1175
  return false;
1025
1176
  } catch (readErr) {
1026
1177
  dlog2(`worker lock unreadable for ${projectKey}, treating as stale: ${readErr.message}`);
1027
1178
  }
1028
1179
  try {
1029
- unlinkSync(p);
1180
+ unlinkSync3(p);
1030
1181
  } catch (unlinkErr) {
1031
1182
  dlog2(`could not unlink stale worker lock for ${projectKey}: ${unlinkErr.message}`);
1032
1183
  return false;
1033
1184
  }
1034
1185
  }
1035
1186
  try {
1036
- const fd = openSync(p, "wx");
1187
+ const fd = openSync2(p, "wx");
1037
1188
  try {
1038
1189
  writeSync(fd, String(Date.now()));
1039
1190
  } finally {
1040
- closeSync(fd);
1191
+ closeSync2(fd);
1041
1192
  }
1042
1193
  return true;
1043
1194
  } catch {
@@ -1045,26 +1196,26 @@ function tryAcquireWorkerLock(projectKey, maxAgeMs = 10 * 60 * 1e3) {
1045
1196
  }
1046
1197
  }
1047
1198
  function releaseWorkerLock(projectKey) {
1048
- const p = lockPath(projectKey);
1199
+ const p = lockPath2(projectKey);
1049
1200
  try {
1050
- unlinkSync(p);
1201
+ unlinkSync3(p);
1051
1202
  } catch {
1052
1203
  }
1053
1204
  }
1054
1205
 
1055
1206
  // dist/src/skillify/scope-config.js
1056
- import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
1057
- import { homedir as homedir8 } from "node:os";
1058
- import { join as join11 } from "node:path";
1059
- var STATE_DIR2 = join11(homedir8(), ".deeplake", "state", "skillify");
1060
- var CONFIG_PATH = join11(STATE_DIR2, "config.json");
1207
+ import { existsSync as existsSync6, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
1208
+ import { homedir as homedir10 } from "node:os";
1209
+ import { join as join13 } from "node:path";
1210
+ var STATE_DIR2 = join13(homedir10(), ".deeplake", "state", "skillify");
1211
+ var CONFIG_PATH = join13(STATE_DIR2, "config.json");
1061
1212
  var DEFAULT = { scope: "me", team: [], install: "project" };
1062
1213
  function loadScopeConfig() {
1063
1214
  migrateLegacyStateDir();
1064
1215
  if (!existsSync6(CONFIG_PATH))
1065
1216
  return DEFAULT;
1066
1217
  try {
1067
- const raw = JSON.parse(readFileSync5(CONFIG_PATH, "utf-8"));
1218
+ const raw = JSON.parse(readFileSync7(CONFIG_PATH, "utf-8"));
1068
1219
  const scope = raw.scope === "team" ? "team" : raw.scope === "org" ? "team" : "me";
1069
1220
  const team = Array.isArray(raw.team) ? raw.team.filter((s) => typeof s === "string") : [];
1070
1221
  const install = raw.install === "global" ? "global" : "project";
@@ -1115,39 +1266,39 @@ function forceSessionEndTrigger(opts) {
1115
1266
  }
1116
1267
 
1117
1268
  // dist/src/hooks/summary-state.js
1118
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, writeSync as writeSync2, mkdirSync as mkdirSync7, renameSync as renameSync3, existsSync as existsSync7, unlinkSync as unlinkSync2, openSync as openSync2, closeSync as closeSync2 } from "node:fs";
1119
- import { homedir as homedir9 } from "node:os";
1120
- import { join as join12 } from "node:path";
1269
+ 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";
1270
+ import { homedir as homedir11 } from "node:os";
1271
+ import { join as join14 } from "node:path";
1121
1272
  var dlog3 = (msg) => log("summary-state", msg);
1122
- var STATE_DIR3 = join12(homedir9(), ".claude", "hooks", "summary-state");
1273
+ var STATE_DIR3 = join14(homedir11(), ".claude", "hooks", "summary-state");
1123
1274
  var YIELD_BUF2 = new Int32Array(new SharedArrayBuffer(4));
1124
- function lockPath2(sessionId) {
1125
- return join12(STATE_DIR3, `${sessionId}.lock`);
1275
+ function lockPath3(sessionId) {
1276
+ return join14(STATE_DIR3, `${sessionId}.lock`);
1126
1277
  }
1127
1278
  function tryAcquireLock(sessionId, maxAgeMs = 10 * 60 * 1e3) {
1128
- mkdirSync7(STATE_DIR3, { recursive: true });
1129
- const p = lockPath2(sessionId);
1279
+ mkdirSync9(STATE_DIR3, { recursive: true });
1280
+ const p = lockPath3(sessionId);
1130
1281
  if (existsSync7(p)) {
1131
1282
  try {
1132
- const ageMs = Date.now() - parseInt(readFileSync6(p, "utf-8"), 10);
1283
+ const ageMs = Date.now() - parseInt(readFileSync8(p, "utf-8"), 10);
1133
1284
  if (Number.isFinite(ageMs) && ageMs < maxAgeMs)
1134
1285
  return false;
1135
1286
  } catch (readErr) {
1136
1287
  dlog3(`lock file unreadable for ${sessionId}, treating as stale: ${readErr.message}`);
1137
1288
  }
1138
1289
  try {
1139
- unlinkSync2(p);
1290
+ unlinkSync4(p);
1140
1291
  } catch (unlinkErr) {
1141
1292
  dlog3(`could not unlink stale lock for ${sessionId}: ${unlinkErr.message}`);
1142
1293
  return false;
1143
1294
  }
1144
1295
  }
1145
1296
  try {
1146
- const fd = openSync2(p, "wx");
1297
+ const fd = openSync3(p, "wx");
1147
1298
  try {
1148
1299
  writeSync2(fd, String(Date.now()));
1149
1300
  } finally {
1150
- closeSync2(fd);
1301
+ closeSync3(fd);
1151
1302
  }
1152
1303
  return true;
1153
1304
  } catch (e) {
@@ -1158,7 +1309,7 @@ function tryAcquireLock(sessionId, maxAgeMs = 10 * 60 * 1e3) {
1158
1309
  }
1159
1310
  function releaseLock(sessionId) {
1160
1311
  try {
1161
- unlinkSync2(lockPath2(sessionId));
1312
+ unlinkSync4(lockPath3(sessionId));
1162
1313
  } catch (e) {
1163
1314
  if (e?.code !== "ENOENT") {
1164
1315
  dlog3(`releaseLock unlink failed for ${sessionId}: ${e.message}`);
@@ -1175,9 +1326,9 @@ function buildSessionPath(config, sessionId) {
1175
1326
  // dist/src/embeddings/client.js
1176
1327
  import { connect } from "node:net";
1177
1328
  import { spawn as spawn3 } from "node:child_process";
1178
- import { openSync as openSync4, closeSync as closeSync4, writeSync as writeSync3, unlinkSync as unlinkSync4, existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
1179
- import { homedir as homedir13 } from "node:os";
1180
- import { join as join16 } from "node:path";
1329
+ import { openSync as openSync4, closeSync as closeSync4, writeSync as writeSync3, unlinkSync as unlinkSync5, existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
1330
+ import { homedir as homedir12 } from "node:os";
1331
+ import { join as join15 } from "node:path";
1181
1332
 
1182
1333
  // dist/src/embeddings/protocol.js
1183
1334
  var DEFAULT_SOCKET_DIR = "/tmp";
@@ -1190,233 +1341,13 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1190
1341
  return `${dir}/hivemind-embed-${uid}.pid`;
1191
1342
  }
1192
1343
 
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
1344
  // dist/src/embeddings/client.js
1413
- var SHARED_DAEMON_PATH = join16(homedir13(), ".hivemind", "embed-deps", "embed-daemon.js");
1345
+ var SHARED_DAEMON_PATH = join15(homedir12(), ".hivemind", "embed-deps", "embed-daemon.js");
1414
1346
  var log4 = (m) => log("embed-client", m);
1415
1347
  function getUid() {
1416
1348
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
1417
1349
  return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
1418
1350
  }
1419
- var _signalledMissingDeps = false;
1420
1351
  var _recycledStuckDaemon = false;
1421
1352
  var EmbedClient = class {
1422
1353
  socketPath;
@@ -1433,7 +1364,7 @@ var EmbedClient = class {
1433
1364
  this.socketPath = socketPathFor(uid, dir);
1434
1365
  this.pidPath = pidPathFor(uid, dir);
1435
1366
  this.timeoutMs = opts.timeoutMs ?? DEFAULT_CLIENT_TIMEOUT_MS;
1436
- this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync9(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1367
+ this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync8(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1437
1368
  this.autoSpawn = opts.autoSpawn ?? true;
1438
1369
  this.spawnWaitMs = opts.spawnWaitMs ?? 5e3;
1439
1370
  }
@@ -1514,7 +1445,7 @@ var EmbedClient = class {
1514
1445
  async waitForDaemonReady() {
1515
1446
  const deadline = Date.now() + this.spawnWaitMs;
1516
1447
  while (Date.now() < deadline) {
1517
- if (existsSync9(this.socketPath))
1448
+ if (existsSync8(this.socketPath))
1518
1449
  return;
1519
1450
  await new Promise((r) => setTimeout(r, 50));
1520
1451
  }
@@ -1557,7 +1488,7 @@ var EmbedClient = class {
1557
1488
  this.recycleDaemon(hello.pid);
1558
1489
  return true;
1559
1490
  }
1560
- if (hello.daemonPath !== this.daemonEntry && !existsSync9(hello.daemonPath)) {
1491
+ if (hello.daemonPath !== this.daemonEntry && !existsSync8(hello.daemonPath)) {
1561
1492
  _recycledStuckDaemon = true;
1562
1493
  log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
1563
1494
  this.recycleDaemon(hello.pid);
@@ -1569,37 +1500,21 @@ var EmbedClient = class {
1569
1500
  /**
1570
1501
  * On a transformers-missing error from the daemon, SIGTERM the stuck
1571
1502
  * daemon (the bundle daemon that can't find its deps) and clear
1572
- * sock/pid so the next call spawns fresh. Also enqueue a one-time
1573
- * notification telling the user to run `hivemind embeddings install`
1574
- * but only when the user has opted in. Suppressed when
1575
- * embeddingsStatus() === "user-disabled" so we don't nag users who
1576
- * explicitly chose to turn embeddings off.
1503
+ * sock/pid so the next call spawns fresh.
1504
+ *
1505
+ * Previously this also enqueued a user-visible "Hivemind embeddings
1506
+ * disabled deps missing" notification telling the user to run
1507
+ * `hivemind embeddings install`. The notification was removed because
1508
+ * (a) the recycle alone often fixes the issue silently, and (b) the
1509
+ * warning kept stacking on top of the primary session-start banner
1510
+ * which clashed with the single-slot priority model. The `detail`
1511
+ * argument is retained for future telemetry / debug logging.
1577
1512
  */
1578
- handleTransformersMissing(detail) {
1513
+ handleTransformersMissing(_detail) {
1579
1514
  if (!_recycledStuckDaemon) {
1580
1515
  _recycledStuckDaemon = true;
1581
1516
  this.recycleDaemon(null);
1582
1517
  }
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
1518
  }
1604
1519
  /**
1605
1520
  * Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
@@ -1622,7 +1537,7 @@ var EmbedClient = class {
1622
1537
  } catch {
1623
1538
  }
1624
1539
  }
1625
- if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync9(this.socketPath)) {
1540
+ if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync8(this.socketPath)) {
1626
1541
  try {
1627
1542
  process.kill(pid, "SIGTERM");
1628
1543
  } catch {
@@ -1631,11 +1546,11 @@ var EmbedClient = class {
1631
1546
  log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
1632
1547
  }
1633
1548
  try {
1634
- unlinkSync4(this.socketPath);
1549
+ unlinkSync5(this.socketPath);
1635
1550
  } catch {
1636
1551
  }
1637
1552
  try {
1638
- unlinkSync4(this.pidPath);
1553
+ unlinkSync5(this.pidPath);
1639
1554
  } catch {
1640
1555
  }
1641
1556
  }
@@ -1686,7 +1601,7 @@ var EmbedClient = class {
1686
1601
  } catch (e) {
1687
1602
  if (this.isPidFileStale()) {
1688
1603
  try {
1689
- unlinkSync4(this.pidPath);
1604
+ unlinkSync5(this.pidPath);
1690
1605
  } catch {
1691
1606
  }
1692
1607
  try {
@@ -1699,11 +1614,11 @@ var EmbedClient = class {
1699
1614
  return;
1700
1615
  }
1701
1616
  }
1702
- if (!this.daemonEntry || !existsSync9(this.daemonEntry)) {
1617
+ if (!this.daemonEntry || !existsSync8(this.daemonEntry)) {
1703
1618
  log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1704
1619
  try {
1705
1620
  closeSync4(fd);
1706
- unlinkSync4(this.pidPath);
1621
+ unlinkSync5(this.pidPath);
1707
1622
  } catch {
1708
1623
  }
1709
1624
  return;
@@ -1742,7 +1657,7 @@ var EmbedClient = class {
1742
1657
  while (Date.now() < deadline) {
1743
1658
  await sleep3(delay);
1744
1659
  delay = Math.min(delay * 1.5, 300);
1745
- if (!existsSync9(this.socketPath))
1660
+ if (!existsSync8(this.socketPath))
1746
1661
  continue;
1747
1662
  try {
1748
1663
  return await this.connectOnce();
@@ -1806,10 +1721,128 @@ function embeddingSqlLiteral(vec) {
1806
1721
  return `ARRAY[${parts.join(",")}]::float4[]`;
1807
1722
  }
1808
1723
 
1724
+ // dist/src/embeddings/disable.js
1725
+ import { createRequire as createRequire2 } from "node:module";
1726
+ import { homedir as homedir14 } from "node:os";
1727
+ import { join as join17 } from "node:path";
1728
+ import { pathToFileURL } from "node:url";
1729
+
1730
+ // dist/src/user-config.js
1731
+ import { existsSync as existsSync9, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "node:fs";
1732
+ import { homedir as homedir13 } from "node:os";
1733
+ import { dirname as dirname4, join as join16 } from "node:path";
1734
+ var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join16(homedir13(), ".deeplake", "config.json");
1735
+ var _cache = null;
1736
+ var _migrated = false;
1737
+ function readUserConfig() {
1738
+ if (_cache !== null)
1739
+ return _cache;
1740
+ const path = _configPath();
1741
+ if (!existsSync9(path)) {
1742
+ _cache = {};
1743
+ return _cache;
1744
+ }
1745
+ try {
1746
+ const raw = readFileSync10(path, "utf-8");
1747
+ const parsed = JSON.parse(raw);
1748
+ _cache = isPlainObject(parsed) ? parsed : {};
1749
+ } catch {
1750
+ _cache = {};
1751
+ }
1752
+ return _cache;
1753
+ }
1754
+ function writeUserConfig(patch) {
1755
+ const current = readUserConfig();
1756
+ const merged = deepMerge(current, patch);
1757
+ const path = _configPath();
1758
+ const dir = dirname4(path);
1759
+ if (!existsSync9(dir))
1760
+ mkdirSync10(dir, { recursive: true });
1761
+ const tmp = `${path}.tmp.${process.pid}`;
1762
+ writeFileSync9(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
1763
+ renameSync5(tmp, path);
1764
+ _cache = merged;
1765
+ return merged;
1766
+ }
1767
+ function getEmbeddingsEnabled() {
1768
+ const cfg = readUserConfig();
1769
+ if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
1770
+ return cfg.embeddings.enabled;
1771
+ }
1772
+ if (_migrated) {
1773
+ return migrationValueFromEnv();
1774
+ }
1775
+ _migrated = true;
1776
+ const enabled = migrationValueFromEnv();
1777
+ try {
1778
+ writeUserConfig({ embeddings: { enabled } });
1779
+ } catch {
1780
+ _cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
1781
+ }
1782
+ return enabled;
1783
+ }
1784
+ function migrationValueFromEnv() {
1785
+ const raw = process.env.HIVEMIND_EMBEDDINGS;
1786
+ if (raw === void 0)
1787
+ return false;
1788
+ if (raw === "false")
1789
+ return false;
1790
+ return true;
1791
+ }
1792
+ function isPlainObject(value) {
1793
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1794
+ }
1795
+ function deepMerge(base, patch) {
1796
+ const out = { ...base };
1797
+ for (const key of Object.keys(patch)) {
1798
+ const patchVal = patch[key];
1799
+ const baseVal = base[key];
1800
+ if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
1801
+ out[key] = { ...baseVal, ...patchVal };
1802
+ } else if (patchVal !== void 0) {
1803
+ out[key] = patchVal;
1804
+ }
1805
+ }
1806
+ return out;
1807
+ }
1808
+
1809
+ // dist/src/embeddings/disable.js
1810
+ var cachedStatus = null;
1811
+ function defaultResolveTransformers() {
1812
+ const sharedDir = join17(homedir14(), ".hivemind", "embed-deps");
1813
+ try {
1814
+ createRequire2(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1815
+ return;
1816
+ } catch {
1817
+ }
1818
+ createRequire2(import.meta.url).resolve("@huggingface/transformers");
1819
+ }
1820
+ var _resolve = defaultResolveTransformers;
1821
+ var _readEnabled = getEmbeddingsEnabled;
1822
+ function detectStatus() {
1823
+ if (!_readEnabled())
1824
+ return "user-disabled";
1825
+ try {
1826
+ _resolve();
1827
+ return "enabled";
1828
+ } catch {
1829
+ return "no-transformers";
1830
+ }
1831
+ }
1832
+ function embeddingsStatus() {
1833
+ if (cachedStatus !== null)
1834
+ return cachedStatus;
1835
+ cachedStatus = detectStatus();
1836
+ return cachedStatus;
1837
+ }
1838
+ function embeddingsDisabled() {
1839
+ return embeddingsStatus() !== "enabled";
1840
+ }
1841
+
1809
1842
  // dist/src/hooks/codex/stop.js
1810
1843
  var log5 = (msg) => log("codex-stop", msg);
1811
1844
  function resolveEmbedDaemonPath() {
1812
- return join17(dirname5(fileURLToPath3(import.meta.url)), "embeddings", "embed-daemon.js");
1845
+ return join18(dirname5(fileURLToPath3(import.meta.url)), "embeddings", "embed-daemon.js");
1813
1846
  }
1814
1847
  var __bundleDir = dirname5(fileURLToPath3(import.meta.url));
1815
1848
  var PLUGIN_VERSION = getInstalledVersion(__bundleDir, ".codex-plugin") ?? "";
@@ -1836,7 +1869,7 @@ async function main() {
1836
1869
  try {
1837
1870
  const transcriptPath = input.transcript_path;
1838
1871
  if (existsSync10(transcriptPath)) {
1839
- const transcript = readFileSync10(transcriptPath, "utf-8");
1872
+ const transcript = readFileSync11(transcriptPath, "utf-8");
1840
1873
  const lines = transcript.trim().split("\n").reverse();
1841
1874
  for (const line2 of lines) {
1842
1875
  try {