@wrongstack/core 0.9.19 → 0.10.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 (73) hide show
  1. package/README.md +37 -33
  2. package/dist/{agent-bridge-DMVOX0cF.d.ts → agent-bridge-DBBGP5O4.d.ts} +1 -1
  3. package/dist/{agent-subagent-runner-C4qt9e5Y.d.ts → agent-subagent-runner-KwufTWwn.d.ts} +3 -4
  4. package/dist/compactor-D1RHFRmF.d.ts +41 -0
  5. package/dist/{config-CWva0qoL.d.ts → config-CJXBka2r.d.ts} +38 -2
  6. package/dist/{context-BRNbHmRM.d.ts → context-7u93AcGD.d.ts} +140 -0
  7. package/dist/coordination/index.d.ts +13 -13
  8. package/dist/coordination/index.js +786 -200
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/{default-config-Uzla85H-.d.ts → default-config-DEXI4jsl.d.ts} +10 -1
  11. package/dist/defaults/index.d.ts +24 -24
  12. package/dist/defaults/index.js +1612 -528
  13. package/dist/defaults/index.js.map +1 -1
  14. package/dist/{events-CiG9qUM_.d.ts → events-Bw1K5E6K.d.ts} +49 -1
  15. package/dist/execution/index.d.ts +46 -32
  16. package/dist/execution/index.js +663 -169
  17. package/dist/execution/index.js.map +1 -1
  18. package/dist/extension/index.d.ts +6 -6
  19. package/dist/extension/index.js.map +1 -1
  20. package/dist/goal-store-BeRsj7YX.d.ts +188 -0
  21. package/dist/{index-p95HQ22A.d.ts → index-DIt5TIaF.d.ts} +8 -8
  22. package/dist/{index-aizK8olO.d.ts → index-DgQWnZxP.d.ts} +11 -8
  23. package/dist/index.d.ts +338 -41
  24. package/dist/index.js +2747 -787
  25. package/dist/index.js.map +1 -1
  26. package/dist/infrastructure/index.d.ts +6 -6
  27. package/dist/infrastructure/index.js +36 -0
  28. package/dist/infrastructure/index.js.map +1 -1
  29. package/dist/kernel/index.d.ts +9 -9
  30. package/dist/kernel/index.js +57 -8
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mcp-servers-BkVEqkRe.d.ts → mcp-servers-BgINZzuo.d.ts} +25 -3
  33. package/dist/models/index.d.ts +3 -3
  34. package/dist/models/index.js +164 -11
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/models-registry-gwMAo6E3.d.ts +86 -0
  37. package/dist/{multi-agent-3ZnTB1aT.d.ts → multi-agent-C1O8EFzb.d.ts} +77 -24
  38. package/dist/{multi-agent-coordinator-bRaI_aD1.d.ts → multi-agent-coordinator-DoVSBFNx.d.ts} +20 -2
  39. package/dist/{null-fleet-bus-DKM3Iy9d.d.ts → null-fleet-bus-T-s3JaOt.d.ts} +413 -110
  40. package/dist/observability/index.d.ts +2 -2
  41. package/dist/{path-resolver-TcJfc29Y.d.ts → path-resolver-BfyK-I7w.d.ts} +2 -2
  42. package/dist/{permission-bPuzAy4x.d.ts → permission-B6sldrSp.d.ts} +1 -1
  43. package/dist/{permission-policy-BUQSutpl.d.ts → permission-policy-CtNscWOA.d.ts} +10 -9
  44. package/dist/{plan-templates-fkQTyz3U.d.ts → plan-templates-BWs6Je7j.d.ts} +8 -8
  45. package/dist/{provider-runner-BEpikbbN.d.ts → provider-runner-BmPe2RuU.d.ts} +3 -3
  46. package/dist/{retry-policy-BYkq0ugs.d.ts → retry-policy-KF18W4dg.d.ts} +1 -1
  47. package/dist/sdd/index.d.ts +9 -10
  48. package/dist/sdd/index.js +350 -122
  49. package/dist/sdd/index.js.map +1 -1
  50. package/dist/security/index.d.ts +65 -4
  51. package/dist/security/index.js +67 -19
  52. package/dist/security/index.js.map +1 -1
  53. package/dist/{selector-pox8abg0.d.ts → selector-DmXxpFyM.d.ts} +1 -1
  54. package/dist/{session-reader-CSWcb5Ga.d.ts → session-reader-CCSBfQmd.d.ts} +2 -2
  55. package/dist/skills/index.d.ts +1 -1
  56. package/dist/skills/index.js +1 -1
  57. package/dist/skills/index.js.map +1 -1
  58. package/dist/storage/index.d.ts +392 -8
  59. package/dist/storage/index.js +796 -40
  60. package/dist/storage/index.js.map +1 -1
  61. package/dist/{system-prompt-Bs-Wliab.d.ts → system-prompt-CM6zOhd2.d.ts} +19 -1
  62. package/dist/{tool-executor-Boo3dekH.d.ts → tool-executor-D7RxLtg4.d.ts} +9 -4
  63. package/dist/types/index.d.ts +16 -16
  64. package/dist/types/index.js +404 -14
  65. package/dist/types/index.js.map +1 -1
  66. package/dist/utils/index.d.ts +40 -8
  67. package/dist/utils/index.js +127 -57
  68. package/dist/utils/index.js.map +1 -1
  69. package/dist/{wstack-paths-BCgmTNlG.d.ts → wstack-paths-eMXnY1_X.d.ts} +8 -0
  70. package/package.json +1 -1
  71. package/dist/compactor-DVTKL7XD.d.ts +0 -23
  72. package/dist/goal-store-C7jcumEh.d.ts +0 -96
  73. package/dist/models-registry-OG_30xqZ.d.ts +0 -46
package/README.md CHANGED
@@ -20,7 +20,7 @@ Requires **Node.js ≥ 22.0.0**.
20
20
  src/
21
21
  core/ — Agent, Context, ConversationState, ProviderRunner, InputBuilder
22
22
  defaults/ — Production-ready implementations (session store, secret vault, …)
23
- kernel/ — Container, TOKENS, EventBus, ToolRegistry, ProviderRegistry
23
+ kernel/ — Container, TOKENS, EventBus, ScopedEventBus, Pipeline, RunController
24
24
  plugin/ — Plugin loader, PluginAPI, manifest validation
25
25
  registry/ — SlashCommandRegistry, ToolRegistry, ProviderRegistry
26
26
  types/ — Public type surface (Tool, Provider, SessionStore, …)
@@ -29,55 +29,59 @@ src/
29
29
 
30
30
  ## Quick example
31
31
 
32
- Run an agent loop with the Anthropic provider and a single tool:
32
+ The kernel is the small set of primitives the agent is built on. You can use them
33
+ standalone — for instance, to wire a small observability pipeline around a tool call:
33
34
 
34
35
  ```ts
35
36
  import {
36
- Agent,
37
37
  Container,
38
- Context,
39
- DefaultEventBus,
38
+ EventBus,
39
+ Pipeline,
40
+ RunController,
41
+ TOKENS,
40
42
  DefaultLogger,
41
43
  DefaultPermissionPolicy,
42
- DefaultSessionStore,
43
- DefaultSystemPromptBuilder,
44
- DefaultTokenCounter,
45
- ToolRegistry,
46
- TOKENS,
47
44
  } from '@wrongstack/core';
48
- import { AnthropicProvider } from '@wrongstack/providers';
49
- import { readTool, writeTool, bashTool } from '@wrongstack/tools';
50
45
 
46
+ // 1. DI container — bind defaults to TOKENS, override per token.
51
47
  const container = new Container();
52
- container.bind(TOKENS.EventBus, () => new DefaultEventBus());
53
48
  container.bind(TOKENS.Logger, () => new DefaultLogger());
54
49
  container.bind(TOKENS.PermissionPolicy, () => new DefaultPermissionPolicy());
55
50
 
56
- const provider = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY! });
57
- const tools = new ToolRegistry([readTool, writeTool, bashTool]);
58
-
59
- const ctx = new Context({
60
- cwd: process.cwd(),
61
- projectRoot: process.cwd(),
62
- provider,
63
- model: 'claude-sonnet-4-6',
64
- tokenCounter: new DefaultTokenCounter({ providerId: 'anthropic' }),
51
+ // 2. Typed event bus observe, don't mutate. Listener errors are isolated
52
+ // and routed to the optional logger; one bad subscriber can't kill emit().
53
+ const events = new EventBus();
54
+ events.on('tool.executed', ({ name, durationMs }) => {
55
+ console.log(`tool ${name} ran in ${durationMs}ms`);
65
56
  });
66
57
 
67
- const agent = new Agent({
68
- container,
69
- ctx,
70
- tools,
71
- systemPromptBuilder: new DefaultSystemPromptBuilder(),
72
- });
73
-
74
- const result = await agent.run({
75
- input: { text: 'list the files in src/' },
58
+ // 3. Koa-style pipeline — chain middleware around a value. The error
59
+ // boundary decides per-middleware whether to rethrow or swallow, so
60
+ // one bad plugin can't take down the agent loop.
61
+ type Req = { url: string };
62
+ const requestLog = new Pipeline<Req>();
63
+ requestLog.use({
64
+ name: 'timing',
65
+ handler: async (req, next) => {
66
+ const start = Date.now();
67
+ const res = await next(req);
68
+ console.log(`${req.url} took ${Date.now() - start}ms`);
69
+ return res;
70
+ },
76
71
  });
72
+ requestLog.setErrorHandler(() => 'swallow');
77
73
 
78
- console.log(result.assistantText);
74
+ // 4. Abort + cleanup — hooks fire in LIFO order on abort OR dispose().
75
+ const run = new RunController();
76
+ const off = run.onAbort(() => console.log('cleaning up'));
77
+ // later, when the run ends: await run.dispose();
79
78
  ```
80
79
 
80
+ For a full agent loop with a real LLM provider and tools, see
81
+ [`packages/cli/src/wiring/pipeline.ts`](../cli/src/wiring/pipeline.ts) — the
82
+ `Agent` constructor needs a `ToolExecutor`, `ProviderRegistry`, and several
83
+ container-resolved policies, which the CLI assembles from the user's config.
84
+
81
85
  ## Replacing a default
82
86
 
83
87
  Every concrete class under `defaults/` implements an interface in `types/`. The container resolves by token, so swapping is a one-line change:
@@ -95,7 +99,7 @@ class StrictPolicy implements PermissionPolicy {
95
99
  container.bind(TOKENS.PermissionPolicy, () => new StrictPolicy());
96
100
  ```
97
101
 
98
- The same pattern works for `SessionStore`, `MemoryStore`, `SystemPromptBuilder`, `RetryPolicy`, `ErrorHandler`, `TokenCounter`, `SecretVault`, `SecretScrubber`, `Compactor`, `ConfigStore`, `ModelsRegistry`, `ModeStore`.
102
+ The same pattern works for `SessionStore`, `MemoryStore`, `SystemPromptBuilder`, `RetryPolicy`, `ErrorHandler`, `TokenCounter`, `SecretScrubber`, `Compactor`, `ConfigStore`, `ModelsRegistry`, `ModeStore`. (`SecretVault` isn't container-resolved — pass it to `ConfigLoader` instead.)
99
103
 
100
104
  ## Building a tool
101
105
 
@@ -1,4 +1,4 @@
1
- import { b as BridgeTransport, B as BridgeMessage, A as AgentBridge, a as AgentBridgeConfig } from './multi-agent-3ZnTB1aT.js';
1
+ import { b as BridgeTransport, B as BridgeMessage, A as AgentBridge, a as AgentBridgeConfig } from './multi-agent-C1O8EFzb.js';
2
2
 
3
3
  /**
4
4
  * In-memory pub/sub transport for agent-to-agent messaging.
@@ -1,6 +1,6 @@
1
- import { c as Agent, f as AgentInput } from './index-aizK8olO.js';
2
- import { E as EventBus } from './events-CiG9qUM_.js';
3
- import { n as SubagentConfig, v as TaskSpec, t as SubagentRunner } from './multi-agent-3ZnTB1aT.js';
1
+ import { c as Agent, f as AgentInput } from './index-DgQWnZxP.js';
2
+ import { E as EventBus } from './events-Bw1K5E6K.js';
3
+ import { n as SubagentConfig, v as TaskSpec, t as SubagentRunner } from './multi-agent-C1O8EFzb.js';
4
4
 
5
5
  /**
6
6
  * Single fleet-wide event with subagent attribution. Whatever a child
@@ -91,7 +91,6 @@ interface SubagentUsageSnapshot {
91
91
  * each subagent's per-token rates from the models registry.
92
92
  */
93
93
  declare class FleetUsageAggregator {
94
- private readonly bus;
95
94
  private readonly priceLookup?;
96
95
  private readonly metaLookup?;
97
96
  private readonly perSubagent;
@@ -0,0 +1,41 @@
1
+ import { d as Context } from './context-7u93AcGD.js';
2
+
3
+ interface CompactRepairReport {
4
+ removedToolUses: string[];
5
+ removedToolResults: string[];
6
+ removedMessages: number;
7
+ }
8
+ interface CompactReport {
9
+ /**
10
+ * Token count of messages only (pre-compaction).
11
+ * Use `fullRequestTokensBefore` for accurate context-window load calculations.
12
+ */
13
+ before: number;
14
+ /**
15
+ * Token count of messages only (post-compaction).
16
+ * Use `fullRequestTokensAfter` for accurate context-window load calculations.
17
+ */
18
+ after: number;
19
+ /**
20
+ * Full API request token count before compaction: messages + systemPrompt + toolDefs.
21
+ * This is the accurate figure for context-window pressure monitoring.
22
+ */
23
+ fullRequestTokensBefore: number;
24
+ /**
25
+ * Full API request token count after compaction: messages + systemPrompt + toolDefs.
26
+ * This is the accurate figure for context-window pressure monitoring.
27
+ */
28
+ fullRequestTokensAfter: number;
29
+ reductions: {
30
+ phase: 'elision' | 'summary' | 'selective';
31
+ saved: number;
32
+ }[];
33
+ repaired?: CompactRepairReport;
34
+ }
35
+ interface Compactor {
36
+ compact(ctx: Context, opts?: {
37
+ aggressive?: boolean;
38
+ }): Promise<CompactReport>;
39
+ }
40
+
41
+ export type { CompactReport as C, Compactor as a };
@@ -1,5 +1,5 @@
1
1
  import { W as WireFamily } from './models-registry-BcYJDKLm.js';
2
- import { P as Permission } from './context-BRNbHmRM.js';
2
+ import { P as Permission } from './context-7u93AcGD.js';
3
3
 
4
4
  type ContextWindowModeId = 'balanced' | 'frugal' | 'deep' | 'archival';
5
5
  type ContextWindowAggressiveOn = 'hard' | 'soft' | 'warn';
@@ -165,6 +165,37 @@ interface AutonomyConfig {
165
165
  /** ms to wait before auto-proceeding in 'auto' mode. Default: 45000. */
166
166
  autoProceedDelayMs?: number;
167
167
  }
168
+ /**
169
+ * Controls how much detail is persisted to the per-session JSONL log
170
+ * (`~/.wrongstack/projects/<hash>/sessions/<id>.jsonl`).
171
+ */
172
+ interface SessionLoggingConfig {
173
+ /**
174
+ * How much detail to write to the persistent session log.
175
+ *
176
+ * - "minimal" → Only events required for resume/rewind/recovery
177
+ * - "standard" → (default) + high-value lightweight audit events
178
+ * (compaction, tool timing, retries, errors, etc.)
179
+ * - "full" → Also persist full request payloads (very large).
180
+ * Consider enabling a separate replay log instead.
181
+ */
182
+ auditLevel?: 'minimal' | 'standard' | 'full';
183
+ /**
184
+ * Sampling configuration for high-volume events (especially relevant at
185
+ * `auditLevel: "full"`).
186
+ */
187
+ sampling?: {
188
+ /** Controls sampling of `tool_progress` events. */
189
+ toolProgress?: {
190
+ /**
191
+ * Sample rate for noisy progress events (`log`, `partial_output`).
192
+ * - 1 = no sampling (every message is logged)
193
+ * - 8 = default (first message + every 8th)
194
+ */
195
+ sampleRate?: number;
196
+ };
197
+ };
198
+ }
168
199
  type SyncCategory = 'settings' | 'skills' | 'prompts' | 'memory' | 'history';
169
200
  interface SyncConfig {
170
201
  enabled: boolean;
@@ -191,6 +222,11 @@ interface Config {
191
222
  cwd?: string;
192
223
  /** Autonomy mode configuration (auto-proceed delay, etc.). */
193
224
  autonomy?: AutonomyConfig;
225
+ /**
226
+ * Session logging & audit configuration.
227
+ * Controls what gets written to the persistent JSONL transcript.
228
+ */
229
+ session?: SessionLoggingConfig;
194
230
  /**
195
231
  * Cloud sync configuration. Stored separately in sync.json to avoid
196
232
  * accidentally committing the GitHub token to project configs.
@@ -252,4 +288,4 @@ interface ConfigStore {
252
288
  watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
253
289
  }
254
290
 
255
- export { type AutonomyConfig as A, CONTEXT_WINDOW_MODES as C, DEFAULT_CONTEXT_WINDOW_MODE_ID as D, type FeaturesConfig as F, type LogConfig as L, type MCPServerConfig as M, type PluginConfig as P, type SyncCategory as S, type ToolsConfig as T, type Config as a, type ConfigLoader as b, type ConfigStore as c, type ContextConfig as d, type ContextWindowAggressiveOn as e, type ContextWindowConfigLike as f, type ContextWindowMode as g, type ContextWindowModeId as h, type ContextWindowPolicy as i, type ContextWindowThresholds as j, type ProviderApiKey as k, type ProviderConfig as l, type SyncConfig as m, formatContextWindowModeList as n, getContextWindowMode as o, isContextWindowModeId as p, listContextWindowModes as q, resolveContextWindowPolicy as r };
291
+ export { type AutonomyConfig as A, CONTEXT_WINDOW_MODES as C, DEFAULT_CONTEXT_WINDOW_MODE_ID as D, type FeaturesConfig as F, type LogConfig as L, type MCPServerConfig as M, type PluginConfig as P, type SessionLoggingConfig as S, type ToolsConfig as T, type Config as a, type ConfigLoader as b, type ConfigStore as c, type ContextConfig as d, type ContextWindowAggressiveOn as e, type ContextWindowConfigLike as f, type ContextWindowMode as g, type ContextWindowModeId as h, type ContextWindowPolicy as i, type ContextWindowThresholds as j, type ProviderApiKey as k, type ProviderConfig as l, type SyncCategory as m, type SyncConfig as n, formatContextWindowModeList as o, getContextWindowMode as p, isContextWindowModeId as q, listContextWindowModes as r, resolveContextWindowPolicy as s };
@@ -131,8 +131,10 @@ declare const ERROR_CODES: {
131
131
  readonly SESSION_WRITE_FAILED: "SESSION_WRITE_FAILED";
132
132
  readonly CONTAINER_TOKEN_ALREADY_BOUND: "CONTAINER_TOKEN_ALREADY_BOUND";
133
133
  readonly CONTAINER_TOKEN_NOT_BOUND: "CONTAINER_TOKEN_NOT_BOUND";
134
+ readonly CONTAINER_CIRCULAR_DEPENDENCY: "CONTAINER_CIRCULAR_DEPENDENCY";
134
135
  readonly REGISTRY_DUPLICATE: "REGISTRY_DUPLICATE";
135
136
  readonly REGISTRY_NOT_FOUND: "REGISTRY_NOT_FOUND";
137
+ readonly REGISTRY_INVALID: "REGISTRY_INVALID";
136
138
  readonly FS_READ_FAILED: "FS_READ_FAILED";
137
139
  readonly FS_WRITE_FAILED: "FS_WRITE_FAILED";
138
140
  readonly FS_MKDIR_FAILED: "FS_MKDIR_FAILED";
@@ -348,6 +350,19 @@ interface Tool<I = unknown, O = unknown> {
348
350
  * unpredictably.
349
351
  */
350
352
  estimatedDurationMs?: number;
353
+ /**
354
+ * Declarative security capabilities granted by this tool.
355
+ *
356
+ * Examples: "shell.arbitrary", "fs.write", "fs.write.outside-project",
357
+ * "net.outbound", "mcp.proxy", "subagent.spawn", "config.mutate".
358
+ *
359
+ * These are used by permission policies (especially subagent guards) and
360
+ * future capability-based allowlists. Prefer well-known values over ad-hoc strings.
361
+ *
362
+ * This field is optional for backward compatibility. Tools without it are
363
+ * treated conservatively by guards.
364
+ */
365
+ capabilities?: readonly string[];
351
366
  execute(input: I, ctx: Context, opts: {
352
367
  signal: AbortSignal;
353
368
  }): Promise<O>;
@@ -584,6 +599,42 @@ interface SessionMetadata {
584
599
  /** Set when a session is closed with open tool calls — used to restore pending state on resume. */
585
600
  pendingToolUses?: string[];
586
601
  }
602
+ /**
603
+ * SessionEvent — per-session persistent JSONL audit + reconstruct log.
604
+ *
605
+ * ## Two-Tier Model (see Config.session.auditLevel)
606
+ *
607
+ * **Core Reconstruct Set** (always persisted, minimal & reliable):
608
+ * - `session_start`, `session_resumed`, `user_input`, `llm_response`, `tool_result`
609
+ * - `checkpoint`, `file_snapshot`, `rewound`
610
+ * - `in_flight_start` / `in_flight_end`, `session_end`
611
+ *
612
+ * These events are **required** for correct resume, rewind, crash recovery
613
+ * and conversation replay. They are written regardless of auditLevel.
614
+ *
615
+ * **Audit Detail Set** (controlled by `session.auditLevel`):
616
+ * - `llm_request` (lightweight by default)
617
+ * - `tool_use`, `tool_call_start`/`tool_call_end`
618
+ * - `compaction`, `error`, `message_truncated`, provider retries, etc.
619
+ *
620
+ * When `auditLevel: "minimal"` only Core Reconstruct events are guaranteed.
621
+ * `"standard"` (default) adds the most valuable lightweight audit events.
622
+ * `"full"` enables heavier payloads (may be stored in a sidecar replay log).
623
+ *
624
+ * ## Guarantees
625
+ * - All appends are best-effort. A failed write logs a throttled warning but
626
+ * never aborts the agent loop.
627
+ * - Sensitive content in `user_input` and `llm_response` is passed through
628
+ * the configured SecretScrubber before being written or summarized.
629
+ * - The log is append-only JSONL. Individual lines may be malformed after
630
+ * hard crashes; `DefaultSessionStore.load()` silently skips bad lines.
631
+ *
632
+ * ## Location (source of truth: resolveWstackPaths)
633
+ * ~/.wrongstack/projects/<sha256(projectRoot).slice(0,12)>/sessions/<id>.jsonl
634
+ *
635
+ * The only files that live inside the project tree are the committed
636
+ * `.wrongstack/AGENTS.md` and `.wrongstack/skills/`.
637
+ */
587
638
  type SessionEvent = {
588
639
  type: 'session_start';
589
640
  ts: string;
@@ -605,6 +656,10 @@ type SessionEvent = {
605
656
  ts: string;
606
657
  model: string;
607
658
  messageCount: number;
659
+ /** Estimated total input tokens for this request (messages + tools + system). */
660
+ estimatedInputTokens?: number;
661
+ /** Number of tools offered to the model in this request. */
662
+ toolCount?: number;
608
663
  } | {
609
664
  type: 'llm_response';
610
665
  ts: string;
@@ -628,6 +683,14 @@ type SessionEvent = {
628
683
  ts: string;
629
684
  before: number;
630
685
  after: number;
686
+ /** Pressure level that triggered the compaction. */
687
+ level?: 'warn' | 'soft' | 'hard';
688
+ aggressive?: boolean;
689
+ /** Summary of token savings per phase (elision, summary, selective). */
690
+ reductions?: Array<{
691
+ phase: string;
692
+ saved: number;
693
+ }>;
631
694
  } | {
632
695
  type: 'error';
633
696
  ts: string;
@@ -709,12 +772,43 @@ type SessionEvent = {
709
772
  name: string;
710
773
  id: string;
711
774
  durationMs: number;
775
+ /** Legacy field kept for backward compatibility. Prefer outputBytes. */
712
776
  outputSize: number;
777
+ ok?: boolean;
778
+ outputBytes?: number;
779
+ outputTokens?: number;
780
+ outputLines?: number;
781
+ } | {
782
+ /** Lightweight sampled progress from Tool.executeStream (only at auditLevel 'full'). */
783
+ type: 'tool_progress';
784
+ ts: string;
785
+ name: string;
786
+ id: string;
787
+ event: {
788
+ type: 'log' | 'warning' | 'metric' | 'file_changed' | 'partial_output';
789
+ text?: string;
790
+ data?: Record<string, unknown>;
791
+ };
713
792
  } | {
714
793
  type: 'message_truncated';
715
794
  ts: string;
716
795
  before: number;
717
796
  after: number;
797
+ } | {
798
+ type: 'provider_retry';
799
+ ts: string;
800
+ providerId: string;
801
+ attempt: number;
802
+ delayMs: number;
803
+ status?: number;
804
+ description: string;
805
+ } | {
806
+ type: 'provider_error';
807
+ ts: string;
808
+ providerId: string;
809
+ status?: number;
810
+ description: string;
811
+ retryable: boolean;
718
812
  } | {
719
813
  type: 'checkpoint';
720
814
  ts: string;
@@ -730,6 +824,29 @@ type SessionEvent = {
730
824
  ts: string;
731
825
  toPromptIndex: number;
732
826
  revertedFiles: string[];
827
+ } | {
828
+ /**
829
+ * Idea #1 from IDEAS.md — Stateful Session Recovery.
830
+ *
831
+ * Marks the start of "the process is currently working on this
832
+ * point in the log". If the process exits cleanly, a matching
833
+ * `in_flight_end` follows. If the process dies (crash, OOM,
834
+ * machine sleep, SIGKILL) the marker is the last event in the
835
+ * file — and `SessionRecovery.detectStale` flags the session
836
+ * as resumable.
837
+ *
838
+ * `context` is a free-form description of the current
839
+ * operation (e.g. "iteration 14 / tool: read / id: tu-7") so
840
+ * the recovery UI can show "what was the agent doing when it
841
+ * died?".
842
+ */
843
+ type: 'in_flight_start';
844
+ ts: string;
845
+ context: string;
846
+ } | {
847
+ type: 'in_flight_end';
848
+ ts: string;
849
+ reason: 'clean' | 'aborted' | 'recovered';
733
850
  };
734
851
  type FileSnapshot = {
735
852
  path: string;
@@ -821,6 +938,29 @@ interface SessionWriter {
821
938
  * Called by /clear to wipe chat history from persistent storage.
822
939
  */
823
940
  clearSession(): Promise<void>;
941
+ /**
942
+ * Idea #1 from IDEAS.md — Stateful Session Recovery.
943
+ *
944
+ * Writes an `in_flight_start` event at the current point in the
945
+ * log. The agent loop should call this at the start of every
946
+ * long-running operation (an iteration, a tool execution, a
947
+ * streaming LLM call) so that a crashed process leaves a
948
+ * visible "what was I doing?" marker. Pair with
949
+ * `clearInFlightMarker` on clean shutdown.
950
+ *
951
+ * The `context` string is surfaced verbatim by
952
+ * `SessionRecovery.detectStale` and the `/resume --incomplete`
953
+ * CLI command, so prefer something a human can read at a glance:
954
+ * "iteration 14 / tool: read / id: tu-7"
955
+ */
956
+ writeInFlightMarker(context: string): Promise<void>;
957
+ /**
958
+ * Writes an `in_flight_end` event. Call on every clean exit
959
+ * point (after a successful iteration, after the user issues
960
+ * /exit, after a graceful SIGINT, etc.). The `reason` is
961
+ * surfaced in the session log for postmortem review.
962
+ */
963
+ clearInFlightMarker(reason: 'clean' | 'aborted' | 'recovered'): Promise<void>;
824
964
  }
825
965
 
826
966
  interface CacheStats {
@@ -1,20 +1,20 @@
1
- export { A as ACP_AGENTS, a as AGENTS_BY_PHASE, b as AGENT_CATALOG, c as ALL_AGENT_DEFINITIONS, d as ALL_FLEET_AGENTS, e as AUDIT_LOG_AGENT, f as AutoExtendCeiling, g as AutoExtendPolicy, B as BUG_HUNTER_AGENT, C as CreateDelegateToolOptions, D as DEFAULT_DIRECTOR_PREAMBLE, h as DEFAULT_SUBAGENT_BASELINE, i as DelegateHost, j as Director, k as DirectorPromptParts, l as DirectorSessionFactory, m as DirectorSessionFactoryOptions, F as FLEET_ROSTER, n as FLEET_ROSTER_BUDGETS, o as FLEET_ROSTER_WITHACP, p as FleetCostCapError, q as FleetManager, r as FleetManagerOptions, s as FleetRosterBudget, t as FleetSpawnBudgetError, I as ICoordinator, u as IFleetManager, N as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, S as SECURITY_SCANNER_AGENT, v as SubagentPromptParts, w as applyRosterBudget, x as attachAutoExtend, y as composeDirectorPrompt, z as composeSubagentPrompt, E as createDelegateTool, G as getAgentDefinition, H as makeAskTool, J as makeAssignTool, K as makeAwaitTasksTool, L as makeCollabDebugTool, M as makeDirectorSessionFactory, O as makeFleetEmitTool, P as makeFleetHealthTool, Q as makeFleetSessionTool, T as makeFleetStatusTool, U as makeFleetUsageTool, V as makeRollUpTool, W as makeSpawnTool, X as makeTerminateTool, Y as rosterSummaryFromConfigs } from '../null-fleet-bus-DKM3Iy9d.js';
2
- import { b as AgentDefinition } from '../multi-agent-coordinator-bRaI_aD1.js';
3
- export { T as AGENT_TOOL_PRESETS, A as AgentBudgetTier, a as AgentCapability, c as AgentPhase, D as DEFAULT_DISPATCH_ROLE, d as DefaultMultiAgentCoordinator, e as DispatchCandidate, f as DispatchClassifier, g as DispatchMethod, h as DispatchOptions, i as DispatchResult, H as HEAVY_BUDGET, L as LIGHT_BUDGET, M as MEDIUM_BUDGET, j as MultiAgentCoordinatorOptions, k as dispatchAgent, m as makeLLMClassifier, s as scoreAgents } from '../multi-agent-coordinator-bRaI_aD1.js';
4
- export { c as BudgetExceededError, d as BudgetKind, e as BudgetLimits, f as BudgetNegotiationMode, g as BudgetThresholdDecision, h as BudgetThresholdHandler, i as BudgetThresholdSignal, j as BudgetUsage, m as SubagentBudget } from '../multi-agent-3ZnTB1aT.js';
5
- 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-C4qt9e5Y.js';
6
- export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-DMVOX0cF.js';
7
- import '../context-BRNbHmRM.js';
8
- import '../director-state-BmYi3DGA.js';
9
- import '../events-CiG9qUM_.js';
1
+ export { A as ACP_AGENTS, a as AGENTS_BY_PHASE, b as AGENT_CATALOG, c as ALL_AGENT_DEFINITIONS, d as ALL_FLEET_AGENTS, e as AUDIT_LOG_AGENT, f as AutoExtendCeiling, g as AutoExtendPolicy, B as BUG_HUNTER_AGENT, h as BugFinding, C as CollabBudgetConfig, i as CollabBudgetOverrides, j as CollabBudgetWarningPayload, k as CollabDebugReport, l as CollabSession, m as CollabSessionOptions, n as CreateDelegateToolOptions, o as CriticConcern, p as CriticEvaluation, D as DEFAULT_DIRECTOR_PREAMBLE, q as DEFAULT_SUBAGENT_BASELINE, r as DelegateHost, s as Director, t as DirectorAlert, u as DirectorAlertLevel, v as DirectorCancelCollabPayload, w as DirectorPromptParts, x as DirectorSessionFactory, y as DirectorSessionFactoryOptions, F as FLEET_ROSTER, z as FLEET_ROSTER_BUDGETS, E as FLEET_ROSTER_WITHACP, G as FleetCostCapError, H as FleetManager, I as FleetManagerOptions, J as FleetRosterBudget, K as FleetSpawnBudgetError, L as ICoordinator, M as IFleetManager, N as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, O as RefactorPhase, P as RefactorPlan, S as SECURITY_SCANNER_AGENT, Q as SharedFileEntry, T as SharedFileSnapshot, U as SubagentPromptParts, V as applyRosterBudget, W as attachAutoExtend, X as composeDirectorPrompt, Y as composeSubagentPrompt, Z as createDelegateTool, _ as getAgentDefinition, $ as makeAskTool, a0 as makeAssignTool, a1 as makeAwaitTasksTool, a2 as makeCollabDebugTool, a3 as makeDirectorSessionFactory, a4 as makeFleetEmitTool, a5 as makeFleetHealthTool, a6 as makeFleetSessionTool, a7 as makeFleetStatusTool, a8 as makeFleetUsageTool, a9 as makeRollUpTool, aa as makeSpawnTool, ab as makeTerminateTool, ac as makeWorkCompleteTool, ad as rosterSummaryFromConfigs } from '../null-fleet-bus-T-s3JaOt.js';
2
+ import { b as AgentDefinition } from '../multi-agent-coordinator-DoVSBFNx.js';
3
+ export { T as AGENT_TOOL_PRESETS, A as AgentBudgetTier, a as AgentCapability, c as AgentPhase, D as DEFAULT_DISPATCH_ROLE, d as DefaultMultiAgentCoordinator, e as DispatchCandidate, f as DispatchClassifier, g as DispatchMethod, h as DispatchOptions, i as DispatchResult, H as HEAVY_BUDGET, L as LIGHT_BUDGET, M as MEDIUM_BUDGET, j as MultiAgentCoordinatorOptions, k as dispatchAgent, m as makeLLMClassifier, s as scoreAgents } from '../multi-agent-coordinator-DoVSBFNx.js';
4
+ export { c as BudgetExceededError, d as BudgetKind, e as BudgetLimits, f as BudgetNegotiationMode, g as BudgetThresholdDecision, h as BudgetThresholdHandler, i as BudgetThresholdSignal, j as BudgetUsage, m as SubagentBudget } from '../multi-agent-C1O8EFzb.js';
5
+ 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-KwufTWwn.js';
6
+ export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-DBBGP5O4.js';
7
+ import '../context-7u93AcGD.js';
10
8
  import 'node:events';
11
- import '../index-aizK8olO.js';
9
+ import '../director-state-BmYi3DGA.js';
10
+ import '../events-Bw1K5E6K.js';
11
+ import '../index-DgQWnZxP.js';
12
12
  import '../logger-DDd5C--Z.js';
13
- import '../system-prompt-Bs-Wliab.js';
13
+ import '../system-prompt-CM6zOhd2.js';
14
14
  import '../observability-BhnVLBLS.js';
15
15
  import '../secret-scrubber-3MHDDAtm.js';
16
- import '../permission-bPuzAy4x.js';
17
- import '../config-CWva0qoL.js';
16
+ import '../permission-B6sldrSp.js';
17
+ import '../config-CJXBka2r.js';
18
18
  import '../models-registry-BcYJDKLm.js';
19
19
 
20
20
  /** Phase 1 · Discovery — map the territory before any work begins. */