@deeplake/hivemind 0.7.31 → 0.7.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,19 +53,19 @@ var init_index_marker_store = __esm({
53
53
  });
54
54
 
55
55
  // dist/src/hooks/codex/stop.js
56
- import { readFileSync as readFileSync8, existsSync as existsSync9 } 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 dirname4, join as join15 } 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() {
62
- return new Promise((resolve, reject) => {
62
+ return new Promise((resolve2, reject) => {
63
63
  let data = "";
64
64
  process.stdin.setEncoding("utf-8");
65
65
  process.stdin.on("data", (chunk) => data += chunk);
66
66
  process.stdin.on("end", () => {
67
67
  try {
68
- resolve(JSON.parse(data));
68
+ resolve2(JSON.parse(data));
69
69
  } catch (err) {
70
70
  reject(new Error(`Failed to parse hook input: ${err}`));
71
71
  }
@@ -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,8 +330,8 @@ 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) {
184
- return new Promise((resolve) => setTimeout(resolve, ms));
333
+ function sleep2(ms) {
334
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
185
335
  }
186
336
  function isTimeoutError(error) {
187
337
  const name = error instanceof Error ? error.name.toLowerCase() : "";
@@ -211,7 +361,7 @@ var Semaphore = class {
211
361
  this.active++;
212
362
  return;
213
363
  }
214
- await new Promise((resolve) => this.waiting.push(resolve));
364
+ await new Promise((resolve2) => this.waiting.push(resolve2));
215
365
  }
216
366
  release() {
217
367
  this.active--;
@@ -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 openSync3, closeSync as closeSync3, writeSync as writeSync3, unlinkSync as unlinkSync3, existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
1179
- import { homedir as homedir10 } from "node:os";
1180
- import { join as join13 } 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";
@@ -1191,12 +1342,13 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1191
1342
  }
1192
1343
 
1193
1344
  // dist/src/embeddings/client.js
1194
- var SHARED_DAEMON_PATH = join13(homedir10(), ".hivemind", "embed-deps", "embed-daemon.js");
1195
- var log3 = (m) => log("embed-client", m);
1345
+ var SHARED_DAEMON_PATH = join15(homedir12(), ".hivemind", "embed-deps", "embed-daemon.js");
1346
+ var log4 = (m) => log("embed-client", m);
1196
1347
  function getUid() {
1197
1348
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
1198
1349
  return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
1199
1350
  }
1351
+ var _recycledStuckDaemon = false;
1200
1352
  var EmbedClient = class {
1201
1353
  socketPath;
1202
1354
  pidPath;
@@ -1205,6 +1357,7 @@ var EmbedClient = class {
1205
1357
  autoSpawn;
1206
1358
  spawnWaitMs;
1207
1359
  nextId = 0;
1360
+ helloVerified = false;
1208
1361
  constructor(opts = {}) {
1209
1362
  const uid = getUid();
1210
1363
  const dir = opts.socketDir ?? "/tmp";
@@ -1221,8 +1374,33 @@ var EmbedClient = class {
1221
1374
  *
1222
1375
  * Fire-and-forget spawn on miss: if the daemon isn't up, this call returns
1223
1376
  * null AND kicks off a background spawn. The next call finds a ready daemon.
1377
+ *
1378
+ * Stuck-daemon recycle: if the daemon returns a transformers-missing
1379
+ * error (typical after a marketplace upgrade left an older daemon process
1380
+ * alive but with no node_modules accessible from its bundle path), we
1381
+ * SIGTERM it and clear its sock/pid so the very next call spawns a fresh
1382
+ * daemon from the current bundle. Without this, the stuck daemon would
1383
+ * keep poisoning every session until its 10-minute idle-out fires.
1224
1384
  */
1225
1385
  async embed(text, kind = "document") {
1386
+ const v = await this.embedAttempt(text, kind);
1387
+ if (v !== "recycled")
1388
+ return v;
1389
+ if (!this.autoSpawn)
1390
+ return null;
1391
+ this.trySpawnDaemon();
1392
+ await this.waitForDaemonReady();
1393
+ const retry = await this.embedAttempt(text, kind);
1394
+ return retry === "recycled" ? null : retry;
1395
+ }
1396
+ /**
1397
+ * One round-trip: connect → verify → embed. Returns:
1398
+ * - number[] : embedding vector (happy path)
1399
+ * - null : timeout / daemon error / transformers-missing
1400
+ * - "recycled": verifyDaemonOnce killed the daemon mid-call;
1401
+ * caller should respawn and retry once.
1402
+ */
1403
+ async embedAttempt(text, kind) {
1226
1404
  let sock;
1227
1405
  try {
1228
1406
  sock = await this.connectOnce();
@@ -1232,17 +1410,25 @@ var EmbedClient = class {
1232
1410
  return null;
1233
1411
  }
1234
1412
  try {
1413
+ const recycled = await this.verifyDaemonOnce(sock);
1414
+ if (recycled) {
1415
+ return "recycled";
1416
+ }
1235
1417
  const id = String(++this.nextId);
1236
1418
  const req = { op: "embed", id, kind, text };
1237
1419
  const resp = await this.sendAndWait(sock, req);
1238
1420
  if (resp.error || !("embedding" in resp) || !resp.embedding) {
1239
- log3(`embed err: ${resp.error ?? "no embedding"}`);
1421
+ const err = resp.error ?? "no embedding";
1422
+ log4(`embed err: ${err}`);
1423
+ if (isTransformersMissingError(err)) {
1424
+ this.handleTransformersMissing(err);
1425
+ }
1240
1426
  return null;
1241
1427
  }
1242
1428
  return resp.embedding;
1243
1429
  } catch (e) {
1244
1430
  const err = e instanceof Error ? e.message : String(e);
1245
- log3(`embed failed: ${err}`);
1431
+ log4(`embed failed: ${err}`);
1246
1432
  return null;
1247
1433
  } finally {
1248
1434
  try {
@@ -1251,6 +1437,123 @@ var EmbedClient = class {
1251
1437
  }
1252
1438
  }
1253
1439
  }
1440
+ /**
1441
+ * Poll for the sock file to come back after `trySpawnDaemon` — used by
1442
+ * the recycle retry path. Best-effort: caps at `spawnWaitMs` and
1443
+ * returns regardless so the retry attempt can run.
1444
+ */
1445
+ async waitForDaemonReady() {
1446
+ const deadline = Date.now() + this.spawnWaitMs;
1447
+ while (Date.now() < deadline) {
1448
+ if (existsSync8(this.socketPath))
1449
+ return;
1450
+ await new Promise((r) => setTimeout(r, 50));
1451
+ }
1452
+ }
1453
+ /**
1454
+ * Send a `hello` on first successful connect per EmbedClient instance.
1455
+ * If the daemon answers with a path that doesn't match our configured
1456
+ * daemonEntry — typical after a marketplace upgrade replaced the bundle
1457
+ * — SIGTERM the daemon + clear sock/pid so the next call spawns from the
1458
+ * current bundle.
1459
+ *
1460
+ * `helloVerified` is set ONLY after we've seen a compatible response,
1461
+ * so a transient probe failure or a recycle-triggering mismatch leaves
1462
+ * the flag false; the next reconnect re-runs verification against
1463
+ * whatever daemon is then live (typically the fresh spawn).
1464
+ */
1465
+ async verifyDaemonOnce(sock) {
1466
+ if (this.helloVerified)
1467
+ return false;
1468
+ if (!this.daemonEntry) {
1469
+ this.helloVerified = true;
1470
+ return false;
1471
+ }
1472
+ const id = String(++this.nextId);
1473
+ const req = { op: "hello", id };
1474
+ let resp;
1475
+ try {
1476
+ resp = await this.sendAndWait(sock, req);
1477
+ } catch (e) {
1478
+ log4(`hello probe failed (inconclusive, will retry next connect): ${e instanceof Error ? e.message : String(e)}`);
1479
+ return false;
1480
+ }
1481
+ const hello = resp;
1482
+ if (_recycledStuckDaemon) {
1483
+ return false;
1484
+ }
1485
+ if (!hello.daemonPath) {
1486
+ _recycledStuckDaemon = true;
1487
+ log4(`daemon does not implement hello (older protocol); recycling`);
1488
+ this.recycleDaemon(hello.pid);
1489
+ return true;
1490
+ }
1491
+ if (hello.daemonPath !== this.daemonEntry && !existsSync8(hello.daemonPath)) {
1492
+ _recycledStuckDaemon = true;
1493
+ log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
1494
+ this.recycleDaemon(hello.pid);
1495
+ return true;
1496
+ }
1497
+ this.helloVerified = true;
1498
+ return false;
1499
+ }
1500
+ /**
1501
+ * On a transformers-missing error from the daemon, SIGTERM the stuck
1502
+ * daemon (the bundle daemon that can't find its deps) and clear
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.
1512
+ */
1513
+ handleTransformersMissing(_detail) {
1514
+ if (!_recycledStuckDaemon) {
1515
+ _recycledStuckDaemon = true;
1516
+ this.recycleDaemon(null);
1517
+ }
1518
+ }
1519
+ /**
1520
+ * Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
1521
+ * combination and dead-PID cases.
1522
+ *
1523
+ * Identity check: gate the SIGTERM on the daemon's socket file still
1524
+ * existing. We know the daemon was alive moments ago (we either just
1525
+ * got a hello response or the caller saw a transformers-missing error
1526
+ * the daemon emitted), but if the socket file is gone by the time we
1527
+ * try to kill, the daemon process is also gone and the PID we
1528
+ * captured may already have been recycled by the OS to an unrelated
1529
+ * user process. Mirrors the gate added to `killEmbedDaemon` in the
1530
+ * CLI — same failure mode, rarer trigger.
1531
+ */
1532
+ recycleDaemon(reportedPid) {
1533
+ let pid = reportedPid;
1534
+ if (pid === null) {
1535
+ try {
1536
+ pid = Number.parseInt(readFileSync9(this.pidPath, "utf-8").trim(), 10);
1537
+ } catch {
1538
+ }
1539
+ }
1540
+ if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync8(this.socketPath)) {
1541
+ try {
1542
+ process.kill(pid, "SIGTERM");
1543
+ } catch {
1544
+ }
1545
+ } else if (pid !== null) {
1546
+ log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
1547
+ }
1548
+ try {
1549
+ unlinkSync5(this.socketPath);
1550
+ } catch {
1551
+ }
1552
+ try {
1553
+ unlinkSync5(this.pidPath);
1554
+ } catch {
1555
+ }
1556
+ }
1254
1557
  /**
1255
1558
  * Wait up to spawnWaitMs for the daemon to accept connections, spawning if
1256
1559
  * necessary. Meant for SessionStart / long-running batches — not the hot path.
@@ -1274,7 +1577,7 @@ var EmbedClient = class {
1274
1577
  }
1275
1578
  }
1276
1579
  connectOnce() {
1277
- return new Promise((resolve, reject) => {
1580
+ return new Promise((resolve2, reject) => {
1278
1581
  const sock = connect(this.socketPath);
1279
1582
  const to = setTimeout(() => {
1280
1583
  sock.destroy();
@@ -1282,7 +1585,7 @@ var EmbedClient = class {
1282
1585
  }, this.timeoutMs);
1283
1586
  sock.once("connect", () => {
1284
1587
  clearTimeout(to);
1285
- resolve(sock);
1588
+ resolve2(sock);
1286
1589
  });
1287
1590
  sock.once("error", (e) => {
1288
1591
  clearTimeout(to);
@@ -1293,16 +1596,16 @@ var EmbedClient = class {
1293
1596
  trySpawnDaemon() {
1294
1597
  let fd;
1295
1598
  try {
1296
- fd = openSync3(this.pidPath, "wx", 384);
1599
+ fd = openSync4(this.pidPath, "wx", 384);
1297
1600
  writeSync3(fd, String(process.pid));
1298
1601
  } catch (e) {
1299
1602
  if (this.isPidFileStale()) {
1300
1603
  try {
1301
- unlinkSync3(this.pidPath);
1604
+ unlinkSync5(this.pidPath);
1302
1605
  } catch {
1303
1606
  }
1304
1607
  try {
1305
- fd = openSync3(this.pidPath, "wx", 384);
1608
+ fd = openSync4(this.pidPath, "wx", 384);
1306
1609
  writeSync3(fd, String(process.pid));
1307
1610
  } catch {
1308
1611
  return;
@@ -1312,10 +1615,10 @@ var EmbedClient = class {
1312
1615
  }
1313
1616
  }
1314
1617
  if (!this.daemonEntry || !existsSync8(this.daemonEntry)) {
1315
- log3(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1618
+ log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1316
1619
  try {
1317
- closeSync3(fd);
1318
- unlinkSync3(this.pidPath);
1620
+ closeSync4(fd);
1621
+ unlinkSync5(this.pidPath);
1319
1622
  } catch {
1320
1623
  }
1321
1624
  return;
@@ -1327,14 +1630,14 @@ var EmbedClient = class {
1327
1630
  env: process.env
1328
1631
  });
1329
1632
  child.unref();
1330
- log3(`spawned daemon pid=${child.pid}`);
1633
+ log4(`spawned daemon pid=${child.pid}`);
1331
1634
  } finally {
1332
- closeSync3(fd);
1635
+ closeSync4(fd);
1333
1636
  }
1334
1637
  }
1335
1638
  isPidFileStale() {
1336
1639
  try {
1337
- const raw = readFileSync7(this.pidPath, "utf-8").trim();
1640
+ const raw = readFileSync9(this.pidPath, "utf-8").trim();
1338
1641
  const pid = Number(raw);
1339
1642
  if (!pid || Number.isNaN(pid))
1340
1643
  return true;
@@ -1352,7 +1655,7 @@ var EmbedClient = class {
1352
1655
  const deadline = Date.now() + this.spawnWaitMs;
1353
1656
  let delay = 30;
1354
1657
  while (Date.now() < deadline) {
1355
- await sleep2(delay);
1658
+ await sleep3(delay);
1356
1659
  delay = Math.min(delay * 1.5, 300);
1357
1660
  if (!existsSync8(this.socketPath))
1358
1661
  continue;
@@ -1364,7 +1667,7 @@ var EmbedClient = class {
1364
1667
  throw new Error("daemon did not become ready within spawnWaitMs");
1365
1668
  }
1366
1669
  sendAndWait(sock, req) {
1367
- return new Promise((resolve, reject) => {
1670
+ return new Promise((resolve2, reject) => {
1368
1671
  let buf = "";
1369
1672
  const to = setTimeout(() => {
1370
1673
  sock.destroy();
@@ -1379,7 +1682,7 @@ var EmbedClient = class {
1379
1682
  const line = buf.slice(0, nl);
1380
1683
  clearTimeout(to);
1381
1684
  try {
1382
- resolve(JSON.parse(line));
1685
+ resolve2(JSON.parse(line));
1383
1686
  } catch (e) {
1384
1687
  reject(e);
1385
1688
  }
@@ -1396,9 +1699,14 @@ var EmbedClient = class {
1396
1699
  });
1397
1700
  }
1398
1701
  };
1399
- function sleep2(ms) {
1702
+ function sleep3(ms) {
1400
1703
  return new Promise((r) => setTimeout(r, ms));
1401
1704
  }
1705
+ function isTransformersMissingError(err) {
1706
+ if (/hivemind embeddings install/i.test(err))
1707
+ return true;
1708
+ return /@huggingface\/transformers/i.test(err);
1709
+ }
1402
1710
 
1403
1711
  // dist/src/embeddings/sql.js
1404
1712
  function embeddingSqlLiteral(vec) {
@@ -1415,23 +1723,105 @@ function embeddingSqlLiteral(vec) {
1415
1723
 
1416
1724
  // dist/src/embeddings/disable.js
1417
1725
  import { createRequire as createRequire2 } from "node:module";
1418
- import { homedir as homedir11 } from "node:os";
1419
- import { join as join14 } from "node:path";
1726
+ import { homedir as homedir14 } from "node:os";
1727
+ import { join as join17 } from "node:path";
1420
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
1421
1810
  var cachedStatus = null;
1422
1811
  function defaultResolveTransformers() {
1812
+ const sharedDir = join17(homedir14(), ".hivemind", "embed-deps");
1423
1813
  try {
1424
- createRequire2(import.meta.url).resolve("@huggingface/transformers");
1814
+ createRequire2(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1425
1815
  return;
1426
1816
  } catch {
1427
1817
  }
1428
- const sharedDir = join14(homedir11(), ".hivemind", "embed-deps");
1429
- createRequire2(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1818
+ createRequire2(import.meta.url).resolve("@huggingface/transformers");
1430
1819
  }
1431
1820
  var _resolve = defaultResolveTransformers;
1821
+ var _readEnabled = getEmbeddingsEnabled;
1432
1822
  function detectStatus() {
1433
- if (process.env.HIVEMIND_EMBEDDINGS === "false")
1434
- return "env-disabled";
1823
+ if (!_readEnabled())
1824
+ return "user-disabled";
1435
1825
  try {
1436
1826
  _resolve();
1437
1827
  return "enabled";
@@ -1450,11 +1840,11 @@ function embeddingsDisabled() {
1450
1840
  }
1451
1841
 
1452
1842
  // dist/src/hooks/codex/stop.js
1453
- var log4 = (msg) => log("codex-stop", msg);
1843
+ var log5 = (msg) => log("codex-stop", msg);
1454
1844
  function resolveEmbedDaemonPath() {
1455
- return join15(dirname4(fileURLToPath3(import.meta.url)), "embeddings", "embed-daemon.js");
1845
+ return join18(dirname5(fileURLToPath3(import.meta.url)), "embeddings", "embed-daemon.js");
1456
1846
  }
1457
- var __bundleDir = dirname4(fileURLToPath3(import.meta.url));
1847
+ var __bundleDir = dirname5(fileURLToPath3(import.meta.url));
1458
1848
  var PLUGIN_VERSION = getInstalledVersion(__bundleDir, ".codex-plugin") ?? "";
1459
1849
  var CAPTURE = process.env.HIVEMIND_CAPTURE !== "false";
1460
1850
  async function main() {
@@ -1466,7 +1856,7 @@ async function main() {
1466
1856
  return;
1467
1857
  const config = loadConfig();
1468
1858
  if (!config) {
1469
- log4("no config");
1859
+ log5("no config");
1470
1860
  return;
1471
1861
  }
1472
1862
  if (CAPTURE) {
@@ -1478,8 +1868,8 @@ async function main() {
1478
1868
  if (input.transcript_path) {
1479
1869
  try {
1480
1870
  const transcriptPath = input.transcript_path;
1481
- if (existsSync9(transcriptPath)) {
1482
- const transcript = readFileSync8(transcriptPath, "utf-8");
1871
+ if (existsSync10(transcriptPath)) {
1872
+ const transcript = readFileSync11(transcriptPath, "utf-8");
1483
1873
  const lines = transcript.trim().split("\n").reverse();
1484
1874
  for (const line2 of lines) {
1485
1875
  try {
@@ -1496,10 +1886,10 @@ async function main() {
1496
1886
  }
1497
1887
  }
1498
1888
  if (lastAssistantMessage)
1499
- log4(`extracted assistant message from transcript (${lastAssistantMessage.length} chars)`);
1889
+ log5(`extracted assistant message from transcript (${lastAssistantMessage.length} chars)`);
1500
1890
  }
1501
1891
  } catch (e) {
1502
- log4(`transcript read failed: ${e.message}`);
1892
+ log5(`transcript read failed: ${e.message}`);
1503
1893
  }
1504
1894
  }
1505
1895
  const entry = {
@@ -1522,9 +1912,9 @@ async function main() {
1522
1912
  const embeddingSql = embeddingSqlLiteral(embedding);
1523
1913
  const insertSql = `INSERT INTO "${sessionsTable}" (id, path, filename, message, message_embedding, author, size_bytes, project, description, agent, plugin_version, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(sessionPath)}', '${sqlStr(filename)}', '${jsonForSql}'::jsonb, ${embeddingSql}, '${sqlStr(config.userName)}', ${Buffer.byteLength(line, "utf-8")}, '${sqlStr(projectName)}', 'Stop', 'codex', '${sqlStr(PLUGIN_VERSION)}', '${ts}', '${ts}')`;
1524
1914
  await api.query(insertSql);
1525
- log4("stop event captured");
1915
+ log5("stop event captured");
1526
1916
  } catch (e) {
1527
- log4(`capture failed: ${e.message}`);
1917
+ log5(`capture failed: ${e.message}`);
1528
1918
  }
1529
1919
  }
1530
1920
  if (!CAPTURE)
@@ -1543,11 +1933,11 @@ async function main() {
1543
1933
  reason: "Stop"
1544
1934
  });
1545
1935
  } catch (e) {
1546
- log4(`spawn failed: ${e.message}`);
1936
+ log5(`spawn failed: ${e.message}`);
1547
1937
  try {
1548
1938
  releaseLock(sessionId);
1549
1939
  } catch (releaseErr) {
1550
- log4(`releaseLock after spawn failure also failed: ${releaseErr.message}`);
1940
+ log5(`releaseLock after spawn failure also failed: ${releaseErr.message}`);
1551
1941
  }
1552
1942
  throw e;
1553
1943
  }
@@ -1560,6 +1950,6 @@ async function main() {
1560
1950
  });
1561
1951
  }
1562
1952
  main().catch((e) => {
1563
- log4(`fatal: ${e.message}`);
1953
+ log5(`fatal: ${e.message}`);
1564
1954
  process.exit(0);
1565
1955
  });