@wrongstack/core 0.6.6 → 0.7.0

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 (52) hide show
  1. package/dist/{agent-bridge-BBXK_ppx.d.ts → agent-bridge-CrQpYjM7.d.ts} +1 -1
  2. package/dist/{compactor-C8NhpSt5.d.ts → compactor-CWV1u-IU.d.ts} +1 -1
  3. package/dist/{config-DfC6g6KV.d.ts → config-C34JRwl4.d.ts} +1 -1
  4. package/dist/{context-DN5v-uQX.d.ts → context-bmR0YgBm.d.ts} +74 -8
  5. package/dist/coordination/index.d.ts +11 -11
  6. package/dist/coordination/index.js +115 -39
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/default-config-DvRSTELf.d.ts +20 -0
  9. package/dist/defaults/index.d.ts +20 -19
  10. package/dist/defaults/index.js +224 -64
  11. package/dist/defaults/index.js.map +1 -1
  12. package/dist/{events-CJqwQl8G.d.ts → events-CEKFTmIY.d.ts} +10 -1
  13. package/dist/execution/index.d.ts +27 -13
  14. package/dist/execution/index.js +153 -40
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/extension/index.d.ts +6 -6
  17. package/dist/extension/index.js +3 -1
  18. package/dist/extension/index.js.map +1 -1
  19. package/dist/{index-DcnXDPdY.d.ts → index-BJIFLGII.d.ts} +20 -5
  20. package/dist/{index-CXnWsGBp.d.ts → index-CZR0HjxM.d.ts} +14 -110
  21. package/dist/index.d.ts +27 -26
  22. package/dist/index.js +396 -180
  23. package/dist/index.js.map +1 -1
  24. package/dist/infrastructure/index.d.ts +6 -6
  25. package/dist/kernel/index.d.ts +9 -9
  26. package/dist/kernel/index.js +8 -4
  27. package/dist/kernel/index.js.map +1 -1
  28. package/dist/{mcp-servers-CevFHHM1.d.ts → mcp-servers-BRJicm5o.d.ts} +3 -3
  29. package/dist/models/index.d.ts +2 -2
  30. package/dist/{multi-agent-D5IbASk_.d.ts → multi-agent-Cm1wYSrw.d.ts} +9 -4
  31. package/dist/{agent-subagent-runner-DsSm9lKN.d.ts → multi-agent-coordinator-CCupVFqv.d.ts} +117 -4
  32. package/dist/observability/index.d.ts +2 -2
  33. package/dist/{path-resolver-CBx_q1HA.d.ts → path-resolver-CfT7e_HT.d.ts} +2 -2
  34. package/dist/{plan-templates-BEOllUJV.d.ts → plan-templates-Q78an-GJ.d.ts} +4 -4
  35. package/dist/{provider-runner-Byh5TcJs.d.ts → provider-runner-WDj28o7J.d.ts} +3 -3
  36. package/dist/{retry-policy-BZSIMxrJ.d.ts → retry-policy-Dpxp4SET.d.ts} +1 -1
  37. package/dist/sdd/index.d.ts +3 -3
  38. package/dist/{secret-scrubber-CT7wefiO.d.ts → secret-scrubber-C2YCYtkn.d.ts} +1 -1
  39. package/dist/{secret-scrubber-I0QHY_ob.d.ts → secret-scrubber-CowtdEF8.d.ts} +1 -1
  40. package/dist/security/index.d.ts +3 -3
  41. package/dist/{selector-DDb_mq9X.d.ts → selector-CP39HhCe.d.ts} +1 -1
  42. package/dist/{session-reader-B9nVkziM.d.ts → session-reader-Dwjn4WZR.d.ts} +1 -1
  43. package/dist/storage/index.d.ts +5 -5
  44. package/dist/storage/index.js +94 -11
  45. package/dist/storage/index.js.map +1 -1
  46. package/dist/{system-prompt-gL06H9P4.d.ts → system-prompt-CfgXqyv2.d.ts} +1 -1
  47. package/dist/{tool-executor-BF7QfYVE.d.ts → tool-executor-D5NFi_LV.d.ts} +5 -5
  48. package/dist/types/index.d.ts +16 -15
  49. package/dist/types/index.js +102 -23
  50. package/dist/types/index.js.map +1 -1
  51. package/dist/utils/index.d.ts +1 -1
  52. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { U as Usage, a2 as Context, z as ToolProgressEvent, v as Tool } from './context-DN5v-uQX.js';
1
+ import { U as Usage, a5 as Context, D as ToolProgressEvent, x as Tool } from './context-bmR0YgBm.js';
2
2
 
3
3
  /**
4
4
  * EventBus — observe-only typed event bus.
@@ -341,6 +341,15 @@ interface EventMap {
341
341
  };
342
342
  };
343
343
  };
344
+ /**
345
+ * Fired by the delegate tool when a subagent finishes. The agent's run
346
+ * loop listens for this to collect `delegateSummaries` for the RunResult,
347
+ * so the CLI/TUI can render flashy completion banners.
348
+ */
349
+ 'subagent.done': {
350
+ summary: string;
351
+ ok: boolean;
352
+ };
344
353
  'mcp.server.connected': {
345
354
  name: string;
346
355
  toolCount: number;
@@ -1,21 +1,22 @@
1
- export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-BF7QfYVE.js';
2
- import { g as Provider, a2 as Context } from '../context-DN5v-uQX.js';
3
- import { a as Compactor, C as CompactReport } from '../compactor-C8NhpSt5.js';
4
- import { M as MessageSelector } from '../selector-DDb_mq9X.js';
5
- import { E as EventBus } from '../events-CJqwQl8G.js';
6
- import { c as MiddlewareHandler } from '../system-prompt-gL06H9P4.js';
7
- import { e as ContextWindowAggressiveOn, i as ContextWindowPolicy } from '../config-DfC6g6KV.js';
8
- import { A as Agent, R as RunResult, j as SystemPromptContributor } from '../index-DcnXDPdY.js';
9
- import { D as DoneCondition } from '../multi-agent-D5IbASk_.js';
1
+ export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-D5NFi_LV.js';
2
+ import { i as Provider, a5 as Context } from '../context-bmR0YgBm.js';
3
+ import { a as Compactor, C as CompactReport } from '../compactor-CWV1u-IU.js';
4
+ import { M as MessageSelector } from '../selector-CP39HhCe.js';
5
+ import { E as EventBus } from '../events-CEKFTmIY.js';
6
+ import { c as MiddlewareHandler } from '../system-prompt-CfgXqyv2.js';
7
+ import { e as ContextWindowAggressiveOn, i as ContextWindowPolicy } from '../config-C34JRwl4.js';
8
+ import { A as Agent, R as RunResult, j as SystemPromptContributor } from '../index-BJIFLGII.js';
9
+ import { D as DoneCondition } from '../multi-agent-Cm1wYSrw.js';
10
10
  import { J as JournalEntry } from '../goal-store-HHgaq5ue.js';
11
- import { A as AgentFactory } from '../agent-subagent-runner-DsSm9lKN.js';
11
+ import { A as AgentFactory, D as DefaultMultiAgentCoordinator } from '../multi-agent-coordinator-CCupVFqv.js';
12
12
  import { a as SkillLoader, b as SkillManifest, S as SkillEntry } from '../skill-CxuWrsKK.js';
13
13
  import { W as WstackPaths } from '../wstack-paths-86YPFktR.js';
14
- import '../retry-policy-BZSIMxrJ.js';
14
+ import '../retry-policy-Dpxp4SET.js';
15
15
  import '../models-registry-Y2xbog0E.js';
16
16
  import '../logger-BMQgxvdy.js';
17
17
  import '../observability-BhnVLBLS.js';
18
- import '../secret-scrubber-CT7wefiO.js';
18
+ import '../secret-scrubber-C2YCYtkn.js';
19
+ import 'node:events';
19
20
 
20
21
  interface SkillLoaderOptions {
21
22
  paths: WstackPaths;
@@ -301,7 +302,8 @@ interface EternalAutonomyOptions {
301
302
  * Maximum number of internal agent.run iterations the engine grants per
302
303
  * eternal-loop tick. The engine sets `autonomousContinue: true` so the
303
304
  * agent can run multi-step tasks end-to-end within one tick instead of
304
- * bouncing back to the engine after every single tool call. Default 50.
305
+ * bouncing back to the engine after every single tool call. Default 500.
306
+ * Previous 50 was far too low — agents hit the limit and restart constantly.
305
307
  */
306
308
  iterationMaxAgentSteps?: number;
307
309
  /**
@@ -387,6 +389,8 @@ interface EternalAutonomyOptions {
387
389
  transientBackoffBaseMs?: number;
388
390
  /** Ceiling for the exponential backoff. Default 60_000 (60 s). */
389
391
  transientBackoffMaxMs?: number;
392
+ /** Called when the eternal loop stops for any reason (manual stop, goal complete, etc.). */
393
+ onEternalStop?: () => void;
390
394
  }
391
395
  type EternalEngineState = 'idle' | 'running' | 'stopped';
392
396
  /**
@@ -511,6 +515,12 @@ declare class EternalAutonomyEngine {
511
515
  * goal is already `completed`.
512
516
  */
513
517
  private markGoalCompleted;
518
+ /**
519
+ * Manually clear the goal — equivalent to `/goal clear` typed by the user.
520
+ * Sets goalState to `abandoned`, removes the goal file, and fires
521
+ * `onEternalStop` so the REPL returns to normal mode.
522
+ */
523
+ private clearGoalManually;
514
524
  private appendFailure;
515
525
  private persistEngineState;
516
526
  }
@@ -565,6 +575,10 @@ declare class ParallelEternalEngine {
565
575
  private agentFactory;
566
576
  constructor(opts: ParallelEternalOptions);
567
577
  get currentState(): ParallelEngineState;
578
+ /**
579
+ * Get the underlying coordinator for stats/monitoring.
580
+ */
581
+ getCoordinator(): DefaultMultiAgentCoordinator | null;
568
582
  stop(): void;
569
583
  prime(): Promise<void>;
570
584
  run(): Promise<void>;
@@ -917,6 +917,22 @@ Summarize the following message range:`;
917
917
  };
918
918
 
919
919
  // src/types/errors.ts
920
+ var ERROR_CODES = {
921
+ // Provider
922
+ PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
923
+ PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
924
+ PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
925
+ PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
926
+ PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
927
+ PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR",
928
+ // Agent
929
+ AGENT_ITERATION_LIMIT: "AGENT_ITERATION_LIMIT",
930
+ AGENT_CONTEXT_OVERFLOW: "AGENT_CONTEXT_OVERFLOW",
931
+ AGENT_ABORTED: "AGENT_ABORTED",
932
+ AGENT_RUN_FAILED: "AGENT_RUN_FAILED",
933
+ // File system
934
+ FS_READ_FAILED: "FS_READ_FAILED",
935
+ FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED"};
920
936
  var WrongStackError = class extends Error {
921
937
  code;
922
938
  subsystem;
@@ -951,23 +967,39 @@ var AgentError = class extends WrongStackError {
951
967
  message: opts.message,
952
968
  code: opts.code,
953
969
  subsystem: "agent",
954
- severity: opts.code === "AGENT_ABORTED" ? "warning" : "error",
955
- recoverable: opts.recoverable ?? opts.code === "AGENT_ITERATION_LIMIT",
970
+ severity: opts.code === ERROR_CODES.AGENT_ABORTED ? "warning" : "error",
971
+ recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,
956
972
  context: opts.context,
957
973
  cause: opts.cause
958
974
  });
959
975
  this.name = "AgentError";
960
976
  }
961
977
  };
962
- function toWrongStackError(err, code = "AGENT_RUN_FAILED") {
978
+ function toWrongStackError(err, code = ERROR_CODES.AGENT_RUN_FAILED) {
963
979
  if (err instanceof WrongStackError) return err;
964
980
  const message = err instanceof Error ? err.message : String(err);
965
981
  return new AgentError({
966
982
  message,
967
- code: code === "UNKNOWN" ? "AGENT_RUN_FAILED" : code,
983
+ code: code === "UNKNOWN" ? ERROR_CODES.AGENT_RUN_FAILED : code,
968
984
  cause: err
969
985
  });
970
986
  }
987
+ var FsError = class extends WrongStackError {
988
+ path;
989
+ constructor(opts) {
990
+ super({
991
+ message: opts.message,
992
+ code: opts.code,
993
+ subsystem: "fs",
994
+ severity: "error",
995
+ recoverable: opts.code !== ERROR_CODES.FS_READ_FAILED,
996
+ context: { path: opts.path, ...opts.context },
997
+ cause: opts.cause
998
+ });
999
+ this.name = "FsError";
1000
+ this.path = opts.path;
1001
+ }
1002
+ };
971
1003
 
972
1004
  // src/execution/auto-compaction-middleware.ts
973
1005
  var AutoCompactionMiddleware = class {
@@ -1059,7 +1091,7 @@ var AutoCompactionMiddleware = class {
1059
1091
  if (fatal) {
1060
1092
  throw new AgentError({
1061
1093
  message: `Auto-compaction failed at ${pressure.level} threshold`,
1062
- code: "AGENT_CONTEXT_OVERFLOW",
1094
+ code: ERROR_CODES.AGENT_CONTEXT_OVERFLOW,
1063
1095
  recoverable: true,
1064
1096
  context: {
1065
1097
  level: pressure.level,
@@ -1688,7 +1720,16 @@ async function loadGoal(filePath) {
1688
1720
  }
1689
1721
  }
1690
1722
  async function saveGoal(filePath, goal) {
1691
- await atomicWrite(filePath, JSON.stringify(goal, null, 2), { mode: 384 });
1723
+ try {
1724
+ await atomicWrite(filePath, JSON.stringify(goal, null, 2), { mode: 384 });
1725
+ } catch (err) {
1726
+ throw new FsError({
1727
+ message: err instanceof Error ? err.message : String(err),
1728
+ code: ERROR_CODES.FS_ATOMIC_WRITE_FAILED,
1729
+ path: filePath,
1730
+ cause: err
1731
+ });
1732
+ }
1692
1733
  }
1693
1734
  function appendJournal(goal, entry) {
1694
1735
  const iteration = goal.iterations + 1;
@@ -1707,7 +1748,8 @@ function appendJournal(goal, entry) {
1707
1748
  // src/execution/eternal-autonomy.ts
1708
1749
  var execFileP = promisify(execFile);
1709
1750
  var BRAINSTORM_DONE = /* @__PURE__ */ Symbol("brainstorm-done");
1710
- var GOAL_COMPLETE_MARKER = /^\s*\[goal[_\s-]?complete\]\s*$/im;
1751
+ var GOAL_COMPLETE_MARKER = /^\s*\[goal[_\s-]*complete\]\s*$/im;
1752
+ var GOAL_CLEAR_MARKER = /^\s*\[\/?goal\s*clear\]\s*$/im;
1711
1753
  var EternalAutonomyEngine = class {
1712
1754
  constructor(opts) {
1713
1755
  this.opts = opts;
@@ -1845,7 +1887,7 @@ var EternalAutonomyEngine = class {
1845
1887
  // Cap the inner loop so a runaway agent.run can't burn through
1846
1888
  // the iteration timeout — the engine's own outer loop is the
1847
1889
  // long-running thing, each tick should be bounded.
1848
- maxIterations: this.opts.iterationMaxAgentSteps ?? 50
1890
+ maxIterations: this.opts.iterationMaxAgentSteps ?? 500
1849
1891
  }
1850
1892
  );
1851
1893
  if (result.status === "aborted") {
@@ -1933,7 +1975,12 @@ var EternalAutonomyEngine = class {
1933
1975
  emit({ phase: "sleep", ms: cycleGapMs });
1934
1976
  await sleep(cycleGapMs);
1935
1977
  if (GOAL_COMPLETE_MARKER.test(finalText)) {
1936
- await this.markGoalCompleted(action, finalText);
1978
+ await this.clearGoalManually(finalText);
1979
+ this.stopRequested = true;
1980
+ return true;
1981
+ }
1982
+ if (GOAL_CLEAR_MARKER.test(finalText)) {
1983
+ await this.clearGoalManually(finalText);
1937
1984
  this.stopRequested = true;
1938
1985
  return true;
1939
1986
  }
@@ -2233,6 +2280,30 @@ ${recentJournal}` : "No prior iterations.",
2233
2280
  });
2234
2281
  await saveGoal(this.goalPath, withEntry);
2235
2282
  }
2283
+ /**
2284
+ * Manually clear the goal — equivalent to `/goal clear` typed by the user.
2285
+ * Sets goalState to `abandoned`, removes the goal file, and fires
2286
+ * `onEternalStop` so the REPL returns to normal mode.
2287
+ */
2288
+ async clearGoalManually(note) {
2289
+ const current = await loadGoal(this.goalPath);
2290
+ if (current) {
2291
+ const abandoned = { ...current, goalState: "abandoned" };
2292
+ await saveGoal(this.goalPath, abandoned);
2293
+ }
2294
+ try {
2295
+ const { unlink: unlink2 } = await import('fs/promises');
2296
+ await unlink2(this.goalPath);
2297
+ } catch {
2298
+ }
2299
+ this.opts.onEternalStop?.();
2300
+ void this.appendIterationEntry({
2301
+ source: "manual",
2302
+ task: "goal cleared",
2303
+ status: "success",
2304
+ note: note.slice(0, 240)
2305
+ });
2306
+ }
2236
2307
  async appendFailure(task, note) {
2237
2308
  await this.appendIterationEntry({ source: "manual", task, status: "failure", note });
2238
2309
  }
@@ -2300,10 +2371,10 @@ var SubagentBudget = class _SubagentBudget {
2300
2371
  * or hung listener (Director not built / event filter detached mid-run)
2301
2372
  * leaves the budget over-limit and never enforces anything, since
2302
2373
  * `checkLimit` returns synchronously via `void this.checkLimitAsync`.
2303
- * Hardcoded for now most fleets set their own per-task timeout that
2304
- * dwarfs this anyway. 30 s matches the existing event-emit timeoutMs.
2374
+ * Raised from 30s to 60s to give subagents more headroom before
2375
+ * the threshold negotiation times out and triggers a hard stop.
2305
2376
  */
2306
- static DECISION_TIMEOUT_MS = 3e4;
2377
+ static DECISION_TIMEOUT_MS = 6e4;
2307
2378
  /**
2308
2379
  * Injected by the runner when wiring the budget to its EventBus.
2309
2380
  * Used by `checkLimitAsync` to emit `budget.threshold_reached` events.
@@ -2723,23 +2794,29 @@ function truncate(s, n) {
2723
2794
  return s.length <= n ? s : `${s.slice(0, n - 1)}\u2026`;
2724
2795
  }
2725
2796
  function providerStatusToCode(status, type) {
2726
- if (status === 0) return "PROVIDER_NETWORK_ERROR";
2727
- if (type === "rate_limit_error" || status === 429) return "PROVIDER_RATE_LIMITED";
2728
- if (type === "authentication_error" || status === 401) return "PROVIDER_AUTH_FAILED";
2729
- if (type === "overloaded_error" || status === 529) return "PROVIDER_OVERLOADED";
2730
- if (type === "invalid_request_error" || status === 400) return "PROVIDER_INVALID_REQUEST";
2731
- if (status === 408) return "PROVIDER_NETWORK_ERROR";
2732
- if (status >= 500) return "PROVIDER_SERVER_ERROR";
2733
- return "PROVIDER_INVALID_REQUEST";
2797
+ if (status === 0) return ERROR_CODES.PROVIDER_NETWORK_ERROR;
2798
+ if (type === "rate_limit_error" || status === 429) return ERROR_CODES.PROVIDER_RATE_LIMITED;
2799
+ if (type === "authentication_error" || status === 401) return ERROR_CODES.PROVIDER_AUTH_FAILED;
2800
+ if (type === "overloaded_error" || status === 529) return ERROR_CODES.PROVIDER_OVERLOADED;
2801
+ if (type === "invalid_request_error" || status === 400) return ERROR_CODES.PROVIDER_INVALID_REQUEST;
2802
+ if (status === 408) return ERROR_CODES.PROVIDER_NETWORK_ERROR;
2803
+ if (status >= 500) return ERROR_CODES.PROVIDER_SERVER_ERROR;
2804
+ return ERROR_CODES.PROVIDER_INVALID_REQUEST;
2734
2805
  }
2735
2806
  var FLEET_ROSTER_BUDGETS = {
2736
- "audit-log": { timeoutMs: 8 * 60 * 1e3, maxIterations: 150, maxToolCalls: 500 },
2737
- "bug-hunter": { timeoutMs: 15 * 60 * 1e3, maxIterations: 200, maxToolCalls: 600 },
2738
- "refactor-planner": { timeoutMs: 12 * 60 * 1e3, maxIterations: 180, maxToolCalls: 550 },
2739
- "security-scanner": { timeoutMs: 15 * 60 * 1e3, maxIterations: 200, maxToolCalls: 600 }
2807
+ "audit-log": { timeoutMs: 7.5 * 60 * 60 * 1e3, maxIterations: 5e3, maxToolCalls: 15e3 },
2808
+ "bug-hunter": { timeoutMs: 10 * 60 * 60 * 1e3, maxIterations: 8e3, maxToolCalls: 2e4 },
2809
+ "refactor-planner": { timeoutMs: 7.5 * 60 * 60 * 1e3, maxIterations: 6e3, maxToolCalls: 18e3 },
2810
+ "security-scanner": { timeoutMs: 10 * 60 * 60 * 1e3, maxIterations: 8e3, maxToolCalls: 2e4 }
2811
+ };
2812
+ var GENERIC_SUBAGENT_BUDGET = {
2813
+ timeoutMs: 3 * 60 * 60 * 1e3,
2814
+ maxIterations: 5e3,
2815
+ maxToolCalls: 15e3
2740
2816
  };
2741
2817
  function applyRosterBudget(cfg) {
2742
- const defaultBudget = FLEET_ROSTER_BUDGETS[cfg.role ?? ""];
2818
+ const roleBudget = cfg.role ? FLEET_ROSTER_BUDGETS[cfg.role] : void 0;
2819
+ const defaultBudget = roleBudget ?? (cfg.name ? GENERIC_SUBAGENT_BUDGET : void 0);
2743
2820
  if (!defaultBudget) return cfg;
2744
2821
  return {
2745
2822
  ...cfg,
@@ -2810,7 +2887,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
2810
2887
  // hasParentBridge() — the type now reflects this.
2811
2888
  parentBridge: null,
2812
2889
  doneCondition: this.config.doneCondition,
2813
- maxConcurrent: this.config.maxConcurrent ?? 4
2890
+ maxConcurrent: this.config.maxConcurrent ?? 16
2814
2891
  };
2815
2892
  this.subagents.set(id, {
2816
2893
  config: { ...subagent, id },
@@ -2856,6 +2933,30 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
2856
2933
  this.drainPendingAsAborted("Coordinator stopAll() drained the pending queue");
2857
2934
  await Promise.allSettled([...this.subagents.keys()].map((id) => this.stop(id)));
2858
2935
  }
2936
+ async remove(subagentId) {
2937
+ await this.stop(subagentId);
2938
+ this.subagents.delete(subagentId);
2939
+ }
2940
+ /**
2941
+ * Get current coordinator stats for monitoring/debugging.
2942
+ */
2943
+ getStats() {
2944
+ let running = 0, idle = 0, stopped = 0;
2945
+ for (const [, entry] of this.subagents) {
2946
+ if (entry.status === "running") running++;
2947
+ else if (entry.status === "idle") idle++;
2948
+ else stopped++;
2949
+ }
2950
+ return {
2951
+ total: this.subagents.size,
2952
+ running,
2953
+ idle,
2954
+ stopped,
2955
+ inFlight: this.inFlight,
2956
+ pending: this.pendingTasks.length,
2957
+ completed: this.completedResults.length
2958
+ };
2959
+ }
2859
2960
  getStatus() {
2860
2961
  return {
2861
2962
  coordinatorId: this.coordinatorId,
@@ -2937,7 +3038,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
2937
3038
  }
2938
3039
  }
2939
3040
  canDispatch() {
2940
- const max = this.config.maxConcurrent ?? 4;
3041
+ const max = this.config.maxConcurrent ?? 16;
2941
3042
  return this.inFlight < max && this.pendingTasks.length > 0;
2942
3043
  }
2943
3044
  takeNextDispatchableTask() {
@@ -3031,13 +3132,18 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
3031
3132
  task.subagentId = subagentId;
3032
3133
  subagent.context.tasks.push(task);
3033
3134
  this.emit("task.assigned", { task, subagentId });
3135
+ const rawMaxIterations = subagent.config.maxIterations;
3136
+ const rawMaxToolCalls = subagent.config.maxToolCalls;
3137
+ const rawMaxTokens = subagent.config.maxTokens;
3138
+ const rawMaxCostUsd = subagent.config.maxCostUsd;
3139
+ const rawTimeoutMs = subagent.config.timeoutMs;
3034
3140
  const configWithRosterDefaults = applyRosterBudget(subagent.config);
3035
3141
  const budget = new SubagentBudget({
3036
- maxIterations: configWithRosterDefaults.maxIterations ?? this.config.defaultBudget?.maxIterations,
3037
- maxToolCalls: task.maxToolCalls ?? configWithRosterDefaults.maxToolCalls ?? this.config.defaultBudget?.maxToolCalls,
3038
- maxTokens: configWithRosterDefaults.maxTokens ?? this.config.defaultBudget?.maxTokens,
3039
- maxCostUsd: configWithRosterDefaults.maxCostUsd ?? this.config.defaultBudget?.maxCostUsd,
3040
- timeoutMs: task.timeoutMs ?? configWithRosterDefaults.timeoutMs ?? this.config.defaultBudget?.timeoutMs
3142
+ maxIterations: rawMaxIterations ?? this.config.defaultBudget?.maxIterations ?? configWithRosterDefaults.maxIterations,
3143
+ maxToolCalls: rawMaxToolCalls ?? this.config.defaultBudget?.maxToolCalls ?? configWithRosterDefaults.maxToolCalls,
3144
+ maxTokens: rawMaxTokens ?? this.config.defaultBudget?.maxTokens ?? configWithRosterDefaults.maxTokens,
3145
+ maxCostUsd: rawMaxCostUsd ?? this.config.defaultBudget?.maxCostUsd ?? configWithRosterDefaults.maxCostUsd,
3146
+ timeoutMs: rawTimeoutMs ?? this.config.defaultBudget?.timeoutMs ?? configWithRosterDefaults.timeoutMs
3041
3147
  });
3042
3148
  subagent.activeBudget = budget;
3043
3149
  if (!this.runner) {
@@ -3108,7 +3214,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
3108
3214
  kind: "timeout",
3109
3215
  used: elapsed,
3110
3216
  limit,
3111
- timeoutMs: 3e4,
3217
+ timeoutMs: 6e4,
3112
3218
  extend: (extra) => resolveDecision({ extend: extra }),
3113
3219
  deny: () => resolveDecision("stop")
3114
3220
  });
@@ -3318,6 +3424,12 @@ var ParallelEternalEngine = class {
3318
3424
  get currentState() {
3319
3425
  return this.state;
3320
3426
  }
3427
+ /**
3428
+ * Get the underlying coordinator for stats/monitoring.
3429
+ */
3430
+ getCoordinator() {
3431
+ return this.coordinator;
3432
+ }
3321
3433
  stop() {
3322
3434
  this.stopRequested = true;
3323
3435
  void this.persistState("stopped").catch(() => {
@@ -3454,8 +3566,8 @@ Task: ${task}
3454
3566
  await coordinator.spawn({
3455
3567
  id: subagentId,
3456
3568
  name: `slot-${subagentId.slice(-6)}`,
3457
- maxIterations: 50,
3458
- maxToolCalls: 200,
3569
+ // Let the coordinator apply its default budget (from roster or generic).
3570
+ // Hardcoding low limits here defeats the x10 budget improvement.
3459
3571
  timeoutMs: this.timeoutMs
3460
3572
  });
3461
3573
  subagentIds.push(subagentId);
@@ -3472,7 +3584,7 @@ Task: ${task}
3472
3584
  let results = [];
3473
3585
  try {
3474
3586
  const ctrl = new AbortController();
3475
- const timer = setTimeout(() => ctrl.abort(), this.timeoutMs + 6e4);
3587
+ const timer = setTimeout(() => ctrl.abort(), Math.max(this.timeoutMs * 2, 72e5));
3476
3588
  try {
3477
3589
  results = await coordinator.awaitTasks(taskIds);
3478
3590
  } finally {
@@ -3746,16 +3858,18 @@ function buildGoalPreamble(goal) {
3746
3858
  ].join("\n");
3747
3859
  }
3748
3860
 
3861
+ // src/execution/regex-patterns.ts
3862
+ var NETWORK_ERR_RE = /ECONN|ETIMEDOUT|ETIME|ENOTFOUND|EAI_AGAIN|fetch failed/i;
3863
+
3749
3864
  // src/execution/retry-policy.ts
3750
- var DefaultRetryPolicy = class _DefaultRetryPolicy {
3751
- static NETWORK_ERR_RE = /ECONN|ETIMEDOUT|ETIME|ENOTFOUND|EAI_AGAIN|fetch failed/i;
3865
+ var DefaultRetryPolicy = class {
3752
3866
  shouldRetry(err, attempt) {
3753
3867
  if (err instanceof ProviderError) {
3754
3868
  if (!err.retryable) return false;
3755
3869
  return attempt < this.maxAttempts(err);
3756
3870
  }
3757
3871
  const msg = err.message ?? "";
3758
- const isNetwork = _DefaultRetryPolicy.NETWORK_ERR_RE.test(msg);
3872
+ const isNetwork = NETWORK_ERR_RE.test(msg);
3759
3873
  if (isNetwork) return attempt < 2;
3760
3874
  return false;
3761
3875
  }
@@ -3778,7 +3892,6 @@ var DefaultRetryPolicy = class _DefaultRetryPolicy {
3778
3892
 
3779
3893
  // src/execution/error-handler.ts
3780
3894
  var CONTEXT_OVERFLOW_RE = /context|too long|tokens/i;
3781
- var NETWORK_ERR_RE = /ECONN|ETIMEDOUT|ETIME|ENOTFOUND|EAI_AGAIN|fetch failed/i;
3782
3895
  function buildRecoveryStrategies(opts) {
3783
3896
  return [
3784
3897
  {