@deeplake/hivemind 0.7.66 → 0.7.68

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.
@@ -6,18 +6,18 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
9
- "version": "0.7.66"
9
+ "version": "0.7.68"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "hivemind",
14
14
  "description": "Persistent shared memory powered by Deeplake — captures all session activity and provides cross-session, cross-agent memory search",
15
- "version": "0.7.66",
15
+ "version": "0.7.68",
16
16
  "source": {
17
17
  "source": "git-subdir",
18
18
  "url": "https://github.com/activeloopai/hivemind.git",
19
19
  "path": "claude-code",
20
- "sha": "a81e56e347bbfa7c8affadedcc6345ec5e6e2a72"
20
+ "sha": "f0e0e28e1f3687c42c7b46ad1af6379120eab37d"
21
21
  },
22
22
  "homepage": "https://github.com/activeloopai/hivemind"
23
23
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hivemind",
3
3
  "description": "Cloud-backed persistent memory powered by Deeplake — read, write, and share memory across Claude Code sessions and agents",
4
- "version": "0.7.66",
4
+ "version": "0.7.68",
5
5
  "author": {
6
6
  "name": "Activeloop",
7
7
  "url": "https://deeplake.ai"
package/bundle/cli.js CHANGED
@@ -4820,9 +4820,6 @@ function traceSql(msg) {
4820
4820
  log4(msg);
4821
4821
  }
4822
4822
  var _signalledBalanceExhausted = false;
4823
- var _signalledLowBalance = false;
4824
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
4825
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
4826
4823
  function maybeSignalBalanceExhausted(status, bodyText) {
4827
4824
  if (status !== 402)
4828
4825
  return;
@@ -4838,40 +4835,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
4838
4835
  transient: true,
4839
4836
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
4840
4837
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
4841
- dedupKey: { reason: "balance-zero" }
4838
+ dedupKey: { reason: "balance-zero" },
4839
+ // User-facing billing notice → user channel only. Never the model's
4840
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
4841
+ // is a prompt-injection pattern external agents flag.
4842
+ userVisibleOnly: true
4842
4843
  }).catch((e) => {
4843
4844
  log4(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
4844
4845
  });
4845
4846
  }
4846
- function signalLowBalanceFromHeader(resp) {
4847
- if (_signalledLowBalance)
4848
- return;
4849
- const raw = resp.headers?.get?.(BALANCE_HEADER);
4850
- if (!raw)
4851
- return;
4852
- if (!/^-?\d+$/.test(raw.trim()))
4853
- return;
4854
- const balance = Number(raw.trim());
4855
- if (!Number.isFinite(balance))
4856
- return;
4857
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
4858
- return;
4859
- if (balance <= 0)
4860
- return;
4861
- _signalledLowBalance = true;
4862
- log4(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
4863
- enqueueNotification({
4864
- id: "low-balance-warning",
4865
- severity: "warn",
4866
- transient: true,
4867
- title: "Your org's Hivemind balance is running low",
4868
- 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.`,
4869
- dedupKey: { reason: "low-balance" }
4870
- }).catch((e) => {
4871
- _signalledLowBalance = false;
4872
- log4(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
4873
- });
4874
- }
4875
4847
  function billingUrl() {
4876
4848
  try {
4877
4849
  const c = loadCredentials();
@@ -4997,7 +4969,6 @@ var DeeplakeApi = class {
4997
4969
  }
4998
4970
  throw lastError;
4999
4971
  }
5000
- signalLowBalanceFromHeader(resp);
5001
4972
  if (resp.ok) {
5002
4973
  const raw = await resp.json();
5003
4974
  if (!raw?.rows || !raw?.columns)
@@ -5158,7 +5129,6 @@ var DeeplakeApi = class {
5158
5129
  ...deeplakeClientHeader()
5159
5130
  }
5160
5131
  });
5161
- signalLowBalanceFromHeader(resp);
5162
5132
  if (resp.ok) {
5163
5133
  const data = await resp.json();
5164
5134
  return {
@@ -7539,6 +7509,14 @@ var CACHE_TTL_MS = 60 * 60 * 1e3;
7539
7509
  function cacheFilePath() {
7540
7510
  return join28(homedir11(), ".deeplake", "hivemind-stats-cache.json");
7541
7511
  }
7512
+ var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
7513
+ function parseBalanceHeader(resp) {
7514
+ const raw = resp.headers?.get?.(BALANCE_HEADER);
7515
+ if (!raw || !/^-?\d+$/.test(raw.trim()))
7516
+ return null;
7517
+ const n = Number(raw.trim());
7518
+ return Number.isFinite(n) ? n : null;
7519
+ }
7542
7520
  function cacheScopeKey(creds) {
7543
7521
  return JSON.stringify({
7544
7522
  apiUrl: creds.apiUrl ?? DEFAULT_API_URL3,
@@ -7618,7 +7596,8 @@ async function fetchOrgStats(creds) {
7618
7596
  }
7619
7597
  const data = {
7620
7598
  org: scopeFromServer(body.org),
7621
- user: scopeFromServer(body.user)
7599
+ user: scopeFromServer(body.user),
7600
+ balanceCents: parseBalanceHeader(resp)
7622
7601
  };
7623
7602
  writeCache2(scopeKey, data);
7624
7603
  log5(`fetched org stats from ${apiUrl}`);
@@ -11017,6 +10996,30 @@ async function runRulesCommand(args) {
11017
10996
  // dist/src/commands/goal.js
11018
10997
  import { randomUUID as randomUUID4 } from "node:crypto";
11019
10998
  var VALID_STATUS = /* @__PURE__ */ new Set(["opened", "in_progress", "closed"]);
10999
+ var VALID_AGENT = /* @__PURE__ */ new Set(["manual", "capture"]);
11000
+ function parseAgentFlag(args) {
11001
+ const rest = [];
11002
+ let agent = "manual";
11003
+ for (let i = 0; i < args.length; i++) {
11004
+ if (args[i] === "--agent") {
11005
+ const val = args[i + 1];
11006
+ if (!val) {
11007
+ process.stderr.write("usage: --agent requires a value (manual|capture)\n");
11008
+ process.exit(1);
11009
+ }
11010
+ agent = val;
11011
+ i++;
11012
+ continue;
11013
+ }
11014
+ rest.push(args[i]);
11015
+ }
11016
+ if (!VALID_AGENT.has(agent)) {
11017
+ process.stderr.write(`invalid --agent: ${agent} (expected manual|capture)
11018
+ `);
11019
+ process.exit(1);
11020
+ }
11021
+ return { agent, rest };
11022
+ }
11020
11023
  function loadApiOrDie(table) {
11021
11024
  const cfg = loadConfig();
11022
11025
  if (!cfg) {
@@ -11027,7 +11030,7 @@ function loadApiOrDie(table) {
11027
11030
  const query = (sql) => api.query(sql);
11028
11031
  return { api, query, userName: cfg.userName };
11029
11032
  }
11030
- async function goalAdd(text) {
11033
+ async function goalAdd(text, agent = "manual") {
11031
11034
  const cfg = loadConfig();
11032
11035
  if (!cfg) {
11033
11036
  process.stderr.write("hivemind: not logged in.\n");
@@ -11039,7 +11042,7 @@ async function goalAdd(text) {
11039
11042
  const safe = sqlIdent(table);
11040
11043
  const goalId = randomUUID4();
11041
11044
  const ts = (/* @__PURE__ */ new Date()).toISOString();
11042
- await query(`INSERT INTO "${safe}" (id, goal_id, owner, status, content, version, created_at, agent, plugin_version) VALUES ('${randomUUID4()}', '${sqlStr(goalId)}', '${sqlStr(cfg.userName)}', 'opened', E'${sqlStr(text)}', 1, '${sqlStr(ts)}', 'manual', '')`);
11045
+ await query(`INSERT INTO "${safe}" (id, goal_id, owner, status, content, version, created_at, agent, plugin_version) VALUES ('${randomUUID4()}', '${sqlStr(goalId)}', '${sqlStr(cfg.userName)}', 'opened', E'${sqlStr(text)}', 1, '${sqlStr(ts)}', '${sqlStr(agent)}', '')`);
11043
11046
  process.stdout.write(`${goalId}
11044
11047
  `);
11045
11048
  }
@@ -11071,6 +11074,33 @@ async function goalList(filter) {
11071
11074
  process.exit(1);
11072
11075
  }
11073
11076
  }
11077
+ async function goalGet(goalId) {
11078
+ if (!goalId) {
11079
+ process.stderr.write("usage: hivemind goal get <goal_id>\n");
11080
+ process.exit(1);
11081
+ }
11082
+ const cfg = loadConfig();
11083
+ if (!cfg) {
11084
+ process.stderr.write("not logged in\n");
11085
+ process.exit(1);
11086
+ }
11087
+ const { query } = loadApiOrDie(cfg.goalsTableName);
11088
+ const safe = sqlIdent(cfg.goalsTableName);
11089
+ try {
11090
+ const rows = await query(`SELECT content FROM "${safe}" WHERE goal_id = '${sqlStr(goalId)}' ORDER BY version DESC, created_at DESC LIMIT 1`);
11091
+ if (rows.length === 0) {
11092
+ process.stderr.write(`goal not found: ${goalId}
11093
+ `);
11094
+ process.exit(1);
11095
+ }
11096
+ process.stdout.write(`${String(rows[0].content ?? "")}
11097
+ `);
11098
+ } catch (e) {
11099
+ process.stderr.write(`hivemind goal get: ${e.message}
11100
+ `);
11101
+ process.exit(1);
11102
+ }
11103
+ }
11074
11104
  async function goalDone(goalId) {
11075
11105
  await goalProgress(goalId, "closed");
11076
11106
  }
@@ -11192,8 +11222,10 @@ var USAGE_GOAL = `
11192
11222
  hivemind goal \u2014 manage team goals
11193
11223
 
11194
11224
  Usage:
11195
- hivemind goal add "<text>" create a goal (status=opened)
11225
+ hivemind goal add "<text>" [--agent manual|capture]
11226
+ create a goal (status=opened)
11196
11227
  hivemind goal list [--all|--mine] list goals (default: --mine)
11228
+ hivemind goal get <goal_id> print a goal's full body (resume context)
11197
11229
  hivemind goal done <goal_id> mark goal closed
11198
11230
  hivemind goal progress <goal_id> <opened|in_progress|closed>
11199
11231
  `.trim();
@@ -11204,12 +11236,13 @@ async function runGoalCommand(args) {
11204
11236
  return;
11205
11237
  }
11206
11238
  if (sub === "add") {
11207
- const text = args.slice(1).join(" ").trim();
11239
+ const { agent, rest } = parseAgentFlag(args.slice(1));
11240
+ const text = rest.join(" ").trim();
11208
11241
  if (!text) {
11209
11242
  process.stderr.write('usage: hivemind goal add "<text>"\n');
11210
11243
  process.exit(1);
11211
11244
  }
11212
- await goalAdd(text);
11245
+ await goalAdd(text, agent);
11213
11246
  return;
11214
11247
  }
11215
11248
  if (sub === "list") {
@@ -11217,6 +11250,15 @@ async function runGoalCommand(args) {
11217
11250
  await goalList(filter);
11218
11251
  return;
11219
11252
  }
11253
+ if (sub === "get") {
11254
+ const id = args[1];
11255
+ if (!id) {
11256
+ process.stderr.write("usage: hivemind goal get <goal_id>\n");
11257
+ process.exit(1);
11258
+ }
11259
+ await goalGet(id);
11260
+ return;
11261
+ }
11220
11262
  if (sub === "done") {
11221
11263
  const id = args[1];
11222
11264
  if (!id) {
@@ -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 {
@@ -1873,6 +1843,9 @@ Format: **entity** (type) \u2014 what was done with it, its current state>
1873
1843
  ## Open Questions / TODO
1874
1844
  <Anything unresolved, blocked, or explicitly deferred>
1875
1845
 
1846
+ ## Next Steps
1847
+ <The single concrete next action to resume with, as one imperative line (e.g. "Wire the resume-brief Next Steps fallback and run the tests"). If the session reached a clean stopping point with nothing pending, write exactly: none>
1848
+
1876
1849
  IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
1877
1850
  PRIVACY: Never include absolute filesystem paths in the summary.
1878
1851
  LENGTH LIMIT: Keep the total summary under 4000 characters.`;
@@ -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 {
@@ -484,9 +484,6 @@ function traceSql(msg) {
484
484
  log3(msg);
485
485
  }
486
486
  var _signalledBalanceExhausted = false;
487
- var _signalledLowBalance = false;
488
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
489
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
490
487
  function maybeSignalBalanceExhausted(status, bodyText) {
491
488
  if (status !== 402)
492
489
  return;
@@ -502,40 +499,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
502
499
  transient: true,
503
500
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
504
501
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
505
- dedupKey: { reason: "balance-zero" }
502
+ dedupKey: { reason: "balance-zero" },
503
+ // User-facing billing notice → user channel only. Never the model's
504
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
505
+ // is a prompt-injection pattern external agents flag.
506
+ userVisibleOnly: true
506
507
  }).catch((e) => {
507
508
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
508
509
  });
509
510
  }
510
- function signalLowBalanceFromHeader(resp) {
511
- if (_signalledLowBalance)
512
- return;
513
- const raw = resp.headers?.get?.(BALANCE_HEADER);
514
- if (!raw)
515
- return;
516
- if (!/^-?\d+$/.test(raw.trim()))
517
- return;
518
- const balance = Number(raw.trim());
519
- if (!Number.isFinite(balance))
520
- return;
521
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
522
- return;
523
- if (balance <= 0)
524
- return;
525
- _signalledLowBalance = true;
526
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
527
- enqueueNotification({
528
- id: "low-balance-warning",
529
- severity: "warn",
530
- transient: true,
531
- title: "Your org's Hivemind balance is running low",
532
- 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.`,
533
- dedupKey: { reason: "low-balance" }
534
- }).catch((e) => {
535
- _signalledLowBalance = false;
536
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
537
- });
538
- }
539
511
  function billingUrl() {
540
512
  try {
541
513
  const c = loadCredentials();
@@ -661,7 +633,6 @@ var DeeplakeApi = class {
661
633
  }
662
634
  throw lastError;
663
635
  }
664
- signalLowBalanceFromHeader(resp);
665
636
  if (resp.ok) {
666
637
  const raw = await resp.json();
667
638
  if (!raw?.rows || !raw?.columns)
@@ -822,7 +793,6 @@ var DeeplakeApi = class {
822
793
  ...deeplakeClientHeader()
823
794
  }
824
795
  });
825
- signalLowBalanceFromHeader(resp);
826
796
  if (resp.ok) {
827
797
  const data = await resp.json();
828
798
  return {
@@ -479,9 +479,6 @@ function traceSql(msg) {
479
479
  log3(msg);
480
480
  }
481
481
  var _signalledBalanceExhausted = false;
482
- var _signalledLowBalance = false;
483
- var LOW_BALANCE_THRESHOLD_CENTS = 200;
484
- var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
485
482
  function maybeSignalBalanceExhausted(status, bodyText) {
486
483
  if (status !== 402)
487
484
  return;
@@ -497,40 +494,15 @@ function maybeSignalBalanceExhausted(status, bodyText) {
497
494
  transient: true,
498
495
  title: "Hivemind credits exhausted \u2014 top up to keep capturing",
499
496
  body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
500
- dedupKey: { reason: "balance-zero" }
497
+ dedupKey: { reason: "balance-zero" },
498
+ // User-facing billing notice → user channel only. Never the model's
499
+ // additionalContext: a "top up at <url>" instruction in the agent prompt
500
+ // is a prompt-injection pattern external agents flag.
501
+ userVisibleOnly: true
501
502
  }).catch((e) => {
502
503
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
503
504
  });
504
505
  }
505
- function signalLowBalanceFromHeader(resp) {
506
- if (_signalledLowBalance)
507
- return;
508
- const raw = resp.headers?.get?.(BALANCE_HEADER);
509
- if (!raw)
510
- return;
511
- if (!/^-?\d+$/.test(raw.trim()))
512
- return;
513
- const balance = Number(raw.trim());
514
- if (!Number.isFinite(balance))
515
- return;
516
- if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
517
- return;
518
- if (balance <= 0)
519
- return;
520
- _signalledLowBalance = true;
521
- log3(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
522
- enqueueNotification({
523
- id: "low-balance-warning",
524
- severity: "warn",
525
- transient: true,
526
- title: "Your org's Hivemind balance is running low",
527
- 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.`,
528
- dedupKey: { reason: "low-balance" }
529
- }).catch((e) => {
530
- _signalledLowBalance = false;
531
- log3(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
532
- });
533
- }
534
506
  function billingUrl() {
535
507
  try {
536
508
  const c = loadCredentials();
@@ -656,7 +628,6 @@ var DeeplakeApi = class {
656
628
  }
657
629
  throw lastError;
658
630
  }
659
- signalLowBalanceFromHeader(resp);
660
631
  if (resp.ok) {
661
632
  const raw = await resp.json();
662
633
  if (!raw?.rows || !raw?.columns)
@@ -817,7 +788,6 @@ var DeeplakeApi = class {
817
788
  ...deeplakeClientHeader()
818
789
  }
819
790
  });
820
- signalLowBalanceFromHeader(resp);
821
791
  if (resp.ok) {
822
792
  const data = await resp.json();
823
793
  return {
@@ -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 {