@wrongstack/core 0.5.6 → 0.6.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 (59) hide show
  1. package/dist/{agent-bridge-B07AYFBk.d.ts → agent-bridge-BKNiE1VH.d.ts} +1 -1
  2. package/dist/{compactor-BWhJXxsW.d.ts → compactor-RIPuTtWK.d.ts} +1 -1
  3. package/dist/{config-BgM0BIpz.d.ts → config-BGGuP_Ar.d.ts} +1 -1
  4. package/dist/{context-CLZXPPYk.d.ts → context-CDRyrkKQ.d.ts} +7 -0
  5. package/dist/coordination/index.d.ts +9 -9
  6. package/dist/coordination/index.js +339 -80
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +20 -19
  9. package/dist/defaults/index.js +731 -180
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{events-qnDZbrtb.d.ts → events-DPQKFX7W.d.ts} +1 -1
  12. package/dist/execution/index.d.ts +152 -12
  13. package/dist/execution/index.js +474 -5
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/extension/index.d.ts +6 -6
  16. package/dist/extension/index.js +2 -1
  17. package/dist/extension/index.js.map +1 -1
  18. package/dist/goal-store-BQ3YX1h1.d.ts +75 -0
  19. package/dist/{index-DPLJw_ZI.d.ts → index-B0qTujQW.d.ts} +52 -5
  20. package/dist/{index-BDnUCRvL.d.ts → index-DkdRz6yK.d.ts} +351 -15
  21. package/dist/index.d.ts +109 -28
  22. package/dist/index.js +1143 -234
  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/{mcp-servers-CSMfaBuL.d.ts → mcp-servers-DBdh3cee.d.ts} +3 -3
  27. package/dist/models/index.d.ts +2 -2
  28. package/dist/models/index.js +2 -3
  29. package/dist/models/index.js.map +1 -1
  30. package/dist/{multi-agent-Cv8wk47i.d.ts → multi-agent-Cpp7FXUl.d.ts} +11 -3
  31. package/dist/observability/index.d.ts +2 -2
  32. package/dist/{path-resolver-DiCUvEg6.d.ts → path-resolver--g_hKJ7V.d.ts} +2 -2
  33. package/dist/{plan-templates-DaxTCPfk.d.ts → plan-templates-CKJs_sYh.d.ts} +9 -8
  34. package/dist/{provider-runner-3SHqk9zB.d.ts → provider-runner-hl4Il3xS.d.ts} +3 -3
  35. package/dist/{retry-policy-LLUxJmYY.d.ts → retry-policy-LKS8MHsB.d.ts} +1 -1
  36. package/dist/sdd/index.d.ts +6 -4
  37. package/dist/sdd/index.js +102 -68
  38. package/dist/sdd/index.js.map +1 -1
  39. package/dist/{secret-scrubber-Z_VXuXQT.d.ts → secret-scrubber-BzQR5BiL.d.ts} +1 -1
  40. package/dist/{secret-scrubber-BhJTNr9v.d.ts → secret-scrubber-CfMdAJ_l.d.ts} +1 -1
  41. package/dist/security/index.d.ts +3 -3
  42. package/dist/security/index.js +82 -82
  43. package/dist/security/index.js.map +1 -1
  44. package/dist/{selector-DB2-byKH.d.ts → selector-C7HqnZJU.d.ts} +1 -1
  45. package/dist/{session-reader-4jxsYLZ8.d.ts → session-reader-CzfRA6Vk.d.ts} +1 -1
  46. package/dist/skills/index.js +102 -38
  47. package/dist/skills/index.js.map +1 -1
  48. package/dist/storage/index.d.ts +6 -5
  49. package/dist/storage/index.js +131 -22
  50. package/dist/storage/index.js.map +1 -1
  51. package/dist/{system-prompt-DI4Dtc1I.d.ts → system-prompt-Dl2QY1_B.d.ts} +1 -1
  52. package/dist/{tool-executor-DSvmOBe6.d.ts → tool-executor-B03CRwu-.d.ts} +4 -4
  53. package/dist/types/index.d.ts +15 -15
  54. package/dist/types/index.js +100 -102
  55. package/dist/types/index.js.map +1 -1
  56. package/dist/utils/index.d.ts +1 -1
  57. package/dist/utils/index.js +5 -0
  58. package/dist/utils/index.js.map +1 -1
  59. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { B as BridgeTransport, l as BridgeMessage, A as AgentBridge, m as AgentBridgeConfig } from './multi-agent-Cv8wk47i.js';
1
+ import { B as BridgeTransport, l as BridgeMessage, A as AgentBridge, m as AgentBridgeConfig } from './multi-agent-Cpp7FXUl.js';
2
2
 
3
3
  /**
4
4
  * In-memory pub/sub transport for agent-to-agent messaging.
@@ -1,4 +1,4 @@
1
- import { a2 as Context } from './context-CLZXPPYk.js';
1
+ import { a2 as Context } from './context-CDRyrkKQ.js';
2
2
 
3
3
  interface CompactRepairReport {
4
4
  removedToolUses: string[];
@@ -1,5 +1,5 @@
1
1
  import { W as WireFamily } from './models-registry-Y2xbog0E.js';
2
- import { P as Permission } from './context-CLZXPPYk.js';
2
+ import { P as Permission } from './context-CDRyrkKQ.js';
3
3
 
4
4
  type ContextWindowModeId = 'balanced' | 'frugal' | 'deep' | 'archival';
5
5
  type ContextWindowAggressiveOn = 'hard' | 'soft' | 'warn';
@@ -887,6 +887,13 @@ interface RunOptions {
887
887
  model?: string;
888
888
  executionStrategy?: 'parallel' | 'sequential' | 'smart';
889
889
  maxIterations?: number;
890
+ /**
891
+ * Enable autonomous continue for this specific run. When true, the agent
892
+ * loop re-runs on `[continue]`/`[next step]`/`[proceed]` markers or
893
+ * `continue_to_next_iteration()` tool calls instead of returning.
894
+ * Overrides `AgentInit.autonomousContinue` for this call only.
895
+ */
896
+ autonomousContinue?: boolean;
890
897
  }
891
898
  interface ContextInit {
892
899
  systemPrompt: TextBlock[];
@@ -1,14 +1,14 @@
1
- export { A as ALL_FLEET_AGENTS, a as AUDIT_LOG_AGENT, b as AgentFactory, c as AgentFactoryResult, d as AgentRunnerOptions, B as BUG_HUNTER_AGENT, C as CreateDelegateToolOptions, D as DEFAULT_DIRECTOR_PREAMBLE, e as DEFAULT_SUBAGENT_BASELINE, f as DefaultMultiAgentCoordinator, g as DelegateHost, h as Director, i as DirectorBudgetError, G as DirectorCostCapError, j as DirectorPromptParts, k as DirectorSessionFactory, l as DirectorSessionFactoryOptions, F as FLEET_ROSTER, n as FleetBus, o as FleetEvent, p as FleetHandler, q as FleetUsage, r as FleetUsageAggregator, M as MultiAgentCoordinatorOptions, R as REFACTOR_PLANNER_AGENT, S as SECURITY_SCANNER_AGENT, s as SubagentPromptParts, t as SubagentUsageSnapshot, v as composeDirectorPrompt, w as composeSubagentPrompt, x as createDelegateTool, y as makeAgentSubagentRunner, z as makeDirectorSessionFactory, E as rosterSummaryFromConfigs } from '../index-BDnUCRvL.js';
2
- export { n as BudgetExceededError, o as BudgetKind, p as BudgetLimits, s as BudgetThresholdDecision, t as BudgetThresholdHandler, u as BudgetThresholdSignal, q as BudgetUsage, r as SubagentBudget } from '../multi-agent-Cv8wk47i.js';
3
- export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-B07AYFBk.js';
1
+ export { A as ALL_FLEET_AGENTS, a as AUDIT_LOG_AGENT, b as AgentFactory, c as AgentFactoryResult, d as AgentRunnerOptions, B as BUG_HUNTER_AGENT, C as CreateDelegateToolOptions, D as DEFAULT_DIRECTOR_PREAMBLE, e as DEFAULT_SUBAGENT_BASELINE, f as DefaultMultiAgentCoordinator, g as DelegateHost, h as Director, i as DirectorPromptParts, j as DirectorSessionFactory, k as DirectorSessionFactoryOptions, F as FLEET_ROSTER, m as FleetBus, K as FleetCostCapError, n as FleetEvent, o as FleetHandler, p as FleetManager, q as FleetManagerOptions, r as FleetSpawnBudgetError, s as FleetUsage, t as FleetUsageAggregator, I as ICoordinator, u as IFleetManager, M as MultiAgentCoordinatorOptions, N as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, S as SECURITY_SCANNER_AGENT, v as SubagentPromptParts, w as SubagentUsageSnapshot, y as composeDirectorPrompt, z as composeSubagentPrompt, E as createDelegateTool, G as makeAgentSubagentRunner, H as makeDirectorSessionFactory, J as rosterSummaryFromConfigs } from '../index-DkdRz6yK.js';
2
+ export { n as BudgetExceededError, o as BudgetKind, p as BudgetLimits, s as BudgetThresholdDecision, t as BudgetThresholdHandler, u as BudgetThresholdSignal, q as BudgetUsage, r as SubagentBudget } from '../multi-agent-Cpp7FXUl.js';
3
+ export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-BKNiE1VH.js';
4
4
  import '../director-state-BmYi3DGA.js';
5
- import '../context-CLZXPPYk.js';
6
- import '../events-qnDZbrtb.js';
5
+ import '../context-CDRyrkKQ.js';
6
+ import '../events-DPQKFX7W.js';
7
7
  import 'node:events';
8
- import '../index-DPLJw_ZI.js';
8
+ import '../index-B0qTujQW.js';
9
9
  import '../logger-BMQgxvdy.js';
10
- import '../system-prompt-DI4Dtc1I.js';
10
+ import '../system-prompt-Dl2QY1_B.js';
11
11
  import '../observability-BhnVLBLS.js';
12
- import '../secret-scrubber-BhJTNr9v.js';
13
- import '../config-BgM0BIpz.js';
12
+ import '../secret-scrubber-CfMdAJ_l.js';
13
+ import '../config-BGGuP_Ar.js';
14
14
  import '../models-registry-Y2xbog0E.js';
@@ -73,8 +73,6 @@ async function renameWithRetry(from, to) {
73
73
  }
74
74
  throw lastErr;
75
75
  }
76
-
77
- // src/storage/director-state.ts
78
76
  async function acquireDirectorStateLock(lockPath, processId = process.pid) {
79
77
  let existing;
80
78
  try {
@@ -1631,10 +1629,10 @@ function makeSpawnTool(director, roster) {
1631
1629
  const subagentId = await director.spawn(cfg);
1632
1630
  return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
1633
1631
  } catch (err) {
1634
- if (err instanceof DirectorBudgetError) {
1632
+ if (err instanceof FleetSpawnBudgetError) {
1635
1633
  return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
1636
1634
  }
1637
- if (err instanceof DirectorCostCapError) {
1635
+ if (err instanceof FleetCostCapError) {
1638
1636
  return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
1639
1637
  }
1640
1638
  return { error: err instanceof Error ? err.message : String(err) };
@@ -1835,7 +1833,7 @@ function makeFleetHealthTool(director) {
1835
1833
  }
1836
1834
 
1837
1835
  // src/coordination/director.ts
1838
- var DirectorBudgetError = class extends Error {
1836
+ var FleetSpawnBudgetError = class extends Error {
1839
1837
  kind;
1840
1838
  limit;
1841
1839
  observed;
@@ -1843,13 +1841,13 @@ var DirectorBudgetError = class extends Error {
1843
1841
  super(
1844
1842
  kind === "max_spawns" ? `Director spawn budget exceeded: tried to spawn #${observed} but maxSpawns is ${limit}` : `Director spawn depth budget exceeded: this director is at depth ${observed} and maxSpawnDepth is ${limit}`
1845
1843
  );
1846
- this.name = "DirectorBudgetError";
1844
+ this.name = "FleetSpawnBudgetError";
1847
1845
  this.kind = kind;
1848
1846
  this.limit = limit;
1849
1847
  this.observed = observed;
1850
1848
  }
1851
1849
  };
1852
- var DirectorCostCapError = class extends Error {
1850
+ var FleetCostCapError = class extends Error {
1853
1851
  kind;
1854
1852
  limit;
1855
1853
  observed;
@@ -1857,16 +1855,34 @@ var DirectorCostCapError = class extends Error {
1857
1855
  super(
1858
1856
  `Director cost cap exceeded: total fleet spend ${observed.toFixed(4)} exceeds maxCostUsd ${limit.toFixed(4)}`
1859
1857
  );
1860
- this.name = "DirectorCostCapError";
1858
+ this.name = "FleetCostCapError";
1861
1859
  this.kind = "max_cost_usd";
1862
1860
  this.limit = limit;
1863
1861
  this.observed = observed;
1864
1862
  }
1865
1863
  };
1866
1864
  var Director = class {
1865
+ /** Alias for the ICoordinator contract. `id` is retained for backward compatibility. */
1866
+ get coordinatorId() {
1867
+ return this.id;
1868
+ }
1867
1869
  id;
1870
+ /**
1871
+ * The fleet event bus. Backed by `fleetManager?.fleet` when a FleetManager
1872
+ * is injected; otherwise own FleetBus instance (preserves existing behavior).
1873
+ */
1868
1874
  fleet;
1875
+ /**
1876
+ * Usage rollup. Backed by `fleetManager?.usage` when a FleetManager is
1877
+ * injected; otherwise own FleetUsageAggregator.
1878
+ */
1869
1879
  usage;
1880
+ /**
1881
+ * Optional fleet-level policy container. When provided the Director
1882
+ * delegates spawn budgeting, manifest entries, and checkpointing to it
1883
+ * instead of managing those internally. All other behavior is unchanged.
1884
+ */
1885
+ fleetManager;
1870
1886
  /**
1871
1887
  * Director-side bridge endpoint. Subagents are wired to the same
1872
1888
  * in-memory transport so the director can `ask()` them synchronously
@@ -1917,8 +1933,8 @@ var Director = class {
1917
1933
  /** Debounce timer for periodic manifest writes. */
1918
1934
  manifestTimer = null;
1919
1935
  manifestDebounceMs;
1920
- /** Fleet-wide cost cap. Infinity means no cap. */
1921
- maxCostUsd;
1936
+ /** Fleet-wide cost cap (entire fleet total, distinct from SubagentBudget limits). Infinity means no cap. */
1937
+ maxFleetCostUsd;
1922
1938
  /** Max auto-extensions per subagent per budget kind before denying. */
1923
1939
  maxBudgetExtensions;
1924
1940
  /** Sessions root for direct subagent JSONL reads (fleet_session tool). */
@@ -1951,7 +1967,7 @@ var Director = class {
1951
1967
  this.spawnDepth = opts.spawnDepth ?? 0;
1952
1968
  this.sessionWriter = opts.sessionWriter ?? null;
1953
1969
  this.manifestDebounceMs = opts.manifestDebounceMs ?? 2e3;
1954
- this.maxCostUsd = opts.directorBudget?.maxCostUsd ?? Number.POSITIVE_INFINITY;
1970
+ this.maxFleetCostUsd = opts.directorBudget?.maxCostUsd ?? Number.POSITIVE_INFINITY;
1955
1971
  this.maxBudgetExtensions = opts.maxBudgetExtensions ?? 2;
1956
1972
  this.sessionsRoot = opts.sessionsRoot;
1957
1973
  this.directorRunId = opts.directorRunId ?? this.id;
@@ -1962,20 +1978,28 @@ var Director = class {
1962
1978
  maxSpawnDepth: this.maxSpawnDepth,
1963
1979
  directorBudget: opts.directorBudget
1964
1980
  }, opts.checkpointDebounceMs ?? 250) : null;
1981
+ this.fleetManager = opts.fleetManager;
1965
1982
  if (this.sharedScratchpadPath) {
1966
- void fsp4.mkdir(this.sharedScratchpadPath, { recursive: true }).catch(() => void 0);
1983
+ void fsp4.mkdir(this.sharedScratchpadPath, { recursive: true }).catch(
1984
+ (err) => this.logShutdownError("shared_scratchpad_mkdir", err)
1985
+ );
1967
1986
  }
1968
1987
  this.transport = new InMemoryBridgeTransport();
1969
1988
  this.bridge = new InMemoryAgentBridge(
1970
1989
  { agentId: this.id, coordinatorId: this.id },
1971
1990
  this.transport
1972
1991
  );
1973
- this.fleet = new FleetBus();
1974
- this.usage = new FleetUsageAggregator(
1975
- this.fleet,
1976
- (id) => this.priceLookups.get(id),
1977
- (id) => this.subagentMeta.get(id)
1978
- );
1992
+ if (this.fleetManager) {
1993
+ this.fleet = this.fleetManager.fleet;
1994
+ this.usage = this.fleetManager.usage;
1995
+ } else {
1996
+ this.fleet = new FleetBus();
1997
+ this.usage = new FleetUsageAggregator(
1998
+ this.fleet,
1999
+ (id) => this.priceLookups.get(id),
2000
+ (id) => this.subagentMeta.get(id)
2001
+ );
2002
+ }
1979
2003
  this.coordinator = new DefaultMultiAgentCoordinator(
1980
2004
  { ...opts.config, coordinatorId: this.id },
1981
2005
  { runner: opts.runner }
@@ -2064,7 +2088,9 @@ var Director = class {
2064
2088
  if (this.manifestTimer) return;
2065
2089
  this.manifestTimer = setTimeout(() => {
2066
2090
  this.manifestTimer = null;
2067
- void this.writeManifest().catch(() => void 0);
2091
+ void this.writeManifest().catch(
2092
+ (err) => this.logShutdownError("manifest_write_debounced", err)
2093
+ );
2068
2094
  }, this.manifestDebounceMs);
2069
2095
  }
2070
2096
  /**
@@ -2077,58 +2103,73 @@ var Director = class {
2077
2103
  * it the `cost` column in `usage.snapshot()` stays at 0.
2078
2104
  */
2079
2105
  async spawn(config, priceLookup) {
2080
- if (this.spawnDepth >= this.maxSpawnDepth) {
2081
- throw new DirectorBudgetError("max_spawn_depth", this.maxSpawnDepth, this.spawnDepth);
2082
- }
2083
- if (this.spawnCount >= this.maxSpawns) {
2084
- throw new DirectorBudgetError("max_spawns", this.maxSpawns, this.spawnCount + 1);
2085
- }
2086
- if (this.maxCostUsd < Number.POSITIVE_INFINITY) {
2087
- const totalCost = this.usage.snapshot().total?.cost ?? 0;
2088
- if (totalCost >= this.maxCostUsd) {
2089
- throw new DirectorCostCapError(this.maxCostUsd, totalCost);
2106
+ if (this.fleetManager) {
2107
+ const rejection = this.fleetManager.canSpawn(config);
2108
+ if (rejection) {
2109
+ if (rejection.kind === "max_spawn_depth") throw new FleetSpawnBudgetError("max_spawn_depth", rejection.limit, rejection.observed);
2110
+ if (rejection.kind === "max_spawns") throw new FleetSpawnBudgetError("max_spawns", rejection.limit, rejection.observed);
2111
+ if (rejection.kind === "max_cost_usd") throw new FleetCostCapError(rejection.limit, rejection.observed);
2112
+ }
2113
+ } else {
2114
+ if (this.spawnDepth >= this.maxSpawnDepth) {
2115
+ throw new FleetSpawnBudgetError("max_spawn_depth", this.maxSpawnDepth, this.spawnDepth);
2116
+ }
2117
+ if (this.spawnCount >= this.maxSpawns) {
2118
+ throw new FleetSpawnBudgetError("max_spawns", this.maxSpawns, this.spawnCount + 1);
2119
+ }
2120
+ if (this.maxFleetCostUsd < Number.POSITIVE_INFINITY) {
2121
+ const totalCost = this.usage.snapshot().total?.cost ?? 0;
2122
+ if (totalCost >= this.maxFleetCostUsd) {
2123
+ throw new FleetCostCapError(this.maxFleetCostUsd, totalCost);
2124
+ }
2090
2125
  }
2091
2126
  }
2092
2127
  const result = await this.coordinator.spawn(config);
2093
- this.spawnCount += 1;
2094
- this.subagentMeta.set(result.subagentId, {
2095
- provider: config.provider,
2096
- model: config.model
2097
- });
2098
- if (priceLookup) this.priceLookups.set(result.subagentId, priceLookup);
2128
+ if (this.fleetManager) {
2129
+ this.fleetManager.recordSpawn(result.subagentId, config, priceLookup);
2130
+ } else {
2131
+ this.spawnCount += 1;
2132
+ this.subagentMeta.set(result.subagentId, {
2133
+ provider: config.provider,
2134
+ model: config.model
2135
+ });
2136
+ if (priceLookup) this.priceLookups.set(result.subagentId, priceLookup);
2137
+ }
2099
2138
  const subagentBridge = new InMemoryAgentBridge(
2100
2139
  { agentId: result.subagentId, coordinatorId: this.id },
2101
2140
  this.transport
2102
2141
  );
2103
2142
  this.coordinator.setSubagentBridge(result.subagentId, subagentBridge);
2104
2143
  this.subagentBridges.set(result.subagentId, subagentBridge);
2105
- this.manifestEntries.set(result.subagentId, {
2106
- subagentId: result.subagentId,
2107
- name: config.name,
2108
- role: config.role,
2109
- provider: config.provider,
2110
- model: config.model,
2111
- taskIds: []
2112
- });
2113
- const spawnedAt = (/* @__PURE__ */ new Date()).toISOString();
2114
- this.stateCheckpoint?.recordSpawn(
2115
- {
2116
- id: result.subagentId,
2144
+ if (!this.fleetManager) {
2145
+ this.manifestEntries.set(result.subagentId, {
2146
+ subagentId: result.subagentId,
2117
2147
  name: config.name,
2118
2148
  role: config.role,
2119
2149
  provider: config.provider,
2120
2150
  model: config.model,
2121
- spawnedAt
2122
- },
2123
- this.spawnCount
2124
- );
2125
- void this.appendSessionEvent({
2126
- type: "agent_spawned",
2127
- ts: spawnedAt,
2128
- agentId: result.subagentId,
2129
- role: config.role ?? config.name
2130
- });
2131
- this.scheduleManifest();
2151
+ taskIds: []
2152
+ });
2153
+ const spawnedAt = (/* @__PURE__ */ new Date()).toISOString();
2154
+ this.stateCheckpoint?.recordSpawn(
2155
+ {
2156
+ id: result.subagentId,
2157
+ name: config.name,
2158
+ role: config.role,
2159
+ provider: config.provider,
2160
+ model: config.model,
2161
+ spawnedAt
2162
+ },
2163
+ this.spawnCount
2164
+ );
2165
+ void this.appendSessionEvent({
2166
+ type: "agent_spawned",
2167
+ ts: spawnedAt,
2168
+ agentId: result.subagentId,
2169
+ role: config.role ?? config.name
2170
+ });
2171
+ this.scheduleManifest();
2172
+ }
2132
2173
  return result.subagentId;
2133
2174
  }
2134
2175
  /**
@@ -2240,7 +2281,7 @@ var Director = class {
2240
2281
  usage: this.usage.snapshot()
2241
2282
  };
2242
2283
  await fsp4.mkdir(path4.dirname(this.manifestPath), { recursive: true });
2243
- await fsp4.writeFile(this.manifestPath, JSON.stringify(manifest, null, 2), { mode: 384 });
2284
+ await atomicWrite(this.manifestPath, JSON.stringify(manifest, null, 2), { mode: 384 });
2244
2285
  return this.manifestPath;
2245
2286
  }
2246
2287
  /**
@@ -2295,8 +2336,12 @@ var Director = class {
2295
2336
  async assign(task) {
2296
2337
  const taskWithId = task.id ? task : { ...task, id: randomUUID() };
2297
2338
  if (task.subagentId) {
2298
- const entry = this.manifestEntries.get(task.subagentId);
2299
- if (entry) entry.taskIds.push(taskWithId.id);
2339
+ if (this.fleetManager) {
2340
+ this.fleetManager.addTaskToSubagent(task.subagentId, taskWithId.id);
2341
+ } else {
2342
+ const entry = this.manifestEntries.get(task.subagentId);
2343
+ if (entry) entry.taskIds.push(taskWithId.id);
2344
+ }
2300
2345
  }
2301
2346
  await this.coordinator.assign(taskWithId);
2302
2347
  this.taskDescriptions.set(taskWithId.id, taskWithId.description);
@@ -2494,8 +2539,9 @@ var Director = class {
2494
2539
  * still permission-checked normally.
2495
2540
  */
2496
2541
  tools(roster) {
2542
+ const effectiveRoster = roster ?? this.roster;
2497
2543
  const t = [
2498
- makeSpawnTool(this, roster),
2544
+ makeSpawnTool(this, effectiveRoster),
2499
2545
  makeAssignTool(this),
2500
2546
  makeAwaitTasksTool(this),
2501
2547
  makeAskTool(this),
@@ -2764,9 +2810,11 @@ async function readSubagentPartial(opts, subagentId) {
2764
2810
  candidates.push(path4.join(opts.sessionsRoot, opts.directorRunId, `${subagentId}.jsonl`));
2765
2811
  } else {
2766
2812
  try {
2767
- const runDirs = await fsp4.readdir(opts.sessionsRoot);
2768
- for (const r of runDirs) {
2769
- candidates.push(path4.join(opts.sessionsRoot, r, `${subagentId}.jsonl`));
2813
+ const entries = await fsp4.readdir(opts.sessionsRoot, { withFileTypes: true });
2814
+ for (const entry of entries) {
2815
+ if (entry.isDirectory()) {
2816
+ candidates.push(path4.join(opts.sessionsRoot, entry.name, `${subagentId}.jsonl`));
2817
+ }
2770
2818
  }
2771
2819
  } catch {
2772
2820
  return void 0;
@@ -3072,19 +3120,25 @@ var DefaultSessionStore = class {
3072
3120
  { cause: err }
3073
3121
  );
3074
3122
  }
3075
- const writer = new FileSessionWriter(
3076
- id,
3077
- handle,
3078
- (/* @__PURE__ */ new Date()).toISOString(),
3079
- {
3123
+ try {
3124
+ const writer = new FileSessionWriter(
3080
3125
  id,
3081
- model: data.metadata.model,
3082
- provider: data.metadata.provider
3083
- },
3084
- this.events,
3085
- { resumed: true, dir: this.dir, filePath: file }
3086
- );
3087
- return { writer, data };
3126
+ handle,
3127
+ (/* @__PURE__ */ new Date()).toISOString(),
3128
+ {
3129
+ id,
3130
+ model: data.metadata.model,
3131
+ provider: data.metadata.provider
3132
+ },
3133
+ this.events,
3134
+ { resumed: true, dir: this.dir, filePath: file }
3135
+ );
3136
+ return { writer, data };
3137
+ } catch (err) {
3138
+ await handle.close().catch(() => {
3139
+ });
3140
+ throw err;
3141
+ }
3088
3142
  }
3089
3143
  async load(id) {
3090
3144
  const file = path4.join(this.dir, `${id}.jsonl`);
@@ -3130,7 +3184,7 @@ var DefaultSessionStore = class {
3130
3184
  const full = path4.join(this.dir, `${id}.jsonl`);
3131
3185
  const stat3 = await fsp4.stat(full);
3132
3186
  const summary = await this.summarize(id, stat3.mtime.toISOString());
3133
- await fsp4.writeFile(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
3187
+ await atomicWrite(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
3134
3188
  console.warn(
3135
3189
  `[session-store] Failed to write manifest for "${id}":`,
3136
3190
  err instanceof Error ? err.message : String(err)
@@ -3358,7 +3412,7 @@ var FileSessionWriter = class {
3358
3412
  this.closed = true;
3359
3413
  if (this.manifestFile) {
3360
3414
  try {
3361
- await fsp4.writeFile(this.manifestFile, JSON.stringify(this.summary), { mode: 384 });
3415
+ await atomicWrite(this.manifestFile, JSON.stringify(this.summary), { mode: 384 });
3362
3416
  } catch {
3363
3417
  }
3364
3418
  }
@@ -3483,6 +3537,211 @@ function makeDirectorSessionFactory(opts) {
3483
3537
  };
3484
3538
  }
3485
3539
 
3486
- export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, BUG_HUNTER_AGENT, BudgetExceededError, BudgetThresholdSignal, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, Director, DirectorBudgetError, DirectorCostCapError, FLEET_ROSTER, FleetBus, FleetUsageAggregator, InMemoryAgentBridge, InMemoryBridgeTransport, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, SubagentBudget, composeDirectorPrompt, composeSubagentPrompt, createDelegateTool, createMessage, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs };
3540
+ // src/coordination/null-fleet-bus.ts
3541
+ var NULL_FLEET_BUS = new FleetBus();
3542
+ var FleetManager = class {
3543
+ /** The fleet-wide event bus. */
3544
+ fleet;
3545
+ /** Usage rollup across all subagents. */
3546
+ usage;
3547
+ manifestPath;
3548
+ sessionsRoot;
3549
+ directorRunId;
3550
+ /** Spawn cap (lifetime total). Infinity means unlimited. */
3551
+ maxSpawns;
3552
+ /** Nesting cap. */
3553
+ maxSpawnDepth;
3554
+ /** This director's depth in a director chain. Root = 0. */
3555
+ spawnDepth;
3556
+ /** Live spawn counter. */
3557
+ spawnCount = 0;
3558
+ stateCheckpoint;
3559
+ sessionWriter;
3560
+ manifestTimer = null;
3561
+ manifestDebounceMs;
3562
+ /** Fleet-wide cost cap. Infinity = no cap. Distinct from SubagentBudget limits,
3563
+ * which track per-subagent spend — this field caps the entire fleet total. */
3564
+ maxFleetCostUsd;
3565
+ manifestEntries = /* @__PURE__ */ new Map();
3566
+ /** Pending tasks with their descriptions — populated by `addPendingTask`
3567
+ * and cleared by `removePendingTask`. Replaces the host-side `pending`
3568
+ * Map so task descriptions live in one place (FleetManager). */
3569
+ pendingTasks = /* @__PURE__ */ new Map();
3570
+ subagentMeta = /* @__PURE__ */ new Map();
3571
+ priceLookups = /* @__PURE__ */ new Map();
3572
+ constructor(opts = {}) {
3573
+ this.manifestPath = opts.manifestPath;
3574
+ this.sessionsRoot = opts.sessionsRoot;
3575
+ this.directorRunId = opts.directorRunId ?? randomUUID();
3576
+ this.maxSpawns = opts.maxSpawns ?? Number.POSITIVE_INFINITY;
3577
+ this.maxSpawnDepth = opts.maxSpawnDepth ?? 2;
3578
+ this.spawnDepth = opts.spawnDepth ?? 0;
3579
+ this.sessionWriter = opts.sessionWriter ?? null;
3580
+ this.manifestDebounceMs = opts.manifestDebounceMs ?? 2e3;
3581
+ this.maxFleetCostUsd = opts.directorBudget?.maxCostUsd ?? Number.POSITIVE_INFINITY;
3582
+ this.stateCheckpoint = opts.stateCheckpointPath ? new DirectorStateCheckpoint(
3583
+ opts.stateCheckpointPath,
3584
+ {
3585
+ directorRunId: this.directorRunId,
3586
+ maxSpawns: opts.maxSpawns,
3587
+ spawnDepth: this.spawnDepth,
3588
+ maxSpawnDepth: this.maxSpawnDepth,
3589
+ directorBudget: opts.directorBudget
3590
+ },
3591
+ opts.checkpointDebounceMs ?? 250
3592
+ ) : null;
3593
+ this.fleet = new FleetBus();
3594
+ this.usage = new FleetUsageAggregator(
3595
+ this.fleet,
3596
+ (id) => this.priceLookups.get(id),
3597
+ (id) => this.subagentMeta.get(id)
3598
+ );
3599
+ }
3600
+ // -----------------------------------------------------------------------
3601
+ // IFleetManager surface
3602
+ // -----------------------------------------------------------------------
3603
+ get fleetBus() {
3604
+ return this.fleet;
3605
+ }
3606
+ snapshot() {
3607
+ return this.usage.snapshot();
3608
+ }
3609
+ getSubagentMeta(id) {
3610
+ return this.subagentMeta.get(id);
3611
+ }
3612
+ /**
3613
+ * Returns null if the spawn is allowed, or an object describing
3614
+ * which cap was exceeded. Does NOT throw — the caller decides
3615
+ * how to surface the rejection.
3616
+ */
3617
+ canSpawn(config) {
3618
+ if (this.spawnDepth >= this.maxSpawnDepth) {
3619
+ return { kind: "max_spawn_depth", limit: this.maxSpawnDepth, observed: this.spawnDepth };
3620
+ }
3621
+ if (this.spawnCount >= this.maxSpawns) {
3622
+ return { kind: "max_spawns", limit: this.maxSpawns, observed: this.spawnCount + 1 };
3623
+ }
3624
+ if (this.maxFleetCostUsd < Number.POSITIVE_INFINITY) {
3625
+ const totalCost = this.usage.snapshot().total?.cost ?? 0;
3626
+ if (totalCost >= this.maxFleetCostUsd) {
3627
+ return { kind: "max_cost_usd", limit: this.maxFleetCostUsd, observed: totalCost };
3628
+ }
3629
+ }
3630
+ return null;
3631
+ }
3632
+ /**
3633
+ * Records a spawn: increments counter, stores metadata, updates state checkpoint,
3634
+ * and schedules a debounced manifest write. Call AFTER the coordinator
3635
+ * has successfully spawned the subagent.
3636
+ *
3637
+ * @param subagentId The subagent's id (from coordinator.spawn result)
3638
+ * @param config The SubagentConfig that was used
3639
+ * @param priceLookup Optional per-subagent pricing data
3640
+ */
3641
+ recordSpawn(subagentId, config, priceLookup) {
3642
+ this.spawnCount += 1;
3643
+ this.subagentMeta.set(subagentId, {
3644
+ provider: config.provider,
3645
+ model: config.model
3646
+ });
3647
+ if (priceLookup) this.priceLookups.set(subagentId, priceLookup);
3648
+ this.manifestEntries.set(subagentId, {
3649
+ subagentId,
3650
+ name: config.name,
3651
+ role: config.role,
3652
+ provider: config.provider,
3653
+ model: config.model,
3654
+ taskIds: []
3655
+ });
3656
+ this.stateCheckpoint?.recordSpawn({
3657
+ id: subagentId,
3658
+ name: config.name,
3659
+ role: config.role,
3660
+ provider: config.provider,
3661
+ model: config.model,
3662
+ spawnedAt: (/* @__PURE__ */ new Date()).toISOString()
3663
+ }, this.spawnCount);
3664
+ void this.appendSessionEvent({
3665
+ type: "agent_spawned",
3666
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
3667
+ agentId: subagentId,
3668
+ role: config.role ?? config.name
3669
+ });
3670
+ this.scheduleManifest();
3671
+ }
3672
+ async writeManifest() {
3673
+ if (!this.manifestPath) return null;
3674
+ const manifest = {
3675
+ version: 1,
3676
+ directorRunId: this.directorRunId,
3677
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3678
+ children: Array.from(this.manifestEntries.values()).map((entry) => ({
3679
+ id: entry.subagentId,
3680
+ name: entry.name,
3681
+ role: entry.role,
3682
+ provider: entry.provider,
3683
+ model: entry.model,
3684
+ taskIds: entry.taskIds
3685
+ })),
3686
+ usage: this.usage.snapshot()
3687
+ };
3688
+ await fsp4.mkdir(path4.dirname(this.manifestPath), { recursive: true });
3689
+ await atomicWrite(this.manifestPath, JSON.stringify(manifest, null, 2), { mode: 384 });
3690
+ return this.manifestPath;
3691
+ }
3692
+ /**
3693
+ * Attach task ids to an already-spawned subagent. Called by
3694
+ * `Director.assign()` after the coordinator assigns a task.
3695
+ */
3696
+ addTaskToSubagent(subagentId, taskId) {
3697
+ const entry = this.manifestEntries.get(subagentId);
3698
+ if (entry) entry.taskIds.push(taskId);
3699
+ }
3700
+ /**
3701
+ * Debounced manifest write. Call after any state mutation
3702
+ * (spawn, assign, complete) so a burst collapses into one write.
3703
+ */
3704
+ scheduleManifest() {
3705
+ if (!this.manifestPath || this.manifestDebounceMs <= 0) return;
3706
+ if (this.manifestTimer) return;
3707
+ this.manifestTimer = setTimeout(() => {
3708
+ this.manifestTimer = null;
3709
+ void this.writeManifest().catch((err) => {
3710
+ const detail = err instanceof Error ? err.message : String(err);
3711
+ process.emitWarning(
3712
+ `FleetManager manifest write failed: ${detail}`,
3713
+ "FleetManagerWarning"
3714
+ );
3715
+ });
3716
+ }, this.manifestDebounceMs);
3717
+ }
3718
+ /** Best-effort session event writer. Swallows failures. */
3719
+ async appendSessionEvent(event) {
3720
+ if (!this.sessionWriter) return;
3721
+ try {
3722
+ await this.sessionWriter.append(event);
3723
+ } catch {
3724
+ }
3725
+ }
3726
+ // -----------------------------------------------------------------------
3727
+ // Pending task management — eliminates host-side state duplication
3728
+ // -----------------------------------------------------------------------
3729
+ addPendingTask(taskId, subagentId, description) {
3730
+ this.pendingTasks.set(taskId, { subagentId, description });
3731
+ }
3732
+ removePendingTask(taskId) {
3733
+ this.pendingTasks.delete(taskId);
3734
+ }
3735
+ getFleetStatus() {
3736
+ const pending = Array.from(this.pendingTasks.entries()).map(([taskId, v]) => ({
3737
+ taskId,
3738
+ description: v.description,
3739
+ subagentId: v.subagentId
3740
+ }));
3741
+ return { pending, live: [] };
3742
+ }
3743
+ };
3744
+
3745
+ export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, BUG_HUNTER_AGENT, BudgetExceededError, BudgetThresholdSignal, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, Director, FLEET_ROSTER, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, InMemoryAgentBridge, InMemoryBridgeTransport, NULL_FLEET_BUS, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, SubagentBudget, composeDirectorPrompt, composeSubagentPrompt, createDelegateTool, createMessage, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs };
3487
3746
  //# sourceMappingURL=index.js.map
3488
3747
  //# sourceMappingURL=index.js.map