@deeplake/hivemind 0.7.65 → 0.7.67

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.
@@ -477,9 +477,6 @@ function traceSql(msg) {
477
477
  log3(msg);
478
478
  }
479
479
  var _signalledBalanceExhausted = false;
480
- var _signalledLowBalance = false;
481
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
482
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
483
480
  function maybeSignalBalanceExhausted(status, bodyText) {
484
481
  if (status !== 402)
485
482
  return;
@@ -495,40 +492,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
495
492
  transient: true,
496
493
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
497
494
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
498
- dedupKey: { reason: "balance-zero" }
495
+ dedupKey: { reason: "balance-zero" },
496
+ // User-facing billing notice → user channel only. Never the model's
497
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
498
+ // is a prompt-injection pattern external agents flag.
499
+ userVisibleOnly: true
499
500
  }).catch((e) => {
500
501
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
501
502
  });
502
503
  }
503
- function signalLowBalanceFromHeader(resp) {
504
- if (_signalledLowBalance)
505
- return;
506
- const raw = resp.headers?.get?.(BALANCE_HEADER);
507
- if (!raw)
508
- return;
509
- if (!/^-?\d+$/.test(raw.trim()))
510
- return;
511
- const balance = Number(raw.trim());
512
- if (!Number.isFinite(balance))
513
- return;
514
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
515
- return;
516
- if (balance <= 0)
517
- return;
518
- _signalledLowBalance = true;
519
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
520
- enqueueNotification({
521
- id: "low-balance-warning",
522
- severity: "warn",
523
- transient: true,
524
- title: "Your org's Hivemind balance is running low",
525
- body: `Only $${(balance / 100).toFixed(2)} of prepaid balance remains. Admins can top up at ${billingUrl()}; otherwise ask an org admin to top up before requests start failing.`,
526
- dedupKey: { reason: "low-balance" }
527
- }).catch((e) => {
528
- _signalledLowBalance = false;
529
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
530
- });
531
- }
532
504
  function billingUrl() {
533
505
  try {
534
506
  const c = loadCredentials();
@@ -654,7 +626,6 @@ var DeeplakeApi = class {
654
626
  }
655
627
  throw lastError;
656
628
  }
657
- signalLowBalanceFromHeader(resp);
658
629
  if (resp.ok) {
659
630
  const raw = await resp.json();
660
631
  if (!raw?.rows || !raw?.columns)
@@ -815,7 +786,6 @@ var DeeplakeApi = class {
815
786
  ...deeplakeClientHeader()
816
787
  }
817
788
  });
818
- signalLowBalanceFromHeader(resp);
819
789
  if (resp.ok) {
820
790
  const data = await resp.json();
821
791
  return {
@@ -126,7 +126,7 @@ function tryAcquireLock(sessionId, maxAgeMs = 10 * 60 * 1e3) {
126
126
  }
127
127
 
128
128
  // dist/src/hooks/cursor/spawn-wiki-worker.js
129
- import { spawn, execSync } from "node:child_process";
129
+ import { execSync } from "node:child_process";
130
130
  import { fileURLToPath } from "node:url";
131
131
  import { dirname as dirname2, join as join6 } from "node:path";
132
132
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "node:fs";
@@ -192,6 +192,32 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
192
192
  return null;
193
193
  }
194
194
 
195
+ // dist/src/utils/spawn-detached.js
196
+ import { spawn as nodeSpawn } from "node:child_process";
197
+ function spawnDetachedNodeWorker(workerPath, args = [], deps = {}) {
198
+ const spawn = deps.spawn ?? nodeSpawn;
199
+ const execPath = deps.execPath ?? process.execPath;
200
+ try {
201
+ const child = spawn(execPath, [workerPath, ...args], {
202
+ detached: true,
203
+ stdio: ["ignore", "ignore", "ignore"],
204
+ // Suppress the transient console window Windows would otherwise pop for
205
+ // the detached worker. No-op on POSIX.
206
+ windowsHide: true
207
+ });
208
+ child.on("error", () => {
209
+ });
210
+ child.unref();
211
+ } catch {
212
+ }
213
+ }
214
+
215
+ // dist/src/utils/project-name.js
216
+ import { basename } from "node:path";
217
+ function projectNameFromCwd(cwd) {
218
+ return basename(cwd ?? "") || "unknown";
219
+ }
220
+
195
221
  // dist/src/hooks/cursor/spawn-wiki-worker.js
196
222
  var HOME = homedir4();
197
223
  var wikiLogger = makeWikiLogger(join6(HOME, ".cursor", "hooks"));
@@ -255,7 +281,7 @@ function findCursorBin() {
255
281
  }
256
282
  function spawnCursorWikiWorker(opts) {
257
283
  const { config, sessionId, cwd, bundleDir, reason } = opts;
258
- const projectName = cwd.split("/").pop() || "unknown";
284
+ const projectName = projectNameFromCwd(cwd);
259
285
  const tmpDir = join6(tmpdir(), `deeplake-wiki-${sessionId}-${Date.now()}`);
260
286
  mkdirSync3(tmpDir, { recursive: true });
261
287
  const pluginVersion = getInstalledVersion(bundleDir, ".claude-plugin") ?? "";
@@ -280,10 +306,7 @@ function spawnCursorWikiWorker(opts) {
280
306
  }));
281
307
  wikiLog(`${reason}: spawning summary worker for ${sessionId}`);
282
308
  const workerPath = join6(bundleDir, "wiki-worker.js");
283
- spawn("nohup", ["node", workerPath, configFile], {
284
- detached: true,
285
- stdio: ["ignore", "ignore", "ignore"]
286
- }).unref();
309
+ spawnDetachedNodeWorker(workerPath, [configFile]);
287
310
  wikiLog(`${reason}: spawned summary worker for ${sessionId}`);
288
311
  }
289
312
  function bundleDirFromImportMeta(importMetaUrl) {
@@ -291,7 +314,6 @@ function bundleDirFromImportMeta(importMetaUrl) {
291
314
  }
292
315
 
293
316
  // dist/src/skillify/spawn-skillify-worker.js
294
- import { spawn as spawn2 } from "node:child_process";
295
317
  import { fileURLToPath as fileURLToPath2 } from "node:url";
296
318
  import { dirname as dirname3, join as join8 } from "node:path";
297
319
  import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, appendFileSync as appendFileSync3, chmodSync } from "node:fs";
@@ -412,10 +434,7 @@ function spawnSkillifyWorker(opts) {
412
434
  }
413
435
  skillifyLog(`${reason}: spawning skillify worker for project=${project} key=${projectKey}`);
414
436
  const workerPath = join8(bundleDir, "skillify-worker.js");
415
- spawn2("nohup", ["node", workerPath, configFile], {
416
- detached: true,
417
- stdio: ["ignore", "ignore", "ignore"]
418
- }).unref();
437
+ spawnDetachedNodeWorker(workerPath, [configFile]);
419
438
  skillifyLog(`${reason}: spawned skillify worker for ${projectKey}`);
420
439
  }
421
440
 
@@ -426,7 +445,7 @@ import { join as join11 } from "node:path";
426
445
  // dist/src/utils/repo-identity.js
427
446
  import { execSync as execSync2 } from "node:child_process";
428
447
  import { createHash } from "node:crypto";
429
- import { basename, resolve } from "node:path";
448
+ import { basename as basename2, resolve } from "node:path";
430
449
  var DEFAULT_PORTS = {
431
450
  http: "80",
432
451
  https: "443",
@@ -454,7 +473,7 @@ function normalizeGitRemoteUrl(url) {
454
473
  }
455
474
  function deriveProjectKey(cwd) {
456
475
  const absCwd = resolve(cwd);
457
- const project = basename(absCwd) || "unknown";
476
+ const project = basename2(absCwd) || "unknown";
458
477
  let signature = null;
459
478
  try {
460
479
  const raw = execSync2("git config --get remote.origin.url", {
@@ -533,9 +533,6 @@ function traceSql(msg) {
533
533
  log3(msg);
534
534
  }
535
535
  var _signalledBalanceExhausted = false;
536
- var _signalledLowBalance = false;
537
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
538
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
539
536
  function maybeSignalBalanceExhausted(status, bodyText) {
540
537
  if (status !== 402)
541
538
  return;
@@ -551,40 +548,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
551
548
  transient: true,
552
549
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
553
550
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
554
- dedupKey: { reason: "balance-zero" }
551
+ dedupKey: { reason: "balance-zero" },
552
+ // User-facing billing notice → user channel only. Never the model's
553
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
554
+ // is a prompt-injection pattern external agents flag.
555
+ userVisibleOnly: true
555
556
  }).catch((e) => {
556
557
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
557
558
  });
558
559
  }
559
- function signalLowBalanceFromHeader(resp) {
560
- if (_signalledLowBalance)
561
- return;
562
- const raw = resp.headers?.get?.(BALANCE_HEADER);
563
- if (!raw)
564
- return;
565
- if (!/^-?\d+$/.test(raw.trim()))
566
- return;
567
- const balance = Number(raw.trim());
568
- if (!Number.isFinite(balance))
569
- return;
570
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
571
- return;
572
- if (balance <= 0)
573
- return;
574
- _signalledLowBalance = true;
575
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
576
- enqueueNotification({
577
- id: "low-balance-warning",
578
- severity: "warn",
579
- transient: true,
580
- title: "Your org's Hivemind balance is running low",
581
- body: `Only $${(balance / 100).toFixed(2)} of prepaid balance remains. Admins can top up at ${billingUrl()}; otherwise ask an org admin to top up before requests start failing.`,
582
- dedupKey: { reason: "low-balance" }
583
- }).catch((e) => {
584
- _signalledLowBalance = false;
585
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
586
- });
587
- }
588
560
  function billingUrl() {
589
561
  try {
590
562
  const c = loadCredentials();
@@ -710,7 +682,6 @@ var DeeplakeApi = class {
710
682
  }
711
683
  throw lastError;
712
684
  }
713
- signalLowBalanceFromHeader(resp);
714
685
  if (resp.ok) {
715
686
  const raw = await resp.json();
716
687
  if (!raw?.rows || !raw?.columns)
@@ -871,7 +842,6 @@ var DeeplakeApi = class {
871
842
  ...deeplakeClientHeader()
872
843
  }
873
844
  });
874
- signalLowBalanceFromHeader(resp);
875
845
  if (resp.ok) {
876
846
  const data = await resp.json();
877
847
  return {
@@ -1222,6 +1192,12 @@ function sanitizeForInject(text) {
1222
1192
  }
1223
1193
  var LINE_TERMINATOR_RE = /\r\n?|[\n\u2028\u2029\u0085]/g;
1224
1194
 
1195
+ // dist/src/utils/project-name.js
1196
+ import { basename } from "node:path";
1197
+ function projectNameFromCwd(cwd) {
1198
+ return basename(cwd ?? "") || "unknown";
1199
+ }
1200
+
1225
1201
  // dist/src/cli/skillify-spec.js
1226
1202
  var SKILLIFY_COMMANDS = [
1227
1203
  { cmd: "hivemind skillify", desc: "show scope, team, install, per-project state" },
@@ -2274,7 +2250,7 @@ async function createPlaceholder(api, table, sessionId, cwd, userName, orgName,
2274
2250
  if (existing.length > 0)
2275
2251
  return;
2276
2252
  const now = (/* @__PURE__ */ new Date()).toISOString();
2277
- const projectName = cwd.split("/").pop() ?? "unknown";
2253
+ const projectName = projectNameFromCwd(cwd);
2278
2254
  const sessionSource = `/sessions/${userName}/${userName}_${orgName}_${workspaceId}_${sessionId}.jsonl`;
2279
2255
  const content = [
2280
2256
  `# Session ${sessionId}`,
@@ -67172,9 +67172,6 @@ function traceSql(msg) {
67172
67172
  log3(msg);
67173
67173
  }
67174
67174
  var _signalledBalanceExhausted = false;
67175
- var _signalledLowBalance = false;
67176
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
67177
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
67178
67175
  function maybeSignalBalanceExhausted(status, bodyText) {
67179
67176
  if (status !== 402)
67180
67177
  return;
@@ -67190,40 +67187,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
67190
67187
  transient: true,
67191
67188
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
67192
67189
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
67193
- dedupKey: { reason: "balance-zero" }
67190
+ dedupKey: { reason: "balance-zero" },
67191
+ // User-facing billing notice → user channel only. Never the model's
67192
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
67193
+ // is a prompt-injection pattern external agents flag.
67194
+ userVisibleOnly: true
67194
67195
  }).catch((e6) => {
67195
67196
  log3(`enqueue balance-exhausted failed: ${e6 instanceof Error ? e6.message : String(e6)}`);
67196
67197
  });
67197
67198
  }
67198
- function signalLowBalanceFromHeader(resp) {
67199
- if (_signalledLowBalance)
67200
- return;
67201
- const raw = resp.headers?.get?.(BALANCE_HEADER);
67202
- if (!raw)
67203
- return;
67204
- if (!/^-?\d+$/.test(raw.trim()))
67205
- return;
67206
- const balance = Number(raw.trim());
67207
- if (!Number.isFinite(balance))
67208
- return;
67209
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
67210
- return;
67211
- if (balance <= 0)
67212
- return;
67213
- _signalledLowBalance = true;
67214
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
67215
- enqueueNotification({
67216
- id: "low-balance-warning",
67217
- severity: "warn",
67218
- transient: true,
67219
- title: "Your org's Hivemind balance is running low",
67220
- body: `Only $${(balance / 100).toFixed(2)} of prepaid balance remains. Admins can top up at ${billingUrl()}; otherwise ask an org admin to top up before requests start failing.`,
67221
- dedupKey: { reason: "low-balance" }
67222
- }).catch((e6) => {
67223
- _signalledLowBalance = false;
67224
- log3(`enqueue low-balance failed: ${e6 instanceof Error ? e6.message : String(e6)}`);
67225
- });
67226
- }
67227
67199
  function billingUrl() {
67228
67200
  try {
67229
67201
  const c15 = loadCredentials();
@@ -67349,7 +67321,6 @@ var DeeplakeApi = class {
67349
67321
  }
67350
67322
  throw lastError;
67351
67323
  }
67352
- signalLowBalanceFromHeader(resp);
67353
67324
  if (resp.ok) {
67354
67325
  const raw = await resp.json();
67355
67326
  if (!raw?.rows || !raw?.columns)
@@ -67510,7 +67481,6 @@ var DeeplakeApi = class {
67510
67481
  ...deeplakeClientHeader()
67511
67482
  }
67512
67483
  });
67513
- signalLowBalanceFromHeader(resp);
67514
67484
  if (resp.ok) {
67515
67485
  const data = await resp.json();
67516
67486
  return {
@@ -477,9 +477,6 @@ function traceSql(msg) {
477
477
  log3(msg);
478
478
  }
479
479
  var _signalledBalanceExhausted = false;
480
- var _signalledLowBalance = false;
481
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
482
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
483
480
  function maybeSignalBalanceExhausted(status, bodyText) {
484
481
  if (status !== 402)
485
482
  return;
@@ -495,40 +492,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
495
492
  transient: true,
496
493
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
497
494
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
498
- dedupKey: { reason: "balance-zero" }
495
+ dedupKey: { reason: "balance-zero" },
496
+ // User-facing billing notice → user channel only. Never the model's
497
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
498
+ // is a prompt-injection pattern external agents flag.
499
+ userVisibleOnly: true
499
500
  }).catch((e) => {
500
501
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
501
502
  });
502
503
  }
503
- function signalLowBalanceFromHeader(resp) {
504
- if (_signalledLowBalance)
505
- return;
506
- const raw = resp.headers?.get?.(BALANCE_HEADER);
507
- if (!raw)
508
- return;
509
- if (!/^-?\d+$/.test(raw.trim()))
510
- return;
511
- const balance = Number(raw.trim());
512
- if (!Number.isFinite(balance))
513
- return;
514
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
515
- return;
516
- if (balance <= 0)
517
- return;
518
- _signalledLowBalance = true;
519
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
520
- enqueueNotification({
521
- id: "low-balance-warning",
522
- severity: "warn",
523
- transient: true,
524
- title: "Your org's Hivemind balance is running low",
525
- body: `Only $${(balance / 100).toFixed(2)} of prepaid balance remains. Admins can top up at ${billingUrl()}; otherwise ask an org admin to top up before requests start failing.`,
526
- dedupKey: { reason: "low-balance" }
527
- }).catch((e) => {
528
- _signalledLowBalance = false;
529
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
530
- });
531
- }
532
504
  function billingUrl() {
533
505
  try {
534
506
  const c = loadCredentials();
@@ -654,7 +626,6 @@ var DeeplakeApi = class {
654
626
  }
655
627
  throw lastError;
656
628
  }
657
- signalLowBalanceFromHeader(resp);
658
629
  if (resp.ok) {
659
630
  const raw = await resp.json();
660
631
  if (!raw?.rows || !raw?.columns)
@@ -815,7 +786,6 @@ var DeeplakeApi = class {
815
786
  ...deeplakeClientHeader()
816
787
  }
817
788
  });
818
- signalLowBalanceFromHeader(resp);
819
789
  if (resp.ok) {
820
790
  const data = await resp.json();
821
791
  return {
@@ -1004,6 +974,12 @@ var DeeplakeApi = class {
1004
974
  }
1005
975
  };
1006
976
 
977
+ // dist/src/utils/project-name.js
978
+ import { basename } from "node:path";
979
+ function projectNameFromCwd(cwd) {
980
+ return basename(cwd ?? "") || "unknown";
981
+ }
982
+
1007
983
  // dist/src/utils/session-path.js
1008
984
  function buildSessionPath(config, sessionId) {
1009
985
  const workspace = config.workspaceId ?? "default";
@@ -1529,9 +1505,9 @@ function embeddingsDisabled() {
1529
1505
  // dist/src/embeddings/self-heal.js
1530
1506
  import { existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync5, readlinkSync, renameSync as renameSync3, rmSync, symlinkSync, statSync as statSync2 } from "node:fs";
1531
1507
  import { homedir as homedir8 } from "node:os";
1532
- import { basename, dirname as dirname2, join as join9 } from "node:path";
1508
+ import { basename as basename2, dirname as dirname2, join as join9 } from "node:path";
1533
1509
  function ensurePluginNodeModulesLink(opts) {
1534
- if (basename(opts.bundleDir) !== "bundle") {
1510
+ if (basename2(opts.bundleDir) !== "bundle") {
1535
1511
  return { kind: "not-bundle-layout", bundleDir: opts.bundleDir };
1536
1512
  }
1537
1513
  const target = opts.sharedNodeModules ?? join9(homedir8(), ".hivemind", "embed-deps", "node_modules");
@@ -1730,7 +1706,7 @@ function releaseLock(sessionId) {
1730
1706
  }
1731
1707
 
1732
1708
  // dist/src/hooks/hermes/spawn-wiki-worker.js
1733
- import { spawn as spawn2, execSync } from "node:child_process";
1709
+ import { execSync } from "node:child_process";
1734
1710
  import { fileURLToPath } from "node:url";
1735
1711
  import { dirname as dirname4, join as join13 } from "node:path";
1736
1712
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync8 } from "node:fs";
@@ -1796,6 +1772,26 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
1796
1772
  return null;
1797
1773
  }
1798
1774
 
1775
+ // dist/src/utils/spawn-detached.js
1776
+ import { spawn as nodeSpawn } from "node:child_process";
1777
+ function spawnDetachedNodeWorker(workerPath, args = [], deps = {}) {
1778
+ const spawn2 = deps.spawn ?? nodeSpawn;
1779
+ const execPath = deps.execPath ?? process.execPath;
1780
+ try {
1781
+ const child = spawn2(execPath, [workerPath, ...args], {
1782
+ detached: true,
1783
+ stdio: ["ignore", "ignore", "ignore"],
1784
+ // Suppress the transient console window Windows would otherwise pop for
1785
+ // the detached worker. No-op on POSIX.
1786
+ windowsHide: true
1787
+ });
1788
+ child.on("error", () => {
1789
+ });
1790
+ child.unref();
1791
+ } catch {
1792
+ }
1793
+ }
1794
+
1799
1795
  // dist/src/hooks/hermes/spawn-wiki-worker.js
1800
1796
  var HOME = homedir10();
1801
1797
  var wikiLogger = makeWikiLogger(join13(HOME, ".hermes", "hooks"));
@@ -1859,7 +1855,7 @@ function findHermesBin() {
1859
1855
  }
1860
1856
  function spawnHermesWikiWorker(opts) {
1861
1857
  const { config, sessionId, cwd, bundleDir, reason } = opts;
1862
- const projectName = cwd.split("/").pop() || "unknown";
1858
+ const projectName = projectNameFromCwd(cwd);
1863
1859
  const tmpDir = join13(tmpdir2(), `deeplake-wiki-${sessionId}-${Date.now()}`);
1864
1860
  mkdirSync8(tmpDir, { recursive: true });
1865
1861
  const pluginVersion = getInstalledVersion(bundleDir, ".claude-plugin") ?? "";
@@ -1885,10 +1881,7 @@ function spawnHermesWikiWorker(opts) {
1885
1881
  }));
1886
1882
  wikiLog(`${reason}: spawning summary worker for ${sessionId}`);
1887
1883
  const workerPath = join13(bundleDir, "wiki-worker.js");
1888
- spawn2("nohup", ["node", workerPath, configFile], {
1889
- detached: true,
1890
- stdio: ["ignore", "ignore", "ignore"]
1891
- }).unref();
1884
+ spawnDetachedNodeWorker(workerPath, [configFile]);
1892
1885
  wikiLog(`${reason}: spawned summary worker for ${sessionId}`);
1893
1886
  }
1894
1887
  function bundleDirFromImportMeta(importMetaUrl) {
@@ -1896,7 +1889,6 @@ function bundleDirFromImportMeta(importMetaUrl) {
1896
1889
  }
1897
1890
 
1898
1891
  // dist/src/skillify/spawn-skillify-worker.js
1899
- import { spawn as spawn3 } from "node:child_process";
1900
1892
  import { fileURLToPath as fileURLToPath2 } from "node:url";
1901
1893
  import { dirname as dirname5, join as join15 } from "node:path";
1902
1894
  import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, chmodSync } from "node:fs";
@@ -2017,10 +2009,7 @@ function spawnSkillifyWorker(opts) {
2017
2009
  }
2018
2010
  skillifyLog(`${reason}: spawning skillify worker for project=${project} key=${projectKey}`);
2019
2011
  const workerPath = join15(bundleDir, "skillify-worker.js");
2020
- spawn3("nohup", ["node", workerPath, configFile], {
2021
- detached: true,
2022
- stdio: ["ignore", "ignore", "ignore"]
2023
- }).unref();
2012
+ spawnDetachedNodeWorker(workerPath, [configFile]);
2024
2013
  skillifyLog(`${reason}: spawned skillify worker for ${projectKey}`);
2025
2014
  }
2026
2015
 
@@ -2031,7 +2020,7 @@ import { join as join18 } from "node:path";
2031
2020
  // dist/src/utils/repo-identity.js
2032
2021
  import { execSync as execSync2 } from "node:child_process";
2033
2022
  import { createHash } from "node:crypto";
2034
- import { basename as basename2, resolve as resolve2 } from "node:path";
2023
+ import { basename as basename3, resolve as resolve2 } from "node:path";
2035
2024
  var DEFAULT_PORTS = {
2036
2025
  http: "80",
2037
2026
  https: "443",
@@ -2059,7 +2048,7 @@ function normalizeGitRemoteUrl(url) {
2059
2048
  }
2060
2049
  function deriveProjectKey(cwd) {
2061
2050
  const absCwd = resolve2(cwd);
2062
- const project = basename2(absCwd) || "unknown";
2051
+ const project = basename3(absCwd) || "unknown";
2063
2052
  let signature = null;
2064
2053
  try {
2065
2054
  const raw = execSync2("git config --get remote.origin.url", {
@@ -2401,7 +2390,7 @@ async function main() {
2401
2390
  const sessionPath = buildSessionPath(config, sessionId);
2402
2391
  const line = JSON.stringify(entry);
2403
2392
  log5(`writing to ${sessionPath}`);
2404
- const projectName = cwd.split("/").pop() || "unknown";
2393
+ const projectName = projectNameFromCwd(cwd);
2405
2394
  const filename = sessionPath.split("/").pop() ?? "";
2406
2395
  const jsonForSql = line.replace(/'/g, "''");
2407
2396
  const embedding = embeddingsDisabled() ? null : await new EmbedClient({ daemonEntry: resolveEmbedDaemonPath() }).embed(line, "document");
@@ -741,9 +741,6 @@ function traceSql(msg) {
741
741
  log3(msg);
742
742
  }
743
743
  var _signalledBalanceExhausted = false;
744
- var _signalledLowBalance = false;
745
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
746
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
747
744
  function maybeSignalBalanceExhausted(status, bodyText) {
748
745
  if (status !== 402)
749
746
  return;
@@ -759,40 +756,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
759
756
  transient: true,
760
757
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
761
758
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
762
- dedupKey: { reason: "balance-zero" }
759
+ dedupKey: { reason: "balance-zero" },
760
+ // User-facing billing notice → user channel only. Never the model's
761
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
762
+ // is a prompt-injection pattern external agents flag.
763
+ userVisibleOnly: true
763
764
  }).catch((e) => {
764
765
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
765
766
  });
766
767
  }
767
- function signalLowBalanceFromHeader(resp) {
768
- if (_signalledLowBalance)
769
- return;
770
- const raw = resp.headers?.get?.(BALANCE_HEADER);
771
- if (!raw)
772
- return;
773
- if (!/^-?\d+$/.test(raw.trim()))
774
- return;
775
- const balance = Number(raw.trim());
776
- if (!Number.isFinite(balance))
777
- return;
778
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
779
- return;
780
- if (balance <= 0)
781
- return;
782
- _signalledLowBalance = true;
783
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
784
- enqueueNotification({
785
- id: "low-balance-warning",
786
- severity: "warn",
787
- transient: true,
788
- title: "Your org's Hivemind balance is running low",
789
- body: `Only $${(balance / 100).toFixed(2)} of prepaid balance remains. Admins can top up at ${billingUrl()}; otherwise ask an org admin to top up before requests start failing.`,
790
- dedupKey: { reason: "low-balance" }
791
- }).catch((e) => {
792
- _signalledLowBalance = false;
793
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
794
- });
795
- }
796
768
  function billingUrl() {
797
769
  try {
798
770
  const c = loadCredentials();
@@ -918,7 +890,6 @@ var DeeplakeApi = class {
918
890
  }
919
891
  throw lastError;
920
892
  }
921
- signalLowBalanceFromHeader(resp);
922
893
  if (resp.ok) {
923
894
  const raw = await resp.json();
924
895
  if (!raw?.rows || !raw?.columns)
@@ -1079,7 +1050,6 @@ var DeeplakeApi = class {
1079
1050
  ...deeplakeClientHeader()
1080
1051
  }
1081
1052
  });
1082
- signalLowBalanceFromHeader(resp);
1083
1053
  if (resp.ok) {
1084
1054
  const data = await resp.json();
1085
1055
  return {
@@ -468,9 +468,6 @@ function traceSql(msg) {
468
468
  log3(msg);
469
469
  }
470
470
  var _signalledBalanceExhausted = false;
471
- var _signalledLowBalance = false;
472
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
473
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
474
471
  function maybeSignalBalanceExhausted(status, bodyText) {
475
472
  if (status !== 402)
476
473
  return;
@@ -486,40 +483,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
486
483
  transient: true,
487
484
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
488
485
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
489
- dedupKey: { reason: "balance-zero" }
486
+ dedupKey: { reason: "balance-zero" },
487
+ // User-facing billing notice → user channel only. Never the model's
488
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
489
+ // is a prompt-injection pattern external agents flag.
490
+ userVisibleOnly: true
490
491
  }).catch((e) => {
491
492
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
492
493
  });
493
494
  }
494
- function signalLowBalanceFromHeader(resp) {
495
- if (_signalledLowBalance)
496
- return;
497
- const raw = resp.headers?.get?.(BALANCE_HEADER);
498
- if (!raw)
499
- return;
500
- if (!/^-?\d+$/.test(raw.trim()))
501
- return;
502
- const balance = Number(raw.trim());
503
- if (!Number.isFinite(balance))
504
- return;
505
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
506
- return;
507
- if (balance <= 0)
508
- return;
509
- _signalledLowBalance = true;
510
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
511
- enqueueNotification({
512
- id: "low-balance-warning",
513
- severity: "warn",
514
- transient: true,
515
- title: "Your org's Hivemind balance is running low",
516
- body: `Only $${(balance / 100).toFixed(2)} of prepaid balance remains. Admins can top up at ${billingUrl()}; otherwise ask an org admin to top up before requests start failing.`,
517
- dedupKey: { reason: "low-balance" }
518
- }).catch((e) => {
519
- _signalledLowBalance = false;
520
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
521
- });
522
- }
523
495
  function billingUrl() {
524
496
  try {
525
497
  const c = loadCredentials();
@@ -645,7 +617,6 @@ var DeeplakeApi = class {
645
617
  }
646
618
  throw lastError;
647
619
  }
648
- signalLowBalanceFromHeader(resp);
649
620
  if (resp.ok) {
650
621
  const raw = await resp.json();
651
622
  if (!raw?.rows || !raw?.columns)
@@ -806,7 +777,6 @@ var DeeplakeApi = class {
806
777
  ...deeplakeClientHeader()
807
778
  }
808
779
  });
809
- signalLowBalanceFromHeader(resp);
810
780
  if (resp.ok) {
811
781
  const data = await resp.json();
812
782
  return {