@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.
@@ -718,9 +718,6 @@ function traceSql(msg) {
718
718
  log3(msg);
719
719
  }
720
720
  var _signalledBalanceExhausted = false;
721
- var _signalledLowBalance = false;
722
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
723
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
724
721
  function maybeSignalBalanceExhausted(status, bodyText) {
725
722
  if (status !== 402)
726
723
  return;
@@ -736,40 +733,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
736
733
  transient: true,
737
734
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
738
735
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
739
- dedupKey: { reason: "balance-zero" }
736
+ dedupKey: { reason: "balance-zero" },
737
+ // User-facing billing notice → user channel only. Never the model's
738
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
739
+ // is a prompt-injection pattern external agents flag.
740
+ userVisibleOnly: true
740
741
  }).catch((e) => {
741
742
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
742
743
  });
743
744
  }
744
- function signalLowBalanceFromHeader(resp) {
745
- if (_signalledLowBalance)
746
- return;
747
- const raw = resp.headers?.get?.(BALANCE_HEADER);
748
- if (!raw)
749
- return;
750
- if (!/^-?\d+$/.test(raw.trim()))
751
- return;
752
- const balance = Number(raw.trim());
753
- if (!Number.isFinite(balance))
754
- return;
755
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
756
- return;
757
- if (balance <= 0)
758
- return;
759
- _signalledLowBalance = true;
760
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
761
- enqueueNotification({
762
- id: "low-balance-warning",
763
- severity: "warn",
764
- transient: true,
765
- title: "Your org's Hivemind balance is running low",
766
- 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.`,
767
- dedupKey: { reason: "low-balance" }
768
- }).catch((e) => {
769
- _signalledLowBalance = false;
770
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
771
- });
772
- }
773
745
  function billingUrl() {
774
746
  try {
775
747
  const c = loadCredentials();
@@ -895,7 +867,6 @@ var DeeplakeApi = class {
895
867
  }
896
868
  throw lastError;
897
869
  }
898
- signalLowBalanceFromHeader(resp);
899
870
  if (resp.ok) {
900
871
  const raw = await resp.json();
901
872
  if (!raw?.rows || !raw?.columns)
@@ -1056,7 +1027,6 @@ var DeeplakeApi = class {
1056
1027
  ...deeplakeClientHeader()
1057
1028
  }
1058
1029
  });
1059
- signalLowBalanceFromHeader(resp);
1060
1030
  if (resp.ok) {
1061
1031
  const data = await resp.json();
1062
1032
  return {
@@ -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 {
@@ -483,9 +483,6 @@ function traceSql(msg) {
483
483
  log3(msg);
484
484
  }
485
485
  var _signalledBalanceExhausted = false;
486
- var _signalledLowBalance = false;
487
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
488
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
489
486
  function maybeSignalBalanceExhausted(status, bodyText) {
490
487
  if (status !== 402)
491
488
  return;
@@ -501,40 +498,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
501
498
  transient: true,
502
499
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
503
500
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
504
- dedupKey: { reason: "balance-zero" }
501
+ dedupKey: { reason: "balance-zero" },
502
+ // User-facing billing notice → user channel only. Never the model's
503
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
504
+ // is a prompt-injection pattern external agents flag.
505
+ userVisibleOnly: true
505
506
  }).catch((e) => {
506
507
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
507
508
  });
508
509
  }
509
- function signalLowBalanceFromHeader(resp) {
510
- if (_signalledLowBalance)
511
- return;
512
- const raw = resp.headers?.get?.(BALANCE_HEADER);
513
- if (!raw)
514
- return;
515
- if (!/^-?\d+$/.test(raw.trim()))
516
- return;
517
- const balance = Number(raw.trim());
518
- if (!Number.isFinite(balance))
519
- return;
520
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
521
- return;
522
- if (balance <= 0)
523
- return;
524
- _signalledLowBalance = true;
525
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
526
- enqueueNotification({
527
- id: "low-balance-warning",
528
- severity: "warn",
529
- transient: true,
530
- title: "Your org's Hivemind balance is running low",
531
- 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.`,
532
- dedupKey: { reason: "low-balance" }
533
- }).catch((e) => {
534
- _signalledLowBalance = false;
535
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
536
- });
537
- }
538
510
  function billingUrl() {
539
511
  try {
540
512
  const c = loadCredentials();
@@ -660,7 +632,6 @@ var DeeplakeApi = class {
660
632
  }
661
633
  throw lastError;
662
634
  }
663
- signalLowBalanceFromHeader(resp);
664
635
  if (resp.ok) {
665
636
  const raw = await resp.json();
666
637
  if (!raw?.rows || !raw?.columns)
@@ -821,7 +792,6 @@ var DeeplakeApi = class {
821
792
  ...deeplakeClientHeader()
822
793
  }
823
794
  });
824
- signalLowBalanceFromHeader(resp);
825
795
  if (resp.ok) {
826
796
  const data = await resp.json();
827
797
  return {
@@ -1010,8 +980,14 @@ var DeeplakeApi = class {
1010
980
  }
1011
981
  };
1012
982
 
983
+ // dist/src/utils/project-name.js
984
+ import { basename } from "node:path";
985
+ function projectNameFromCwd(cwd) {
986
+ return basename(cwd ?? "") || "unknown";
987
+ }
988
+
1013
989
  // dist/src/hooks/codex/spawn-wiki-worker.js
1014
- import { spawn, execSync } from "node:child_process";
990
+ import { execSync } from "node:child_process";
1015
991
  import { fileURLToPath } from "node:url";
1016
992
  import { dirname as dirname2, join as join8 } from "node:path";
1017
993
  import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "node:fs";
@@ -1077,6 +1053,26 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
1077
1053
  return null;
1078
1054
  }
1079
1055
 
1056
+ // dist/src/utils/spawn-detached.js
1057
+ import { spawn as nodeSpawn } from "node:child_process";
1058
+ function spawnDetachedNodeWorker(workerPath, args = [], deps = {}) {
1059
+ const spawn2 = deps.spawn ?? nodeSpawn;
1060
+ const execPath = deps.execPath ?? process.execPath;
1061
+ try {
1062
+ const child = spawn2(execPath, [workerPath, ...args], {
1063
+ detached: true,
1064
+ stdio: ["ignore", "ignore", "ignore"],
1065
+ // Suppress the transient console window Windows would otherwise pop for
1066
+ // the detached worker. No-op on POSIX.
1067
+ windowsHide: true
1068
+ });
1069
+ child.on("error", () => {
1070
+ });
1071
+ child.unref();
1072
+ } catch {
1073
+ }
1074
+ }
1075
+
1080
1076
  // dist/src/hooks/codex/spawn-wiki-worker.js
1081
1077
  var HOME = homedir5();
1082
1078
  var wikiLogger = makeWikiLogger(join8(HOME, ".codex", "hooks"));
@@ -1140,7 +1136,7 @@ function findCodexBin() {
1140
1136
  }
1141
1137
  function spawnCodexWikiWorker(opts) {
1142
1138
  const { config, sessionId, cwd, bundleDir, reason } = opts;
1143
- const projectName = cwd.split("/").pop() || "unknown";
1139
+ const projectName = projectNameFromCwd(cwd);
1144
1140
  const tmpDir = join8(tmpdir2(), `deeplake-wiki-${sessionId}-${Date.now()}`);
1145
1141
  mkdirSync5(tmpDir, { recursive: true });
1146
1142
  const pluginVersion = getInstalledVersion(bundleDir, ".codex-plugin") ?? "";
@@ -1164,10 +1160,7 @@ function spawnCodexWikiWorker(opts) {
1164
1160
  }));
1165
1161
  wikiLog(`${reason}: spawning summary worker for ${sessionId}`);
1166
1162
  const workerPath = join8(bundleDir, "wiki-worker.js");
1167
- spawn("nohup", ["node", workerPath, configFile], {
1168
- detached: true,
1169
- stdio: ["ignore", "ignore", "ignore"]
1170
- }).unref();
1163
+ spawnDetachedNodeWorker(workerPath, [configFile]);
1171
1164
  wikiLog(`${reason}: spawned summary worker for ${sessionId}`);
1172
1165
  }
1173
1166
  function bundleDirFromImportMeta(importMetaUrl) {
@@ -1175,7 +1168,6 @@ function bundleDirFromImportMeta(importMetaUrl) {
1175
1168
  }
1176
1169
 
1177
1170
  // dist/src/skillify/spawn-skillify-worker.js
1178
- import { spawn as spawn2 } from "node:child_process";
1179
1171
  import { fileURLToPath as fileURLToPath2 } from "node:url";
1180
1172
  import { dirname as dirname3, join as join10 } from "node:path";
1181
1173
  import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, appendFileSync as appendFileSync3, chmodSync } from "node:fs";
@@ -1296,10 +1288,7 @@ function spawnSkillifyWorker(opts) {
1296
1288
  }
1297
1289
  skillifyLog(`${reason}: spawning skillify worker for project=${project} key=${projectKey}`);
1298
1290
  const workerPath = join10(bundleDir, "skillify-worker.js");
1299
- spawn2("nohup", ["node", workerPath, configFile], {
1300
- detached: true,
1301
- stdio: ["ignore", "ignore", "ignore"]
1302
- }).unref();
1291
+ spawnDetachedNodeWorker(workerPath, [configFile]);
1303
1292
  skillifyLog(`${reason}: spawned skillify worker for ${projectKey}`);
1304
1293
  }
1305
1294
 
@@ -1310,7 +1299,7 @@ import { join as join13 } from "node:path";
1310
1299
  // dist/src/utils/repo-identity.js
1311
1300
  import { execSync as execSync2 } from "node:child_process";
1312
1301
  import { createHash } from "node:crypto";
1313
- import { basename, resolve as resolve2 } from "node:path";
1302
+ import { basename as basename2, resolve as resolve2 } from "node:path";
1314
1303
  var DEFAULT_PORTS = {
1315
1304
  http: "80",
1316
1305
  https: "443",
@@ -1338,7 +1327,7 @@ function normalizeGitRemoteUrl(url) {
1338
1327
  }
1339
1328
  function deriveProjectKey(cwd) {
1340
1329
  const absCwd = resolve2(cwd);
1341
- const project = basename(absCwd) || "unknown";
1330
+ const project = basename2(absCwd) || "unknown";
1342
1331
  let signature = null;
1343
1332
  try {
1344
1333
  const raw = execSync2("git config --get remote.origin.url", {
@@ -1645,7 +1634,7 @@ function buildSessionPath(config, sessionId) {
1645
1634
 
1646
1635
  // dist/src/embeddings/client.js
1647
1636
  import { connect } from "node:net";
1648
- import { spawn as spawn3 } from "node:child_process";
1637
+ import { spawn } from "node:child_process";
1649
1638
  import { openSync as openSync4, closeSync as closeSync4, writeSync as writeSync3, unlinkSync as unlinkSync5, existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
1650
1639
  import { homedir as homedir10 } from "node:os";
1651
1640
  import { join as join16 } from "node:path";
@@ -1944,7 +1933,7 @@ var EmbedClient = class {
1944
1933
  return;
1945
1934
  }
1946
1935
  try {
1947
- const child = spawn3(process.execPath, [this.daemonEntry], {
1936
+ const child = spawn(process.execPath, [this.daemonEntry], {
1948
1937
  detached: true,
1949
1938
  stdio: "ignore",
1950
1939
  env: process.env
@@ -2225,7 +2214,7 @@ async function main() {
2225
2214
  };
2226
2215
  const line = JSON.stringify(entry);
2227
2216
  const sessionPath = buildSessionPath(config, sessionId);
2228
- const projectName = (input.cwd ?? "").split("/").pop() || "unknown";
2217
+ const projectName = projectNameFromCwd(input.cwd);
2229
2218
  const filename = sessionPath.split("/").pop() ?? "";
2230
2219
  const jsonForSql = line.replace(/'/g, "''");
2231
2220
  const embedding = embeddingsDisabled() ? null : await new EmbedClient({ daemonEntry: resolveEmbedDaemonPath() }).embed(line, "document");
@@ -478,9 +478,6 @@ function traceSql(msg) {
478
478
  log3(msg);
479
479
  }
480
480
  var _signalledBalanceExhausted = false;
481
- var _signalledLowBalance = false;
482
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
483
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
484
481
  function maybeSignalBalanceExhausted(status, bodyText) {
485
482
  if (status !== 402)
486
483
  return;
@@ -496,40 +493,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
496
493
  transient: true,
497
494
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
498
495
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
499
- dedupKey: { reason: "balance-zero" }
496
+ dedupKey: { reason: "balance-zero" },
497
+ // User-facing billing notice → user channel only. Never the model's
498
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
499
+ // is a prompt-injection pattern external agents flag.
500
+ userVisibleOnly: true
500
501
  }).catch((e) => {
501
502
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
502
503
  });
503
504
  }
504
- function signalLowBalanceFromHeader(resp) {
505
- if (_signalledLowBalance)
506
- return;
507
- const raw = resp.headers?.get?.(BALANCE_HEADER);
508
- if (!raw)
509
- return;
510
- if (!/^-?\d+$/.test(raw.trim()))
511
- return;
512
- const balance = Number(raw.trim());
513
- if (!Number.isFinite(balance))
514
- return;
515
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
516
- return;
517
- if (balance <= 0)
518
- return;
519
- _signalledLowBalance = true;
520
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
521
- enqueueNotification({
522
- id: "low-balance-warning",
523
- severity: "warn",
524
- transient: true,
525
- title: "Your org's Hivemind balance is running low",
526
- 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.`,
527
- dedupKey: { reason: "low-balance" }
528
- }).catch((e) => {
529
- _signalledLowBalance = false;
530
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
531
- });
532
- }
533
505
  function billingUrl() {
534
506
  try {
535
507
  const c = loadCredentials();
@@ -655,7 +627,6 @@ var DeeplakeApi = class {
655
627
  }
656
628
  throw lastError;
657
629
  }
658
- signalLowBalanceFromHeader(resp);
659
630
  if (resp.ok) {
660
631
  const raw = await resp.json();
661
632
  if (!raw?.rows || !raw?.columns)
@@ -816,7 +787,6 @@ var DeeplakeApi = class {
816
787
  ...deeplakeClientHeader()
817
788
  }
818
789
  });
819
- signalLowBalanceFromHeader(resp);
820
790
  if (resp.ok) {
821
791
  const data = await resp.json();
822
792
  return {
@@ -1005,6 +975,12 @@ var DeeplakeApi = class {
1005
975
  }
1006
976
  };
1007
977
 
978
+ // dist/src/utils/project-name.js
979
+ import { basename } from "node:path";
980
+ function projectNameFromCwd(cwd) {
981
+ return basename(cwd ?? "") || "unknown";
982
+ }
983
+
1008
984
  // dist/src/utils/session-path.js
1009
985
  function buildSessionPath(config, sessionId) {
1010
986
  const workspace = config.workspaceId ?? "default";
@@ -1530,9 +1506,9 @@ function embeddingsDisabled() {
1530
1506
  // dist/src/embeddings/self-heal.js
1531
1507
  import { existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync5, readlinkSync, renameSync as renameSync3, rmSync, symlinkSync, statSync as statSync2 } from "node:fs";
1532
1508
  import { homedir as homedir8 } from "node:os";
1533
- import { basename, dirname as dirname2, join as join9 } from "node:path";
1509
+ import { basename as basename2, dirname as dirname2, join as join9 } from "node:path";
1534
1510
  function ensurePluginNodeModulesLink(opts) {
1535
- if (basename(opts.bundleDir) !== "bundle") {
1511
+ if (basename2(opts.bundleDir) !== "bundle") {
1536
1512
  return { kind: "not-bundle-layout", bundleDir: opts.bundleDir };
1537
1513
  }
1538
1514
  const target = opts.sharedNodeModules ?? join9(homedir8(), ".hivemind", "embed-deps", "node_modules");
@@ -1731,7 +1707,7 @@ function releaseLock(sessionId) {
1731
1707
  }
1732
1708
 
1733
1709
  // dist/src/hooks/cursor/spawn-wiki-worker.js
1734
- import { spawn as spawn2, execSync } from "node:child_process";
1710
+ import { execSync } from "node:child_process";
1735
1711
  import { fileURLToPath } from "node:url";
1736
1712
  import { dirname as dirname4, join as join13 } from "node:path";
1737
1713
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync8 } from "node:fs";
@@ -1797,6 +1773,26 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
1797
1773
  return null;
1798
1774
  }
1799
1775
 
1776
+ // dist/src/utils/spawn-detached.js
1777
+ import { spawn as nodeSpawn } from "node:child_process";
1778
+ function spawnDetachedNodeWorker(workerPath, args = [], deps = {}) {
1779
+ const spawn2 = deps.spawn ?? nodeSpawn;
1780
+ const execPath = deps.execPath ?? process.execPath;
1781
+ try {
1782
+ const child = spawn2(execPath, [workerPath, ...args], {
1783
+ detached: true,
1784
+ stdio: ["ignore", "ignore", "ignore"],
1785
+ // Suppress the transient console window Windows would otherwise pop for
1786
+ // the detached worker. No-op on POSIX.
1787
+ windowsHide: true
1788
+ });
1789
+ child.on("error", () => {
1790
+ });
1791
+ child.unref();
1792
+ } catch {
1793
+ }
1794
+ }
1795
+
1800
1796
  // dist/src/hooks/cursor/spawn-wiki-worker.js
1801
1797
  var HOME = homedir10();
1802
1798
  var wikiLogger = makeWikiLogger(join13(HOME, ".cursor", "hooks"));
@@ -1860,7 +1856,7 @@ function findCursorBin() {
1860
1856
  }
1861
1857
  function spawnCursorWikiWorker(opts) {
1862
1858
  const { config, sessionId, cwd, bundleDir, reason } = opts;
1863
- const projectName = cwd.split("/").pop() || "unknown";
1859
+ const projectName = projectNameFromCwd(cwd);
1864
1860
  const tmpDir = join13(tmpdir2(), `deeplake-wiki-${sessionId}-${Date.now()}`);
1865
1861
  mkdirSync8(tmpDir, { recursive: true });
1866
1862
  const pluginVersion = getInstalledVersion(bundleDir, ".claude-plugin") ?? "";
@@ -1885,10 +1881,7 @@ function spawnCursorWikiWorker(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", {
@@ -2403,7 +2392,7 @@ async function main() {
2403
2392
  const sessionPath = buildSessionPath(config, sessionId);
2404
2393
  const line = JSON.stringify(entry);
2405
2394
  log5(`writing to ${sessionPath}`);
2406
- const projectName = cwd.split("/").pop() || "unknown";
2395
+ const projectName = projectNameFromCwd(cwd);
2407
2396
  const filename = sessionPath.split("/").pop() ?? "";
2408
2397
  const jsonForSql = line.replace(/'/g, "''");
2409
2398
  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 {