@wrongstack/core 0.6.4 → 0.6.6

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 (66) hide show
  1. package/dist/{agent-bridge-eb7qnNrd.d.ts → agent-bridge-BBXK_ppx.d.ts} +1 -1
  2. package/dist/agent-subagent-runner-DsSm9lKN.d.ts +174 -0
  3. package/dist/{compactor-RIPuTtWK.d.ts → compactor-C8NhpSt5.d.ts} +1 -1
  4. package/dist/{config-BGGuP_Ar.d.ts → config-DfC6g6KV.d.ts} +1 -1
  5. package/dist/{context-CDRyrkKQ.d.ts → context-DN5v-uQX.d.ts} +11 -0
  6. package/dist/coordination/index.d.ts +10 -9
  7. package/dist/coordination/index.js +113 -20
  8. package/dist/coordination/index.js.map +1 -1
  9. package/dist/defaults/index.d.ts +22 -21
  10. package/dist/defaults/index.js +1359 -919
  11. package/dist/defaults/index.js.map +1 -1
  12. package/dist/{events-BHuIHekD.d.ts → events-CJqwQl8G.d.ts} +17 -1
  13. package/dist/execution/index.d.ts +116 -13
  14. package/dist/execution/index.js +1438 -131
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/extension/index.d.ts +6 -6
  17. package/dist/{goal-store-DVCfj7Ff.d.ts → goal-store-HHgaq5ue.d.ts} +3 -3
  18. package/dist/{index-CPcDqvZh.d.ts → index-CXnWsGBp.d.ts} +11 -175
  19. package/dist/{index-BOn9NK7D.d.ts → index-DcnXDPdY.d.ts} +6 -6
  20. package/dist/index.d.ts +29 -28
  21. package/dist/index.js +1105 -666
  22. package/dist/index.js.map +1 -1
  23. package/dist/infrastructure/index.d.ts +6 -6
  24. package/dist/kernel/index.d.ts +9 -9
  25. package/dist/kernel/index.js.map +1 -1
  26. package/dist/{mcp-servers-DBdh3cee.d.ts → mcp-servers-CevFHHM1.d.ts} +3 -3
  27. package/dist/models/index.d.ts +2 -2
  28. package/dist/models/index.js +5 -16
  29. package/dist/models/index.js.map +1 -1
  30. package/dist/{multi-agent-CxSb-9dQ.d.ts → multi-agent-D5IbASk_.d.ts} +16 -4
  31. package/dist/observability/index.d.ts +2 -2
  32. package/dist/{path-resolver-CMGNadvq.d.ts → path-resolver-CBx_q1HA.d.ts} +2 -2
  33. package/dist/{plan-templates-BJflQY2i.d.ts → plan-templates-BEOllUJV.d.ts} +5 -4
  34. package/dist/{provider-runner-BFgNXpaP.d.ts → provider-runner-Byh5TcJs.d.ts} +3 -3
  35. package/dist/{retry-policy-LKS8MHsB.d.ts → retry-policy-BZSIMxrJ.d.ts} +1 -1
  36. package/dist/sdd/index.d.ts +9 -4
  37. package/dist/sdd/index.js +21 -0
  38. package/dist/sdd/index.js.map +1 -1
  39. package/dist/{secret-scrubber-CfMdAJ_l.d.ts → secret-scrubber-CT7wefiO.d.ts} +1 -1
  40. package/dist/{secret-scrubber-BzQR5BiL.d.ts → secret-scrubber-I0QHY_ob.d.ts} +1 -1
  41. package/dist/security/index.d.ts +3 -3
  42. package/dist/{selector-C7HqnZJU.d.ts → selector-DDb_mq9X.d.ts} +1 -1
  43. package/dist/{session-reader-CzfRA6Vk.d.ts → session-reader-B9nVkziM.d.ts} +1 -1
  44. package/dist/storage/index.d.ts +6 -6
  45. package/dist/storage/index.js +29 -3
  46. package/dist/storage/index.js.map +1 -1
  47. package/dist/{system-prompt-Dl2QY1_B.d.ts → system-prompt-gL06H9P4.d.ts} +1 -1
  48. package/dist/{task-graph-BITvWt4t.d.ts → task-graph-D1YQbpxF.d.ts} +1 -0
  49. package/dist/{tool-executor-FoxBjULX.d.ts → tool-executor-BF7QfYVE.d.ts} +4 -4
  50. package/dist/types/index.d.ts +16 -16
  51. package/dist/types/index.js +5 -16
  52. package/dist/types/index.js.map +1 -1
  53. package/dist/utils/index.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/skills/audit-log/SKILL.md +57 -28
  56. package/skills/bug-hunter/SKILL.md +85 -61
  57. package/skills/git-flow/SKILL.md +73 -18
  58. package/skills/multi-agent/SKILL.md +69 -40
  59. package/skills/node-modern/SKILL.md +111 -19
  60. package/skills/prompt-engineering/SKILL.md +97 -16
  61. package/skills/react-modern/SKILL.md +104 -18
  62. package/skills/refactor-planner/SKILL.md +73 -43
  63. package/skills/sdd/SKILL.md +123 -165
  64. package/skills/security-scanner/SKILL.md +95 -93
  65. package/skills/skill-creator/SKILL.md +58 -25
  66. package/skills/typescript-strict/SKILL.md +107 -15
@@ -1,4 +1,4 @@
1
- import { B as BridgeTransport, l as BridgeMessage, A as AgentBridge, m as AgentBridgeConfig } from './multi-agent-CxSb-9dQ.js';
1
+ import { B as BridgeTransport, l as BridgeMessage, A as AgentBridge, m as AgentBridgeConfig } from './multi-agent-D5IbASk_.js';
2
2
 
3
3
  /**
4
4
  * In-memory pub/sub transport for agent-to-agent messaging.
@@ -0,0 +1,174 @@
1
+ import { A as Agent, k as AgentInput } from './index-DcnXDPdY.js';
2
+ import { E as EventBus } from './events-CJqwQl8G.js';
3
+ import { c as SubagentConfig, k as TaskSpec, i as SubagentRunner } from './multi-agent-D5IbASk_.js';
4
+
5
+ /**
6
+ * Single fleet-wide event with subagent attribution. Whatever a child
7
+ * agent emits on its own EventBus gets re-published here, prefixed with
8
+ * `subagentId` so a single subscriber can multiplex across the fleet.
9
+ *
10
+ * The director uses `FleetBus.filter('tool.executed', …)` to see every
11
+ * tool call across the fleet; the TUI uses
12
+ * `FleetBus.subscribe(id, handler)` to render a per-subagent panel.
13
+ */
14
+ interface FleetEvent {
15
+ subagentId: string;
16
+ taskId?: string;
17
+ ts: number;
18
+ type: string;
19
+ payload: unknown;
20
+ }
21
+ type FleetHandler = (event: FleetEvent) => void;
22
+ /**
23
+ * Fan-in for per-subagent EventBuses. Each subagent's bus is plugged in
24
+ * via `attach()`; the FleetBus re-emits every event with subagent
25
+ * attribution. Detachment is automatic via the returned disposer — call
26
+ * it when a subagent terminates so we don't leak listeners.
27
+ *
28
+ * The bus exposes two subscription modes: by `subagentId` (everything
29
+ * from one child) and by `type` (one event-type across the fleet). They
30
+ * compose — if you need a per-subagent + per-type slice, subscribe by
31
+ * type and filter on `event.subagentId` in your handler.
32
+ */
33
+ declare class FleetBus {
34
+ private readonly byId;
35
+ private readonly byType;
36
+ private readonly any;
37
+ /**
38
+ * Hook a subagent's EventBus into the fleet. EventBus is strongly
39
+ * typed and doesn't expose an `onAny` hook, so we subscribe to the
40
+ * canonical set of event types a subagent emits during a run. New
41
+ * event types added to the kernel must be added here too — but the
42
+ * cost is a tiny single line per type, and the explicit list keeps
43
+ * the wire format clear.
44
+ *
45
+ * Returns a disposer that detaches every subscription; call on
46
+ * subagent teardown so the listeners don't outlive the run.
47
+ */
48
+ attach(subagentId: string, bus: EventBus, taskId?: string): () => void;
49
+ /** Subscribe to every event from one subagent. */
50
+ subscribe(subagentId: string, handler: FleetHandler): () => void;
51
+ /** Subscribe to one event type across all subagents. */
52
+ filter(type: string, handler: FleetHandler): () => void;
53
+ /** Subscribe to literally everything. The fleet roll-up uses this. */
54
+ onAny(handler: FleetHandler): () => void;
55
+ emit(event: FleetEvent): void;
56
+ }
57
+ /**
58
+ * Roll-up of token usage + cost across an entire director run. The
59
+ * director's `fleet_status` tool returns this so the model can reason
60
+ * about budget in its next turn ("the researcher already burned $0.40,
61
+ * lean on summaries for the next task").
62
+ */
63
+ interface FleetUsage {
64
+ total: {
65
+ input: number;
66
+ output: number;
67
+ cacheRead: number;
68
+ cacheWrite: number;
69
+ cost: number;
70
+ };
71
+ perSubagent: Record<string, SubagentUsageSnapshot>;
72
+ }
73
+ interface SubagentUsageSnapshot {
74
+ subagentId: string;
75
+ provider?: string;
76
+ model?: string;
77
+ input: number;
78
+ output: number;
79
+ cacheRead: number;
80
+ cacheWrite: number;
81
+ cost: number;
82
+ toolCalls: number;
83
+ iterations: number;
84
+ startedAt: number;
85
+ lastEventAt: number;
86
+ }
87
+ /**
88
+ * Aggregates provider.response + tool.executed events from the FleetBus
89
+ * into a live `FleetUsage` snapshot. Costs are computed by the caller
90
+ * via a `priceLookup(subagentId)` so we don't bake provider-pricing
91
+ * coupling into core; the CLI/tests supply a function that resolves
92
+ * each subagent's per-token rates from the models registry.
93
+ */
94
+ declare class FleetUsageAggregator {
95
+ private readonly bus;
96
+ private readonly priceLookup?;
97
+ private readonly metaLookup?;
98
+ private readonly perSubagent;
99
+ private readonly total;
100
+ constructor(bus: FleetBus, priceLookup?: ((subagentId: string) => {
101
+ input?: number;
102
+ output?: number;
103
+ cacheRead?: number;
104
+ cacheWrite?: number;
105
+ } | undefined) | undefined, metaLookup?: ((subagentId: string) => {
106
+ provider?: string;
107
+ model?: string;
108
+ } | undefined) | undefined);
109
+ /** Live snapshot — safe to call from a tool's execute() body. */
110
+ snapshot(): FleetUsage;
111
+ private ensure;
112
+ private onProviderResponse;
113
+ private onToolExecuted;
114
+ private onIterationStarted;
115
+ }
116
+
117
+ /**
118
+ * Caller-supplied factory that builds an isolated `Agent` for a subagent.
119
+ * The factory MUST construct a fresh `Context` per call — sharing context
120
+ * between subagents defeats isolation. Each Agent should also use either
121
+ * its own `EventBus` or a forwarded view, so per-subagent metrics can be
122
+ * attributed correctly.
123
+ */
124
+ type AgentFactory = (config: SubagentConfig) => Promise<AgentFactoryResult>;
125
+ interface AgentFactoryResult {
126
+ agent: Agent;
127
+ /** Event bus the factory wired to this agent — required for budget hookup. */
128
+ events: EventBus;
129
+ /**
130
+ * Optional cleanup hook invoked in the runner's `finally` block once
131
+ * the task ends (success, failure, abort — same exit path). Factories
132
+ * that own resources scoped to a single task (per-subagent JSONL
133
+ * writers, transient providers, throwaway containers) implement this
134
+ * to close them deterministically instead of relying on GC. Errors
135
+ * thrown here are swallowed so a flaky cleanup can't mask the task's
136
+ * real result.
137
+ */
138
+ dispose?: () => Promise<void> | void;
139
+ }
140
+ interface AgentRunnerOptions {
141
+ factory: AgentFactory;
142
+ /**
143
+ * Format a TaskSpec into the user input the agent will receive. Defaults
144
+ * to `task.description ?? ''`. Override when subagents expect structured
145
+ * input (e.g. JSON contracts, role-prefixed prompts).
146
+ */
147
+ formatTaskInput?: (task: TaskSpec, config: SubagentConfig) => AgentInput;
148
+ /**
149
+ * When set, the runner attaches the subagent's EventBus to this FleetBus
150
+ * on task start and detaches it when the task finishes. This is the
151
+ * injection seam that lets the TUI fleet panel observe subagent activity
152
+ * live — without it, FleetBus stays empty.
153
+ */
154
+ fleetBus?: FleetBus;
155
+ }
156
+ /**
157
+ * Builds a `SubagentRunner` that drives a real `Agent` per task while honoring
158
+ * the coordinator's budget and abort signal. This is the production adapter —
159
+ * the coordinator's `runner` option in CLI/TUI assemblies points here.
160
+ *
161
+ * Lifecycle per task:
162
+ * 1. factory(config) → fresh Agent + EventBus.
163
+ * 2. Subscribe to events to feed the budget (tool calls, token usage).
164
+ * 3. Call agent.run(input, { signal }) — the coordinator's signal cancels.
165
+ * 4. Map RunResult.status onto a `SubagentRunOutcome` or throw on failure.
166
+ * 5. Unsubscribe and let the factory's resources be GC'd.
167
+ *
168
+ * The budget is checked synchronously from event handlers — a runaway agent
169
+ * that crosses its tool-call limit triggers `BudgetExceededError`, which the
170
+ * coordinator surfaces as `status: 'failed'` on the task result.
171
+ */
172
+ declare function makeAgentSubagentRunner(opts: AgentRunnerOptions): SubagentRunner;
173
+
174
+ export { type AgentFactory as A, FleetBus as F, type SubagentUsageSnapshot as S, type AgentFactoryResult as a, type AgentRunnerOptions as b, type FleetEvent as c, type FleetHandler as d, type FleetUsage as e, FleetUsageAggregator as f, makeAgentSubagentRunner as m };
@@ -1,4 +1,4 @@
1
- import { a2 as Context } from './context-CDRyrkKQ.js';
1
+ import { a2 as Context } from './context-DN5v-uQX.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-CDRyrkKQ.js';
2
+ import { P as Permission } from './context-DN5v-uQX.js';
3
3
 
4
4
  type ContextWindowModeId = 'balanced' | 'frugal' | 'deep' | 'archival';
5
5
  type ContextWindowAggressiveOn = 'hard' | 'soft' | 'warn';
@@ -696,6 +696,12 @@ interface SessionStore {
696
696
  resume(id: string): Promise<ResumedSession>;
697
697
  list(limit?: number): Promise<SessionSummary[]>;
698
698
  delete(id: string): Promise<void>;
699
+ /**
700
+ * Rewrite the session JSONL file to contain only a fresh session_start
701
+ * event, effectively clearing all conversation history for that session.
702
+ * Called by /clear to wipe persistent chat history.
703
+ */
704
+ clearHistory(id: string): Promise<void>;
699
705
  }
700
706
  interface SessionWriter {
701
707
  readonly id: string;
@@ -736,6 +742,11 @@ interface SessionWriter {
736
742
  * Returns the number of events removed.
737
743
  */
738
744
  truncateToCheckpoint(promptIndex: number): Promise<number>;
745
+ /**
746
+ * Clear the session transcript file, resetting the on-disk history.
747
+ * Called by /clear to wipe chat history from persistent storage.
748
+ */
749
+ clearSession(): Promise<void>;
739
750
  }
740
751
 
741
752
  interface CacheStats {
@@ -1,14 +1,15 @@
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-CPcDqvZh.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-CxSb-9dQ.js';
3
- export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-eb7qnNrd.js';
1
+ export { A as ALL_FLEET_AGENTS, a as AUDIT_LOG_AGENT, B as BUG_HUNTER_AGENT, C as CreateDelegateToolOptions, D as DEFAULT_DIRECTOR_PREAMBLE, b as DEFAULT_SUBAGENT_BASELINE, c as DefaultMultiAgentCoordinator, d as DelegateHost, e as Director, f as DirectorPromptParts, g as DirectorSessionFactory, h as DirectorSessionFactoryOptions, F as FLEET_ROSTER, u as FleetCostCapError, j as FleetManager, k as FleetManagerOptions, l as FleetSpawnBudgetError, I as ICoordinator, m as IFleetManager, M as MultiAgentCoordinatorOptions, N as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, S as SECURITY_SCANNER_AGENT, n as SubagentPromptParts, p as composeDirectorPrompt, q as composeSubagentPrompt, r as createDelegateTool, s as makeDirectorSessionFactory, t as rosterSummaryFromConfigs } from '../index-CXnWsGBp.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-D5IbASk_.js';
3
+ export { A as AgentFactory, a as AgentFactoryResult, b as AgentRunnerOptions, F as FleetBus, c as FleetEvent, d as FleetHandler, e as FleetUsage, f as FleetUsageAggregator, S as SubagentUsageSnapshot, m as makeAgentSubagentRunner } from '../agent-subagent-runner-DsSm9lKN.js';
4
+ export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-BBXK_ppx.js';
4
5
  import '../director-state-BmYi3DGA.js';
5
- import '../context-CDRyrkKQ.js';
6
- import '../events-BHuIHekD.js';
6
+ import '../context-DN5v-uQX.js';
7
7
  import 'node:events';
8
- import '../index-BOn9NK7D.js';
8
+ import '../events-CJqwQl8G.js';
9
+ import '../index-DcnXDPdY.js';
9
10
  import '../logger-BMQgxvdy.js';
10
- import '../system-prompt-Dl2QY1_B.js';
11
+ import '../system-prompt-gL06H9P4.js';
11
12
  import '../observability-BhnVLBLS.js';
12
- import '../secret-scrubber-CfMdAJ_l.js';
13
- import '../config-BGGuP_Ar.js';
13
+ import '../secret-scrubber-CT7wefiO.js';
14
+ import '../config-DfC6g6KV.js';
14
15
  import '../models-registry-Y2xbog0E.js';
@@ -832,7 +832,7 @@ var SubagentBudget = class _SubagentBudget {
832
832
  * is dispatched as a fire-and-forget promise.
833
833
  */
834
834
  checkLimit(kind, used, limit) {
835
- if (kind === "timeout" || !this._onThreshold) {
835
+ if (!this._onThreshold) {
836
836
  throw new BudgetExceededError(kind, limit, used);
837
837
  }
838
838
  const bus = this._events;
@@ -948,14 +948,18 @@ var SubagentBudget = class _SubagentBudget {
948
948
  }
949
949
  }
950
950
  /**
951
- * Throws if the wall-clock budget is exhausted. Call this from the iteration
952
- * loop so a hung tool can't keep a subagent running past its deadline.
951
+ * Wall-clock budget check. Unlike other limits, timeout is treated as a
952
+ * warning-only event it NEVER hard-stops the subagent. When the
953
+ * elapsed time exceeds timeoutMs, emits `budget.threshold_reached` with
954
+ * kind='timeout' so the Director can decide whether to extend or warn.
955
+ * Call this from the iteration loop so a hung tool gets a chance to
956
+ * negotiate more time before the coordinator's Promise.race kills it.
953
957
  */
954
958
  checkTimeout() {
955
959
  if (this.startTime === null || this.limits.timeoutMs === void 0) return;
956
960
  const elapsed = Date.now() - this.startTime;
957
961
  if (elapsed > this.limits.timeoutMs) {
958
- throw new BudgetExceededError("timeout", this.limits.timeoutMs, elapsed);
962
+ void this.checkLimit("timeout", elapsed, this.limits.timeoutMs);
959
963
  }
960
964
  }
961
965
  /** Returns true if a timeout has occurred without throwing. Useful for races. */
@@ -1151,10 +1155,10 @@ var FLEET_ROSTER = {
1151
1155
  "security-scanner": SECURITY_SCANNER_AGENT
1152
1156
  };
1153
1157
  var FLEET_ROSTER_BUDGETS = {
1154
- "audit-log": { timeoutMs: 5 * 60 * 1e3, maxIterations: 80, maxToolCalls: 300 },
1155
- "bug-hunter": { timeoutMs: 10 * 60 * 1e3, maxIterations: 120, maxToolCalls: 400 },
1156
- "refactor-planner": { timeoutMs: 8 * 60 * 1e3, maxIterations: 100, maxToolCalls: 350 },
1157
- "security-scanner": { timeoutMs: 10 * 60 * 1e3, maxIterations: 120, maxToolCalls: 400 }
1158
+ "audit-log": { timeoutMs: 8 * 60 * 1e3, maxIterations: 150, maxToolCalls: 500 },
1159
+ "bug-hunter": { timeoutMs: 15 * 60 * 1e3, maxIterations: 200, maxToolCalls: 600 },
1160
+ "refactor-planner": { timeoutMs: 12 * 60 * 1e3, maxIterations: 180, maxToolCalls: 550 },
1161
+ "security-scanner": { timeoutMs: 15 * 60 * 1e3, maxIterations: 200, maxToolCalls: 600 }
1158
1162
  };
1159
1163
  function applyRosterBudget(cfg) {
1160
1164
  const defaultBudget = FLEET_ROSTER_BUDGETS[cfg.role ?? ""];
@@ -1294,6 +1298,33 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
1294
1298
  results() {
1295
1299
  return this.completedResults;
1296
1300
  }
1301
+ /**
1302
+ * Wait for one or more tasks to complete and return their results.
1303
+ * If a task is already done when called, returns immediately.
1304
+ * Resolves to an array in the same order as `taskIds`.
1305
+ */
1306
+ async awaitTasks(taskIds) {
1307
+ return Promise.all(
1308
+ taskIds.map((id) => {
1309
+ const cached = this.completedResults.find((r) => r.taskId === id);
1310
+ if (cached) return cached;
1311
+ return new Promise((resolve, reject) => {
1312
+ const timeout = setTimeout(() => {
1313
+ this.off("task.completed", handler);
1314
+ reject(new Error(`awaitTasks timed out waiting for task "${id}"`));
1315
+ }, this.config.timeoutMs ?? 3e5);
1316
+ const handler = ({ result }) => {
1317
+ if (result.taskId === id) {
1318
+ clearTimeout(timeout);
1319
+ this.off("task.completed", handler);
1320
+ resolve(result);
1321
+ }
1322
+ };
1323
+ this.on("task.completed", handler);
1324
+ });
1325
+ })
1326
+ );
1327
+ }
1297
1328
  /**
1298
1329
  * Manual completion — for callers that drive subagents without a runner
1299
1330
  * (e.g. external orchestrators). When a runner is configured the coordinator
@@ -1512,8 +1543,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
1512
1543
  return;
1513
1544
  }
1514
1545
  if (decision === "throw" || decision === "stop") {
1515
- this.subagents.get(ctx.subagentId)?.abortController.abort();
1516
- reject(new BudgetExceededError("timeout", limit, elapsed));
1546
+ armFor(Math.max(1e3, limit));
1517
1547
  return;
1518
1548
  }
1519
1549
  if (decision.extend.timeoutMs !== void 0) {
@@ -2060,7 +2090,7 @@ var Director = class {
2060
2090
  this.sessionWriter = opts.sessionWriter ?? null;
2061
2091
  this.manifestDebounceMs = opts.manifestDebounceMs ?? 2e3;
2062
2092
  this.maxFleetCostUsd = opts.directorBudget?.maxCostUsd ?? Number.POSITIVE_INFINITY;
2063
- this.maxBudgetExtensions = opts.maxBudgetExtensions ?? 2;
2093
+ this.maxBudgetExtensions = opts.maxBudgetExtensions ?? 5;
2064
2094
  this.sessionsRoot = opts.sessionsRoot;
2065
2095
  this.directorRunId = opts.directorRunId ?? this.id;
2066
2096
  this.stateCheckpoint = opts.stateCheckpointPath ? new DirectorStateCheckpoint(opts.stateCheckpointPath, {
@@ -2148,19 +2178,19 @@ var Director = class {
2148
2178
  const extra = {};
2149
2179
  switch (payload.kind) {
2150
2180
  case "iterations":
2151
- extra.maxIterations = Math.min(payload.used + 50, 500);
2181
+ extra.maxIterations = Math.min(payload.used + 100, 800);
2152
2182
  break;
2153
2183
  case "tool_calls":
2154
- extra.maxToolCalls = Math.min(Math.ceil(payload.limit * 1.5), 1e3);
2184
+ extra.maxToolCalls = Math.min(Math.ceil(payload.limit * 2), 1500);
2155
2185
  break;
2156
2186
  case "tokens":
2157
- extra.maxTokens = Math.min(Math.ceil(payload.limit * 1.5), 5e5);
2187
+ extra.maxTokens = Math.min(Math.ceil(payload.limit * 2), 8e5);
2158
2188
  break;
2159
2189
  case "cost":
2160
- extra.maxCostUsd = Math.min(payload.limit * 1.5, 10);
2190
+ extra.maxCostUsd = Math.min(payload.limit * 2, 25);
2161
2191
  break;
2162
2192
  case "timeout":
2163
- extra.timeoutMs = Math.min(Math.ceil(payload.limit * 1.5), 60 * 6e4);
2193
+ extra.timeoutMs = Math.min(Math.ceil(payload.limit * 2), 2 * 60 * 6e4);
2164
2194
  break;
2165
2195
  }
2166
2196
  payload.extend(extra);
@@ -3009,10 +3039,22 @@ function makeAgentSubagentRunner(opts) {
3009
3039
  events.on("iteration.started", () => {
3010
3040
  try {
3011
3041
  ctx.budget.recordIteration();
3012
- ctx.budget.checkTimeout();
3013
3042
  } catch (e) {
3014
3043
  void onBudgetError(e);
3015
3044
  }
3045
+ const u = ctx.budget.usage();
3046
+ const since = u.iterations - lastSummaryAtIteration;
3047
+ if (since >= SUMMARY_INTERVAL) {
3048
+ lastSummaryAtIteration = u.iterations;
3049
+ events.emit("subagent.iteration_summary", {
3050
+ subagentId: ctx.subagentId,
3051
+ iteration: u.iterations,
3052
+ toolCalls: u.toolCalls,
3053
+ costUsd: u.costUsd,
3054
+ currentTool: currentToolName,
3055
+ partialText: streamingTextAcc.trim() || void 0
3056
+ });
3057
+ }
3016
3058
  }),
3017
3059
  // D3: cooperative timeout enforcement DURING a long tool call.
3018
3060
  // The iteration-loop checkTimeout() only fires between agent
@@ -3035,6 +3077,18 @@ function makeAgentSubagentRunner(opts) {
3035
3077
  }
3036
3078
  })
3037
3079
  );
3080
+ let currentToolName;
3081
+ let streamingTextAcc = "";
3082
+ let lastSummaryAtIteration = 0;
3083
+ const SUMMARY_INTERVAL = 25;
3084
+ unsub.push(
3085
+ events.on("tool.started", (e) => {
3086
+ currentToolName = e.name;
3087
+ }),
3088
+ events.on("provider.text_delta", (e) => {
3089
+ streamingTextAcc = (streamingTextAcc + e.text).slice(-200);
3090
+ })
3091
+ );
3038
3092
  const onParentAbort = () => aborter.abort();
3039
3093
  ctx.signal.addEventListener("abort", onParentAbort);
3040
3094
  let result;
@@ -3051,7 +3105,21 @@ function makeAgentSubagentRunner(opts) {
3051
3105
  }
3052
3106
  }
3053
3107
  }
3054
- if (budgetError) throw budgetError;
3108
+ if (budgetError) {
3109
+ if ("decision" in budgetError) {
3110
+ const decision = await budgetError.decision;
3111
+ if (decision === "stop") {
3112
+ budgetError = new BudgetExceededError(
3113
+ budgetError.kind,
3114
+ budgetError.limit,
3115
+ budgetError.used
3116
+ );
3117
+ } else {
3118
+ budgetError = null;
3119
+ }
3120
+ }
3121
+ if (budgetError) throw budgetError;
3122
+ }
3055
3123
  if (result.status === "failed") {
3056
3124
  throw result.error instanceof Error ? result.error : new Error(String(result.error ?? "agent failed"));
3057
3125
  }
@@ -3293,6 +3361,20 @@ var DefaultSessionStore = class {
3293
3361
  await fsp4.unlink(path4.join(this.dir, `${id}.jsonl`));
3294
3362
  await fsp4.unlink(path4.join(this.dir, `${id}.summary.json`)).catch(() => void 0);
3295
3363
  }
3364
+ async clearHistory(id) {
3365
+ const file = path4.join(this.dir, `${id}.jsonl`);
3366
+ const meta = path4.join(this.dir, `${id}.summary.json`);
3367
+ const record = `${JSON.stringify({
3368
+ type: "session_start",
3369
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
3370
+ id,
3371
+ model: "unknown",
3372
+ provider: "unknown"
3373
+ })}
3374
+ `;
3375
+ await fsp4.writeFile(file, record, "utf8");
3376
+ await fsp4.unlink(meta).catch(() => void 0);
3377
+ }
3296
3378
  async summarize(id, mtime) {
3297
3379
  try {
3298
3380
  const data = await this.load(id);
@@ -3598,10 +3680,21 @@ var FileSessionWriter = class {
3598
3680
  });
3599
3681
  return removedCount;
3600
3682
  }
3683
+ async clearSession() {
3684
+ if (!this.filePath) return;
3685
+ const record = `${JSON.stringify({
3686
+ type: "session_start",
3687
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
3688
+ id: this.id,
3689
+ model: this.meta.model ?? "unknown",
3690
+ provider: this.meta.provider ?? "unknown"
3691
+ })}
3692
+ `;
3693
+ await fsp4.writeFile(this.filePath, record, "utf8");
3694
+ }
3601
3695
  };
3602
3696
  function userInputTitle(content) {
3603
- if (typeof content === "string") return content.slice(0, 60);
3604
- const text = content.filter((b) => b.type === "text").map((b) => b.text).join(" ");
3697
+ const text = typeof content === "string" ? content : content.filter((b) => b.type === "text").map((b) => b.text).join(" ");
3605
3698
  return (text || "(non-text input)").slice(0, 60);
3606
3699
  }
3607
3700