@probelabs/visor 0.1.166 → 0.1.167

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 (72) hide show
  1. package/dist/config.d.ts.map +1 -1
  2. package/dist/frontends/github-frontend.d.ts.map +1 -1
  3. package/dist/index.js +344 -29
  4. package/dist/output/traces/{run-2026-03-06T13-08-34-152Z.ndjson → run-2026-03-06T13-29-14-416Z.ndjson} +84 -84
  5. package/dist/output/traces/{run-2026-03-06T13-09-10-593Z.ndjson → run-2026-03-06T13-29-52-749Z.ndjson} +1892 -1892
  6. package/dist/sdk/{check-provider-registry-V6C4LUYJ.mjs → check-provider-registry-6WR2SG66.mjs} +3 -3
  7. package/dist/sdk/{check-provider-registry-TGPICTHD.mjs → check-provider-registry-GPV5DYN5.mjs} +3 -3
  8. package/dist/sdk/{check-provider-registry-WXEBJWXY.mjs → check-provider-registry-P356JWTA.mjs} +6 -6
  9. package/dist/sdk/{chunk-WSYVK6ML.mjs → chunk-2G2PJKHM.mjs} +297 -31
  10. package/dist/sdk/chunk-2G2PJKHM.mjs.map +1 -0
  11. package/dist/sdk/{chunk-HFCOZPAS.mjs → chunk-HM3RZ3NP.mjs} +2 -2
  12. package/dist/sdk/{chunk-HFCOZPAS.mjs.map → chunk-HM3RZ3NP.mjs.map} +1 -1
  13. package/dist/sdk/{chunk-DEAPFYNX.mjs → chunk-KYBKVKBS.mjs} +7 -1
  14. package/dist/sdk/{chunk-DEAPFYNX.mjs.map → chunk-KYBKVKBS.mjs.map} +1 -1
  15. package/dist/sdk/{chunk-KKGMGB4X.mjs → chunk-MHLP6P4V.mjs} +297 -31
  16. package/dist/sdk/chunk-MHLP6P4V.mjs.map +1 -0
  17. package/dist/sdk/{chunk-OQ3CML4F.mjs → chunk-UNUZFJ5I.mjs} +3 -3
  18. package/dist/sdk/{chunk-KBTFMYZQ.mjs → chunk-XYQSWTGC.mjs} +2 -2
  19. package/dist/sdk/{chunk-ZQR4AGS3.mjs → chunk-YSQV7N5H.mjs} +304 -38
  20. package/dist/sdk/chunk-YSQV7N5H.mjs.map +1 -0
  21. package/dist/sdk/{config-D6WF2U4B.mjs → config-DP5QU3XC.mjs} +2 -2
  22. package/dist/sdk/{failure-condition-evaluator-5EAESM44.mjs → failure-condition-evaluator-VWQ54IK4.mjs} +3 -3
  23. package/dist/sdk/{github-frontend-BPRRUIGB.mjs → github-frontend-SOVBEAK4.mjs} +21 -3
  24. package/dist/sdk/{github-frontend-BPRRUIGB.mjs.map → github-frontend-SOVBEAK4.mjs.map} +1 -1
  25. package/dist/sdk/{github-frontend-P274ISBJ.mjs → github-frontend-VM52NX7N.mjs} +19 -1
  26. package/dist/sdk/{github-frontend-P274ISBJ.mjs.map → github-frontend-VM52NX7N.mjs.map} +1 -1
  27. package/dist/sdk/{host-753E6PKF.mjs → host-7MGCKSHM.mjs} +2 -2
  28. package/dist/sdk/{host-AIMRV5YL.mjs → host-JHMDZR6P.mjs} +2 -2
  29. package/dist/sdk/{routing-QHWSMAIH.mjs → routing-3WG46XWU.mjs} +4 -4
  30. package/dist/sdk/{schedule-tool-OCZGLKMJ.mjs → schedule-tool-B6SEZ77N.mjs} +3 -3
  31. package/dist/sdk/{schedule-tool-MQHISNJ6.mjs → schedule-tool-MPHHE2IM.mjs} +3 -3
  32. package/dist/sdk/{schedule-tool-ZVOSSFN2.mjs → schedule-tool-SPJWY2Y2.mjs} +6 -6
  33. package/dist/sdk/{schedule-tool-handler-BGOL2TOP.mjs → schedule-tool-handler-SUYGQJ63.mjs} +3 -3
  34. package/dist/sdk/{schedule-tool-handler-TZYXM664.mjs → schedule-tool-handler-V7A4AQGS.mjs} +3 -3
  35. package/dist/sdk/{schedule-tool-handler-4NCS4ARE.mjs → schedule-tool-handler-VNAVYBCM.mjs} +6 -6
  36. package/dist/sdk/sdk.js +312 -22
  37. package/dist/sdk/sdk.js.map +1 -1
  38. package/dist/sdk/sdk.mjs +5 -5
  39. package/dist/sdk/{trace-helpers-CTHTK6V5.mjs → trace-helpers-7BSOH35A.mjs} +2 -2
  40. package/dist/sdk/{workflow-check-provider-3M5LXLLX.mjs → workflow-check-provider-AECYZCBK.mjs} +3 -3
  41. package/dist/sdk/{workflow-check-provider-QKHL6AFT.mjs → workflow-check-provider-N4ZTFOH6.mjs} +3 -3
  42. package/dist/sdk/{workflow-check-provider-UTNO6XN6.mjs → workflow-check-provider-X7ZGHZA6.mjs} +6 -6
  43. package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
  44. package/dist/traces/{run-2026-03-06T13-08-34-152Z.ndjson → run-2026-03-06T13-29-14-416Z.ndjson} +84 -84
  45. package/dist/traces/{run-2026-03-06T13-09-10-593Z.ndjson → run-2026-03-06T13-29-52-749Z.ndjson} +1892 -1892
  46. package/dist/utils/fair-concurrency-limiter.d.ts +56 -0
  47. package/dist/utils/fair-concurrency-limiter.d.ts.map +1 -0
  48. package/dist/utils/interactive-prompt.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/dist/sdk/chunk-KKGMGB4X.mjs.map +0 -1
  51. package/dist/sdk/chunk-WSYVK6ML.mjs.map +0 -1
  52. package/dist/sdk/chunk-ZQR4AGS3.mjs.map +0 -1
  53. /package/dist/sdk/{check-provider-registry-TGPICTHD.mjs.map → check-provider-registry-6WR2SG66.mjs.map} +0 -0
  54. /package/dist/sdk/{check-provider-registry-V6C4LUYJ.mjs.map → check-provider-registry-GPV5DYN5.mjs.map} +0 -0
  55. /package/dist/sdk/{check-provider-registry-WXEBJWXY.mjs.map → check-provider-registry-P356JWTA.mjs.map} +0 -0
  56. /package/dist/sdk/{chunk-OQ3CML4F.mjs.map → chunk-UNUZFJ5I.mjs.map} +0 -0
  57. /package/dist/sdk/{chunk-KBTFMYZQ.mjs.map → chunk-XYQSWTGC.mjs.map} +0 -0
  58. /package/dist/sdk/{config-D6WF2U4B.mjs.map → config-DP5QU3XC.mjs.map} +0 -0
  59. /package/dist/sdk/{failure-condition-evaluator-5EAESM44.mjs.map → failure-condition-evaluator-VWQ54IK4.mjs.map} +0 -0
  60. /package/dist/sdk/{host-753E6PKF.mjs.map → host-7MGCKSHM.mjs.map} +0 -0
  61. /package/dist/sdk/{host-AIMRV5YL.mjs.map → host-JHMDZR6P.mjs.map} +0 -0
  62. /package/dist/sdk/{routing-QHWSMAIH.mjs.map → routing-3WG46XWU.mjs.map} +0 -0
  63. /package/dist/sdk/{schedule-tool-MQHISNJ6.mjs.map → schedule-tool-B6SEZ77N.mjs.map} +0 -0
  64. /package/dist/sdk/{schedule-tool-OCZGLKMJ.mjs.map → schedule-tool-MPHHE2IM.mjs.map} +0 -0
  65. /package/dist/sdk/{schedule-tool-ZVOSSFN2.mjs.map → schedule-tool-SPJWY2Y2.mjs.map} +0 -0
  66. /package/dist/sdk/{schedule-tool-handler-4NCS4ARE.mjs.map → schedule-tool-handler-SUYGQJ63.mjs.map} +0 -0
  67. /package/dist/sdk/{schedule-tool-handler-BGOL2TOP.mjs.map → schedule-tool-handler-V7A4AQGS.mjs.map} +0 -0
  68. /package/dist/sdk/{schedule-tool-handler-TZYXM664.mjs.map → schedule-tool-handler-VNAVYBCM.mjs.map} +0 -0
  69. /package/dist/sdk/{trace-helpers-CTHTK6V5.mjs.map → trace-helpers-7BSOH35A.mjs.map} +0 -0
  70. /package/dist/sdk/{workflow-check-provider-3M5LXLLX.mjs.map → workflow-check-provider-AECYZCBK.mjs.map} +0 -0
  71. /package/dist/sdk/{workflow-check-provider-QKHL6AFT.mjs.map → workflow-check-provider-N4ZTFOH6.mjs.map} +0 -0
  72. /package/dist/sdk/{workflow-check-provider-UTNO6XN6.mjs.map → workflow-check-provider-X7ZGHZA6.mjs.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CheckProviderRegistry,
3
3
  init_check_provider_registry
4
- } from "./chunk-KKGMGB4X.mjs";
4
+ } from "./chunk-2G2PJKHM.mjs";
5
5
  import "./chunk-KFKHU6CM.mjs";
6
6
  import "./chunk-AVMMKGLQ.mjs";
7
7
  import "./chunk-LG4AUKHB.mjs";
@@ -9,7 +9,7 @@ import "./chunk-B7BVQM5K.mjs";
9
9
  import "./chunk-XXAEN5KU.mjs";
10
10
  import "./chunk-GEW6LS32.mjs";
11
11
  import "./chunk-NZADFXHE.mjs";
12
- import "./chunk-DEAPFYNX.mjs";
12
+ import "./chunk-KYBKVKBS.mjs";
13
13
  import "./chunk-NCWIZVOT.mjs";
14
14
  import "./chunk-RV5SK4FZ.mjs";
15
15
  import "./chunk-E7NRUDWL.mjs";
@@ -26,4 +26,4 @@ init_check_provider_registry();
26
26
  export {
27
27
  CheckProviderRegistry
28
28
  };
29
- //# sourceMappingURL=check-provider-registry-V6C4LUYJ.mjs.map
29
+ //# sourceMappingURL=check-provider-registry-6WR2SG66.mjs.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CheckProviderRegistry,
3
3
  init_check_provider_registry
4
- } from "./chunk-WSYVK6ML.mjs";
4
+ } from "./chunk-MHLP6P4V.mjs";
5
5
  import "./chunk-KFKHU6CM.mjs";
6
6
  import "./chunk-AVMMKGLQ.mjs";
7
7
  import "./chunk-LG4AUKHB.mjs";
@@ -9,7 +9,7 @@ import "./chunk-B7BVQM5K.mjs";
9
9
  import "./chunk-XXAEN5KU.mjs";
10
10
  import "./chunk-GEW6LS32.mjs";
11
11
  import "./chunk-NZADFXHE.mjs";
12
- import "./chunk-DEAPFYNX.mjs";
12
+ import "./chunk-KYBKVKBS.mjs";
13
13
  import "./chunk-NCWIZVOT.mjs";
14
14
  import "./chunk-RV5SK4FZ.mjs";
15
15
  import "./chunk-E7NRUDWL.mjs";
@@ -26,4 +26,4 @@ init_check_provider_registry();
26
26
  export {
27
27
  CheckProviderRegistry
28
28
  };
29
- //# sourceMappingURL=check-provider-registry-TGPICTHD.mjs.map
29
+ //# sourceMappingURL=check-provider-registry-GPV5DYN5.mjs.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CheckProviderRegistry,
3
3
  init_check_provider_registry
4
- } from "./chunk-ZQR4AGS3.mjs";
4
+ } from "./chunk-YSQV7N5H.mjs";
5
5
  import "./chunk-KFKHU6CM.mjs";
6
6
  import "./chunk-AVMMKGLQ.mjs";
7
7
  import "./chunk-LG4AUKHB.mjs";
@@ -9,11 +9,11 @@ import "./chunk-B7BVQM5K.mjs";
9
9
  import "./chunk-XXAEN5KU.mjs";
10
10
  import "./chunk-GEW6LS32.mjs";
11
11
  import "./chunk-NZADFXHE.mjs";
12
- import "./chunk-DEAPFYNX.mjs";
12
+ import "./chunk-KYBKVKBS.mjs";
13
13
  import "./chunk-NCWIZVOT.mjs";
14
- import "./chunk-OQ3CML4F.mjs";
15
- import "./chunk-KBTFMYZQ.mjs";
16
- import "./chunk-HFCOZPAS.mjs";
14
+ import "./chunk-UNUZFJ5I.mjs";
15
+ import "./chunk-XYQSWTGC.mjs";
16
+ import "./chunk-HM3RZ3NP.mjs";
17
17
  import "./chunk-JL7JXCET.mjs";
18
18
  import "./chunk-ZUEQNCKB.mjs";
19
19
  import "./chunk-25IC7KXZ.mjs";
@@ -26,4 +26,4 @@ init_check_provider_registry();
26
26
  export {
27
27
  CheckProviderRegistry
28
28
  };
29
- //# sourceMappingURL=check-provider-registry-WXEBJWXY.mjs.map
29
+ //# sourceMappingURL=check-provider-registry-P356JWTA.mjs.map
@@ -33,7 +33,7 @@ import {
33
33
  import {
34
34
  config_exports,
35
35
  init_config
36
- } from "./chunk-DEAPFYNX.mjs";
36
+ } from "./chunk-KYBKVKBS.mjs";
37
37
  import {
38
38
  ExecutionJournal,
39
39
  checkLoopBudget,
@@ -3965,7 +3965,7 @@ async function executeWorkflowAsTool(workflowId, args, context2, argsOverrides)
3965
3965
  ...args,
3966
3966
  ...argsOverrides
3967
3967
  };
3968
- const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-QKHL6AFT.mjs");
3968
+ const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-N4ZTFOH6.mjs");
3969
3969
  const provider = new WorkflowCheckProvider2();
3970
3970
  const checkConfig = {
3971
3971
  type: "workflow",
@@ -8457,7 +8457,29 @@ async function executeCheckGroup(checks, context2, state, maxParallelism, emitEv
8457
8457
  } catch {
8458
8458
  }
8459
8459
  if (pool.length >= maxParallelism) {
8460
- await Promise.race(pool);
8460
+ const activeCount = pool.filter((p) => !p._settled).length;
8461
+ logger.info(
8462
+ `[LevelDispatch] Check pool full (${activeCount}/${maxParallelism} active). Check "${checkId}" queued, waiting for a slot...`
8463
+ );
8464
+ const queuedAt = Date.now();
8465
+ const reminder = setInterval(() => {
8466
+ const waited = Math.round((Date.now() - queuedAt) / 1e3);
8467
+ const stillActive = pool.filter((p) => !p._settled).length;
8468
+ logger.info(
8469
+ `[LevelDispatch] Check "${checkId}" still queued (${waited}s). ${stillActive}/${maxParallelism} slots busy.`
8470
+ );
8471
+ }, 15e3);
8472
+ try {
8473
+ await Promise.race(pool);
8474
+ } finally {
8475
+ clearInterval(reminder);
8476
+ }
8477
+ const waitedMs = Date.now() - queuedAt;
8478
+ if (waitedMs > 100) {
8479
+ logger.info(
8480
+ `[LevelDispatch] Check "${checkId}" dequeued after ${Math.round(waitedMs / 1e3)}s wait.`
8481
+ );
8482
+ }
8461
8483
  pool.splice(
8462
8484
  0,
8463
8485
  pool.length,
@@ -12746,6 +12768,223 @@ var init_workspace_manager = __esm({
12746
12768
  }
12747
12769
  });
12748
12770
 
12771
+ // src/utils/fair-concurrency-limiter.ts
12772
+ var FairConcurrencyLimiter;
12773
+ var init_fair_concurrency_limiter = __esm({
12774
+ "src/utils/fair-concurrency-limiter.ts"() {
12775
+ "use strict";
12776
+ init_logger();
12777
+ FairConcurrencyLimiter = class _FairConcurrencyLimiter {
12778
+ maxConcurrent;
12779
+ globalActive = 0;
12780
+ // Per-session FIFO queues
12781
+ sessionQueues = /* @__PURE__ */ new Map();
12782
+ // Round-robin order of sessions with waiting entries
12783
+ roundRobinSessions = [];
12784
+ roundRobinIndex = 0;
12785
+ // Per-session active count (for stats)
12786
+ sessionActive = /* @__PURE__ */ new Map();
12787
+ constructor(maxConcurrent) {
12788
+ this.maxConcurrent = maxConcurrent;
12789
+ }
12790
+ static getInstance(maxConcurrent) {
12791
+ const key = /* @__PURE__ */ Symbol.for("visor.fairConcurrencyLimiter");
12792
+ let instance = globalThis[key];
12793
+ if (!instance) {
12794
+ instance = new _FairConcurrencyLimiter(maxConcurrent);
12795
+ globalThis[key] = instance;
12796
+ logger.info(`[FairLimiter] Created global fair concurrency limiter (max: ${maxConcurrent})`);
12797
+ } else if (instance.maxConcurrent !== maxConcurrent) {
12798
+ const old = instance.maxConcurrent;
12799
+ instance.maxConcurrent = maxConcurrent;
12800
+ logger.info(`[FairLimiter] Updated max concurrency: ${old} -> ${maxConcurrent}`);
12801
+ instance._processQueue();
12802
+ }
12803
+ return instance;
12804
+ }
12805
+ /**
12806
+ * Try to acquire a slot immediately (non-blocking).
12807
+ */
12808
+ tryAcquire(sessionId) {
12809
+ if (this.globalActive >= this.maxConcurrent) {
12810
+ return false;
12811
+ }
12812
+ this.globalActive++;
12813
+ const sid = sessionId || "__anonymous__";
12814
+ this.sessionActive.set(sid, (this.sessionActive.get(sid) || 0) + 1);
12815
+ return true;
12816
+ }
12817
+ /**
12818
+ * Acquire a slot, waiting in a fair queue if necessary.
12819
+ * Sessions are served round-robin so no single session can starve others.
12820
+ */
12821
+ async acquire(sessionId, _debug, queueTimeout) {
12822
+ const sid = sessionId || "__anonymous__";
12823
+ if (this.tryAcquire(sid)) {
12824
+ return true;
12825
+ }
12826
+ const totalQueued = this._totalQueued();
12827
+ const sessionsWaiting = this.sessionQueues.size;
12828
+ const sessionQueueLen = this.sessionQueues.get(sid)?.length || 0;
12829
+ logger.info(
12830
+ `[FairLimiter] Slot unavailable (${this.globalActive}/${this.maxConcurrent} active). Session "${sid}" queued (${sessionQueueLen} own + ${totalQueued} total across ${sessionsWaiting} sessions). Waiting...`
12831
+ );
12832
+ const queuedAt = Date.now();
12833
+ const effectiveTimeout = queueTimeout ?? 12e4;
12834
+ return new Promise((resolve9, reject) => {
12835
+ const entry = { resolve: resolve9, reject, queuedAt };
12836
+ entry.reminder = setInterval(() => {
12837
+ const waited = Math.round((Date.now() - queuedAt) / 1e3);
12838
+ const curQueued = this._totalQueued();
12839
+ const curSessions = this._waitingSessions();
12840
+ logger.info(
12841
+ `[FairLimiter] Session "${sid}" still waiting (${waited}s). ${this.globalActive}/${this.maxConcurrent} active, ${curQueued} queued across ${curSessions} sessions.`
12842
+ );
12843
+ }, 15e3);
12844
+ let queue = this.sessionQueues.get(sid);
12845
+ if (!queue) {
12846
+ queue = [];
12847
+ this.sessionQueues.set(sid, queue);
12848
+ this.roundRobinSessions.push(sid);
12849
+ }
12850
+ queue.push(entry);
12851
+ if (effectiveTimeout > 0) {
12852
+ setTimeout(() => {
12853
+ const q = this.sessionQueues.get(sid);
12854
+ if (q) {
12855
+ const idx = q.indexOf(entry);
12856
+ if (idx !== -1) {
12857
+ q.splice(idx, 1);
12858
+ if (q.length === 0) {
12859
+ this.sessionQueues.delete(sid);
12860
+ this._removeFromRoundRobin(sid);
12861
+ }
12862
+ this._clearReminder(entry);
12863
+ reject(
12864
+ new Error(
12865
+ `[FairLimiter] Queue timeout: session "${sid}" waited ${effectiveTimeout}ms for a slot`
12866
+ )
12867
+ );
12868
+ }
12869
+ }
12870
+ }, effectiveTimeout);
12871
+ }
12872
+ });
12873
+ }
12874
+ /**
12875
+ * Release a slot and grant the next one fairly (round-robin across sessions).
12876
+ */
12877
+ release(sessionId, _debug) {
12878
+ const sid = sessionId || "__anonymous__";
12879
+ this.globalActive = Math.max(0, this.globalActive - 1);
12880
+ const active = this.sessionActive.get(sid);
12881
+ if (active !== void 0) {
12882
+ if (active <= 1) {
12883
+ this.sessionActive.delete(sid);
12884
+ } else {
12885
+ this.sessionActive.set(sid, active - 1);
12886
+ }
12887
+ }
12888
+ this._processQueue();
12889
+ }
12890
+ /**
12891
+ * Round-robin queue processing: cycle through sessions and grant one slot per session per round.
12892
+ */
12893
+ _processQueue() {
12894
+ const toGrant = [];
12895
+ while (this.globalActive < this.maxConcurrent && this.roundRobinSessions.length > 0) {
12896
+ if (this.roundRobinIndex >= this.roundRobinSessions.length) {
12897
+ this.roundRobinIndex = 0;
12898
+ }
12899
+ const sid = this.roundRobinSessions[this.roundRobinIndex];
12900
+ const queue = this.sessionQueues.get(sid);
12901
+ if (!queue || queue.length === 0) {
12902
+ this.sessionQueues.delete(sid);
12903
+ this.roundRobinSessions.splice(this.roundRobinIndex, 1);
12904
+ continue;
12905
+ }
12906
+ const entry = queue.shift();
12907
+ if (queue.length === 0) {
12908
+ this.sessionQueues.delete(sid);
12909
+ this.roundRobinSessions.splice(this.roundRobinIndex, 1);
12910
+ } else {
12911
+ this.roundRobinIndex++;
12912
+ }
12913
+ this.globalActive++;
12914
+ this.sessionActive.set(sid, (this.sessionActive.get(sid) || 0) + 1);
12915
+ toGrant.push({ entry, sid });
12916
+ }
12917
+ for (const { entry, sid } of toGrant) {
12918
+ this._clearReminder(entry);
12919
+ const waitedMs = Date.now() - entry.queuedAt;
12920
+ if (waitedMs > 100) {
12921
+ logger.info(
12922
+ `[FairLimiter] Session "${sid}" acquired slot after ${Math.round(waitedMs / 1e3)}s wait.`
12923
+ );
12924
+ }
12925
+ setImmediate(() => entry.resolve(true));
12926
+ }
12927
+ }
12928
+ getStats() {
12929
+ const perSession = {};
12930
+ const allSessions = /* @__PURE__ */ new Set([...this.sessionActive.keys(), ...this.sessionQueues.keys()]);
12931
+ for (const sid of allSessions) {
12932
+ perSession[sid] = {
12933
+ active: this.sessionActive.get(sid) || 0,
12934
+ queued: this.sessionQueues.get(sid)?.length || 0
12935
+ };
12936
+ }
12937
+ return {
12938
+ globalActive: this.globalActive,
12939
+ maxConcurrent: this.maxConcurrent,
12940
+ queueSize: this._totalQueued(),
12941
+ waitingSessions: this._waitingSessions(),
12942
+ perSession
12943
+ };
12944
+ }
12945
+ cleanup() {
12946
+ for (const queue of this.sessionQueues.values()) {
12947
+ for (const entry of queue) {
12948
+ this._clearReminder(entry);
12949
+ }
12950
+ }
12951
+ this.sessionQueues.clear();
12952
+ this.roundRobinSessions = [];
12953
+ this.roundRobinIndex = 0;
12954
+ const key = /* @__PURE__ */ Symbol.for("visor.fairConcurrencyLimiter");
12955
+ delete globalThis[key];
12956
+ }
12957
+ shutdown() {
12958
+ this.cleanup();
12959
+ }
12960
+ // -- helpers --
12961
+ _totalQueued() {
12962
+ let n = 0;
12963
+ for (const q of this.sessionQueues.values()) n += q.length;
12964
+ return n;
12965
+ }
12966
+ _waitingSessions() {
12967
+ return this.roundRobinSessions.length;
12968
+ }
12969
+ _removeFromRoundRobin(sid) {
12970
+ const idx = this.roundRobinSessions.indexOf(sid);
12971
+ if (idx !== -1) {
12972
+ this.roundRobinSessions.splice(idx, 1);
12973
+ if (this.roundRobinIndex > idx) {
12974
+ this.roundRobinIndex--;
12975
+ }
12976
+ }
12977
+ }
12978
+ _clearReminder(entry) {
12979
+ if (entry.reminder) {
12980
+ clearInterval(entry.reminder);
12981
+ entry.reminder = void 0;
12982
+ }
12983
+ }
12984
+ };
12985
+ }
12986
+ });
12987
+
12749
12988
  // src/state-machine/context/build-engine-context.ts
12750
12989
  var build_engine_context_exports = {};
12751
12990
  __export(build_engine_context_exports, {
@@ -12801,15 +13040,30 @@ function buildEngineContextForRun(workingDirectory, config, prInfo, debug, maxPa
12801
13040
  const journal = new ExecutionJournal();
12802
13041
  const memory = MemoryStore.getInstance(clonedConfig.memory);
12803
13042
  let sharedConcurrencyLimiter = void 0;
12804
- if (clonedConfig.max_ai_concurrency && _DelegationManager) {
12805
- sharedConcurrencyLimiter = new _DelegationManager({
12806
- maxConcurrent: clonedConfig.max_ai_concurrency,
12807
- maxPerSession: 999
12808
- // No per-session limit needed for global AI gating
12809
- });
12810
- logger.debug(
12811
- `[EngineContext] Created shared AI concurrency limiter (max: ${clonedConfig.max_ai_concurrency})`
12812
- );
13043
+ const sessionId = generateHumanId();
13044
+ if (clonedConfig.max_ai_concurrency) {
13045
+ const fairLimiter = FairConcurrencyLimiter.getInstance(clonedConfig.max_ai_concurrency);
13046
+ sharedConcurrencyLimiter = {
13047
+ async acquire(parentSessionId, _dbg, queueTimeout) {
13048
+ const sid = parentSessionId || sessionId;
13049
+ return fairLimiter.acquire(sid, _dbg, queueTimeout);
13050
+ },
13051
+ release(parentSessionId, _dbg) {
13052
+ const sid = parentSessionId || sessionId;
13053
+ return fairLimiter.release(sid, _dbg);
13054
+ },
13055
+ tryAcquire(parentSessionId) {
13056
+ const sid = parentSessionId || sessionId;
13057
+ return fairLimiter.tryAcquire(sid);
13058
+ },
13059
+ getStats() {
13060
+ return fairLimiter.getStats();
13061
+ },
13062
+ shutdown() {
13063
+ },
13064
+ cleanup() {
13065
+ }
13066
+ };
12813
13067
  }
12814
13068
  return {
12815
13069
  mode: "state-machine",
@@ -12819,7 +13073,7 @@ function buildEngineContextForRun(workingDirectory, config, prInfo, debug, maxPa
12819
13073
  memory,
12820
13074
  workingDirectory,
12821
13075
  originalWorkingDirectory: workingDirectory,
12822
- sessionId: generateHumanId(),
13076
+ sessionId,
12823
13077
  event: prInfo.eventType,
12824
13078
  debug,
12825
13079
  maxParallelism,
@@ -12873,7 +13127,6 @@ async function initializeWorkspace(context2) {
12873
13127
  return context2;
12874
13128
  }
12875
13129
  }
12876
- var _DelegationManager;
12877
13130
  var init_build_engine_context = __esm({
12878
13131
  "src/state-machine/context/build-engine-context.ts"() {
12879
13132
  "use strict";
@@ -12882,14 +13135,7 @@ var init_build_engine_context = __esm({
12882
13135
  init_human_id();
12883
13136
  init_logger();
12884
13137
  init_workspace_manager();
12885
- _DelegationManager = null;
12886
- try {
12887
- const probe = __require("@probelabs/probe");
12888
- if (probe && typeof probe.DelegationManager === "function") {
12889
- _DelegationManager = probe.DelegationManager;
12890
- }
12891
- } catch {
12892
- }
13138
+ init_fair_concurrency_limiter();
12893
13139
  }
12894
13140
  });
12895
13141
 
@@ -13033,7 +13279,7 @@ var init_state_machine_execution_engine = __esm({
13033
13279
  try {
13034
13280
  const map = options?.webhookContext?.webhookData;
13035
13281
  if (map) {
13036
- const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-TGPICTHD.mjs");
13282
+ const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-6WR2SG66.mjs");
13037
13283
  const reg = CheckProviderRegistry2.getInstance();
13038
13284
  const p = reg.getProvider("http_input");
13039
13285
  if (p && typeof p.setWebhookContext === "function") p.setWebhookContext(map);
@@ -13146,7 +13392,7 @@ var init_state_machine_execution_engine = __esm({
13146
13392
  logger.info("[StateMachine] Using state machine engine");
13147
13393
  }
13148
13394
  if (!config) {
13149
- const { ConfigManager } = await import("./config-D6WF2U4B.mjs");
13395
+ const { ConfigManager } = await import("./config-DP5QU3XC.mjs");
13150
13396
  const configManager = new ConfigManager();
13151
13397
  config = await configManager.getDefaultConfig();
13152
13398
  logger.debug("[StateMachine] Using default configuration (no config provided)");
@@ -13156,7 +13402,7 @@ var init_state_machine_execution_engine = __esm({
13156
13402
  tag_filter: tagFilter
13157
13403
  } : config;
13158
13404
  try {
13159
- const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-TGPICTHD.mjs");
13405
+ const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-6WR2SG66.mjs");
13160
13406
  const registry = CheckProviderRegistry2.getInstance();
13161
13407
  registry.setCustomTools(configWithTagFilter.tools || {});
13162
13408
  } catch (error) {
@@ -13220,7 +13466,7 @@ var init_state_machine_execution_engine = __esm({
13220
13466
  try {
13221
13467
  const webhookData = this.executionContext?.webhookContext?.webhookData;
13222
13468
  if (webhookData instanceof Map) {
13223
- const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-TZYXM664.mjs");
13469
+ const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-V7A4AQGS.mjs");
13224
13470
  const slackCtx = extractSlackContext2(webhookData);
13225
13471
  if (slackCtx) {
13226
13472
  const payload = Array.from(webhookData.values())[0];
@@ -13249,7 +13495,7 @@ var init_state_machine_execution_engine = __esm({
13249
13495
  if (Array.isArray(configWithTagFilter.frontends) && configWithTagFilter.frontends.length > 0) {
13250
13496
  try {
13251
13497
  const { EventBus } = await import("./event-bus-5K3Y2FCS.mjs");
13252
- const { FrontendsHost } = await import("./host-AIMRV5YL.mjs");
13498
+ const { FrontendsHost } = await import("./host-7MGCKSHM.mjs");
13253
13499
  const bus = new EventBus();
13254
13500
  context2.eventBus = bus;
13255
13501
  frontendsHost = new FrontendsHost(bus, logger);
@@ -39826,7 +40072,27 @@ async function acquirePromptLock() {
39826
40072
  activePrompt = true;
39827
40073
  return;
39828
40074
  }
39829
- await new Promise((resolve9) => waiters.push(resolve9));
40075
+ console.error(
40076
+ `[human-input] Prompt queued, waiting for active prompt to finish (${waiters.length} already waiting).`
40077
+ );
40078
+ const queuedAt = Date.now();
40079
+ const reminder = setInterval(() => {
40080
+ const waited = Math.round((Date.now() - queuedAt) / 1e3);
40081
+ console.error(
40082
+ `[human-input] Still waiting for prompt lock (${waited}s, ${waiters.length} in queue).`
40083
+ );
40084
+ }, 1e4);
40085
+ try {
40086
+ await new Promise((resolve9) => waiters.push(resolve9));
40087
+ } finally {
40088
+ clearInterval(reminder);
40089
+ const waitedMs = Date.now() - queuedAt;
40090
+ if (waitedMs > 100) {
40091
+ console.error(
40092
+ `[human-input] Prompt lock acquired after ${Math.round(waitedMs / 1e3)}s wait.`
40093
+ );
40094
+ }
40095
+ }
39830
40096
  activePrompt = true;
39831
40097
  }
39832
40098
  function releasePromptLock() {
@@ -40908,8 +41174,8 @@ function buildBuiltinGlobals(opts) {
40908
41174
  const asyncFunctionNames = /* @__PURE__ */ new Set();
40909
41175
  const scheduleFn = async (args = {}) => {
40910
41176
  try {
40911
- const { handleScheduleAction: handleScheduleAction2, buildScheduleToolContext: buildScheduleToolContext2 } = await import("./schedule-tool-MQHISNJ6.mjs");
40912
- const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-TZYXM664.mjs");
41177
+ const { handleScheduleAction: handleScheduleAction2, buildScheduleToolContext: buildScheduleToolContext2 } = await import("./schedule-tool-MPHHE2IM.mjs");
41178
+ const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-V7A4AQGS.mjs");
40913
41179
  const parentCtx = opts.sessionInfo?._parentContext;
40914
41180
  const webhookData = parentCtx?.prInfo?.eventContext?.webhookData;
40915
41181
  const visorCfg = parentCtx?.config;
@@ -44054,4 +44320,4 @@ undici/lib/fetch/body.js:
44054
44320
  undici/lib/websocket/frame.js:
44055
44321
  (*! ws. MIT License. Einar Otto Stangvik <einaros@gmail.com> *)
44056
44322
  */
44057
- //# sourceMappingURL=chunk-WSYVK6ML.mjs.map
44323
+ //# sourceMappingURL=chunk-2G2PJKHM.mjs.map