@deeplake/hivemind 0.7.60 → 0.7.62

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.
Files changed (34) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/bundle/cli.js +34 -0
  4. package/codex/bundle/capture.js +34 -0
  5. package/codex/bundle/commands/auth-login.js +34 -0
  6. package/codex/bundle/graph-pull-worker.js +34 -0
  7. package/codex/bundle/pre-tool-use.js +34 -0
  8. package/codex/bundle/session-start-setup.js +34 -0
  9. package/codex/bundle/session-start.js +34 -0
  10. package/codex/bundle/shell/deeplake-shell.js +34 -0
  11. package/codex/bundle/stop.js +34 -0
  12. package/cursor/bundle/capture.js +34 -0
  13. package/cursor/bundle/commands/auth-login.js +34 -0
  14. package/cursor/bundle/graph-pull-worker.js +34 -0
  15. package/cursor/bundle/pre-tool-use.js +34 -0
  16. package/cursor/bundle/session-start.js +34 -0
  17. package/cursor/bundle/shell/deeplake-shell.js +34 -0
  18. package/hermes/bundle/capture.js +34 -0
  19. package/hermes/bundle/commands/auth-login.js +34 -0
  20. package/hermes/bundle/graph-pull-worker.js +34 -0
  21. package/hermes/bundle/pre-tool-use.js +34 -0
  22. package/hermes/bundle/session-start.js +34 -0
  23. package/hermes/bundle/shell/deeplake-shell.js +34 -0
  24. package/mcp/bundle/server.js +34 -0
  25. package/openclaw/dist/index.js +29 -1
  26. package/openclaw/openclaw.plugin.json +1 -1
  27. package/openclaw/package.json +1 -1
  28. package/package.json +2 -1
  29. package/scripts/audit-openclaw-bundle.mjs +187 -0
  30. package/scripts/ensure-tree-sitter.mjs +91 -0
  31. package/scripts/pack-check.mjs +29 -0
  32. package/scripts/sync-versions.d.mts +15 -0
  33. package/scripts/sync-versions.mjs +103 -0
  34. package/scripts/verify-install.sh +218 -0
@@ -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.60"
9
+ "version": "0.7.62"
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.60",
15
+ "version": "0.7.62",
16
16
  "source": {
17
17
  "source": "git-subdir",
18
18
  "url": "https://github.com/activeloopai/hivemind.git",
19
19
  "path": "claude-code",
20
- "sha": "16a718fb94219d96ad5686ca414504d694643bc9"
20
+ "sha": "eaaf8f667132304bbdbbc796a531d243d06a67f2"
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.60",
4
+ "version": "0.7.62",
5
5
  "author": {
6
6
  "name": "Activeloop",
7
7
  "url": "https://deeplake.ai"
package/bundle/cli.js CHANGED
@@ -4816,6 +4816,9 @@ function traceSql(msg) {
4816
4816
  log4(msg);
4817
4817
  }
4818
4818
  var _signalledBalanceExhausted = false;
4819
+ var _signalledLowBalance = false;
4820
+ var LOW_BALANCE_THRESHOLD_CENTS = 200;
4821
+ var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
4819
4822
  function maybeSignalBalanceExhausted(status, bodyText) {
4820
4823
  if (status !== 402)
4821
4824
  return;
@@ -4836,6 +4839,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
4836
4839
  log4(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
4837
4840
  });
4838
4841
  }
4842
+ function signalLowBalanceFromHeader(resp) {
4843
+ if (_signalledLowBalance)
4844
+ return;
4845
+ const raw = resp.headers?.get?.(BALANCE_HEADER);
4846
+ if (!raw)
4847
+ return;
4848
+ if (!/^-?\d+$/.test(raw.trim()))
4849
+ return;
4850
+ const balance = Number(raw.trim());
4851
+ if (!Number.isFinite(balance))
4852
+ return;
4853
+ if (balance >= LOW_BALANCE_THRESHOLD_CENTS)
4854
+ return;
4855
+ if (balance <= 0)
4856
+ return;
4857
+ _signalledLowBalance = true;
4858
+ log4(`balance below threshold (${balance}\xA2) \u2014 enqueuing low-balance banner`);
4859
+ enqueueNotification({
4860
+ id: "low-balance-warning",
4861
+ severity: "warn",
4862
+ transient: true,
4863
+ title: "Your org's Hivemind balance is running low",
4864
+ 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.`,
4865
+ dedupKey: { reason: "low-balance" }
4866
+ }).catch((e) => {
4867
+ _signalledLowBalance = false;
4868
+ log4(`enqueue low-balance failed: ${e instanceof Error ? e.message : String(e)}`);
4869
+ });
4870
+ }
4839
4871
  function billingUrl() {
4840
4872
  try {
4841
4873
  const c = loadCredentials();
@@ -4961,6 +4993,7 @@ var DeeplakeApi = class {
4961
4993
  }
4962
4994
  throw lastError;
4963
4995
  }
4996
+ signalLowBalanceFromHeader(resp);
4964
4997
  if (resp.ok) {
4965
4998
  const raw = await resp.json();
4966
4999
  if (!raw?.rows || !raw?.columns)
@@ -5121,6 +5154,7 @@ var DeeplakeApi = class {
5121
5154
  ...deeplakeClientHeader()
5122
5155
  }
5123
5156
  });
5157
+ signalLowBalanceFromHeader(resp);
5124
5158
  if (resp.ok) {
5125
5159
  const data = await resp.json();
5126
5160
  return {
@@ -478,6 +478,9 @@ 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";
481
484
  function maybeSignalBalanceExhausted(status, bodyText) {
482
485
  if (status !== 402)
483
486
  return;
@@ -498,6 +501,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
498
501
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
499
502
  });
500
503
  }
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
+ }
501
533
  function billingUrl() {
502
534
  try {
503
535
  const c = loadCredentials();
@@ -623,6 +655,7 @@ var DeeplakeApi = class {
623
655
  }
624
656
  throw lastError;
625
657
  }
658
+ signalLowBalanceFromHeader(resp);
626
659
  if (resp.ok) {
627
660
  const raw = await resp.json();
628
661
  if (!raw?.rows || !raw?.columns)
@@ -783,6 +816,7 @@ var DeeplakeApi = class {
783
816
  ...deeplakeClientHeader()
784
817
  }
785
818
  });
819
+ signalLowBalanceFromHeader(resp);
786
820
  if (resp.ok) {
787
821
  const data = await resp.json();
788
822
  return {
@@ -741,6 +741,9 @@ 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";
744
747
  function maybeSignalBalanceExhausted(status, bodyText) {
745
748
  if (status !== 402)
746
749
  return;
@@ -761,6 +764,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
761
764
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
762
765
  });
763
766
  }
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
+ }
764
796
  function billingUrl() {
765
797
  try {
766
798
  const c = loadCredentials();
@@ -886,6 +918,7 @@ var DeeplakeApi = class {
886
918
  }
887
919
  throw lastError;
888
920
  }
921
+ signalLowBalanceFromHeader(resp);
889
922
  if (resp.ok) {
890
923
  const raw = await resp.json();
891
924
  if (!raw?.rows || !raw?.columns)
@@ -1046,6 +1079,7 @@ var DeeplakeApi = class {
1046
1079
  ...deeplakeClientHeader()
1047
1080
  }
1048
1081
  });
1082
+ signalLowBalanceFromHeader(resp);
1049
1083
  if (resp.ok) {
1050
1084
  const data = await resp.json();
1051
1085
  return {
@@ -468,6 +468,9 @@ 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";
471
474
  function maybeSignalBalanceExhausted(status, bodyText) {
472
475
  if (status !== 402)
473
476
  return;
@@ -488,6 +491,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
488
491
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
489
492
  });
490
493
  }
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
+ }
491
523
  function billingUrl() {
492
524
  try {
493
525
  const c = loadCredentials();
@@ -613,6 +645,7 @@ var DeeplakeApi = class {
613
645
  }
614
646
  throw lastError;
615
647
  }
648
+ signalLowBalanceFromHeader(resp);
616
649
  if (resp.ok) {
617
650
  const raw = await resp.json();
618
651
  if (!raw?.rows || !raw?.columns)
@@ -773,6 +806,7 @@ var DeeplakeApi = class {
773
806
  ...deeplakeClientHeader()
774
807
  }
775
808
  });
809
+ signalLowBalanceFromHeader(resp);
776
810
  if (resp.ok) {
777
811
  const data = await resp.json();
778
812
  return {
@@ -484,6 +484,9 @@ 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";
487
490
  function maybeSignalBalanceExhausted(status, bodyText) {
488
491
  if (status !== 402)
489
492
  return;
@@ -504,6 +507,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
504
507
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
505
508
  });
506
509
  }
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
+ }
507
539
  function billingUrl() {
508
540
  try {
509
541
  const c = loadCredentials();
@@ -629,6 +661,7 @@ var DeeplakeApi = class {
629
661
  }
630
662
  throw lastError;
631
663
  }
664
+ signalLowBalanceFromHeader(resp);
632
665
  if (resp.ok) {
633
666
  const raw = await resp.json();
634
667
  if (!raw?.rows || !raw?.columns)
@@ -789,6 +822,7 @@ var DeeplakeApi = class {
789
822
  ...deeplakeClientHeader()
790
823
  }
791
824
  });
825
+ signalLowBalanceFromHeader(resp);
792
826
  if (resp.ok) {
793
827
  const data = await resp.json();
794
828
  return {
@@ -479,6 +479,9 @@ 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";
482
485
  function maybeSignalBalanceExhausted(status, bodyText) {
483
486
  if (status !== 402)
484
487
  return;
@@ -499,6 +502,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
499
502
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
500
503
  });
501
504
  }
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
+ }
502
534
  function billingUrl() {
503
535
  try {
504
536
  const c = loadCredentials();
@@ -624,6 +656,7 @@ var DeeplakeApi = class {
624
656
  }
625
657
  throw lastError;
626
658
  }
659
+ signalLowBalanceFromHeader(resp);
627
660
  if (resp.ok) {
628
661
  const raw = await resp.json();
629
662
  if (!raw?.rows || !raw?.columns)
@@ -784,6 +817,7 @@ var DeeplakeApi = class {
784
817
  ...deeplakeClientHeader()
785
818
  }
786
819
  });
820
+ signalLowBalanceFromHeader(resp);
787
821
  if (resp.ok) {
788
822
  const data = await resp.json();
789
823
  return {
@@ -718,6 +718,9 @@ 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";
721
724
  function maybeSignalBalanceExhausted(status, bodyText) {
722
725
  if (status !== 402)
723
726
  return;
@@ -738,6 +741,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
738
741
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
739
742
  });
740
743
  }
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
+ }
741
773
  function billingUrl() {
742
774
  try {
743
775
  const c = loadCredentials();
@@ -863,6 +895,7 @@ var DeeplakeApi = class {
863
895
  }
864
896
  throw lastError;
865
897
  }
898
+ signalLowBalanceFromHeader(resp);
866
899
  if (resp.ok) {
867
900
  const raw = await resp.json();
868
901
  if (!raw?.rows || !raw?.columns)
@@ -1023,6 +1056,7 @@ var DeeplakeApi = class {
1023
1056
  ...deeplakeClientHeader()
1024
1057
  }
1025
1058
  });
1059
+ signalLowBalanceFromHeader(resp);
1026
1060
  if (resp.ok) {
1027
1061
  const data = await resp.json();
1028
1062
  return {
@@ -67172,6 +67172,9 @@ 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";
67175
67178
  function maybeSignalBalanceExhausted(status, bodyText) {
67176
67179
  if (status !== 402)
67177
67180
  return;
@@ -67192,6 +67195,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
67192
67195
  log3(`enqueue balance-exhausted failed: ${e6 instanceof Error ? e6.message : String(e6)}`);
67193
67196
  });
67194
67197
  }
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
+ }
67195
67227
  function billingUrl() {
67196
67228
  try {
67197
67229
  const c15 = loadCredentials();
@@ -67317,6 +67349,7 @@ var DeeplakeApi = class {
67317
67349
  }
67318
67350
  throw lastError;
67319
67351
  }
67352
+ signalLowBalanceFromHeader(resp);
67320
67353
  if (resp.ok) {
67321
67354
  const raw = await resp.json();
67322
67355
  if (!raw?.rows || !raw?.columns)
@@ -67477,6 +67510,7 @@ var DeeplakeApi = class {
67477
67510
  ...deeplakeClientHeader()
67478
67511
  }
67479
67512
  });
67513
+ signalLowBalanceFromHeader(resp);
67480
67514
  if (resp.ok) {
67481
67515
  const data = await resp.json();
67482
67516
  return {
@@ -483,6 +483,9 @@ 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";
486
489
  function maybeSignalBalanceExhausted(status, bodyText) {
487
490
  if (status !== 402)
488
491
  return;
@@ -503,6 +506,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
503
506
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
504
507
  });
505
508
  }
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
+ }
506
538
  function billingUrl() {
507
539
  try {
508
540
  const c = loadCredentials();
@@ -628,6 +660,7 @@ var DeeplakeApi = class {
628
660
  }
629
661
  throw lastError;
630
662
  }
663
+ signalLowBalanceFromHeader(resp);
631
664
  if (resp.ok) {
632
665
  const raw = await resp.json();
633
666
  if (!raw?.rows || !raw?.columns)
@@ -788,6 +821,7 @@ var DeeplakeApi = class {
788
821
  ...deeplakeClientHeader()
789
822
  }
790
823
  });
824
+ signalLowBalanceFromHeader(resp);
791
825
  if (resp.ok) {
792
826
  const data = await resp.json();
793
827
  return {
@@ -478,6 +478,9 @@ 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";
481
484
  function maybeSignalBalanceExhausted(status, bodyText) {
482
485
  if (status !== 402)
483
486
  return;
@@ -498,6 +501,35 @@ function maybeSignalBalanceExhausted(status, bodyText) {
498
501
  log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
499
502
  });
500
503
  }
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
+ }
501
533
  function billingUrl() {
502
534
  try {
503
535
  const c = loadCredentials();
@@ -623,6 +655,7 @@ var DeeplakeApi = class {
623
655
  }
624
656
  throw lastError;
625
657
  }
658
+ signalLowBalanceFromHeader(resp);
626
659
  if (resp.ok) {
627
660
  const raw = await resp.json();
628
661
  if (!raw?.rows || !raw?.columns)
@@ -783,6 +816,7 @@ var DeeplakeApi = class {
783
816
  ...deeplakeClientHeader()
784
817
  }
785
818
  });
819
+ signalLowBalanceFromHeader(resp);
786
820
  if (resp.ok) {
787
821
  const data = await resp.json();
788
822
  return {