@wrongstack/core 0.309.0 → 0.310.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 (129) hide show
  1. package/dist/chronicle/index.js +113 -41
  2. package/dist/chronicle/metrics-ingest.d.ts +7 -0
  3. package/dist/chronicle/metrics-schema.d.ts +4 -1
  4. package/dist/chronicle/project-server.js +94 -38
  5. package/dist/chronicle/query.d.ts +1 -0
  6. package/dist/chronicle/sqlite-journal-schema.d.ts +2 -1
  7. package/dist/chronicle/types.d.ts +2 -0
  8. package/dist/{agent-status-helpers.d.ts → coordination/agent-status-helpers.d.ts} +1 -1
  9. package/dist/{agent-status-tracker.d.ts → coordination/agent-status-tracker.d.ts} +2 -2
  10. package/dist/{middleware → coordination}/collab-pause.d.ts +1 -1
  11. package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -1
  12. package/dist/coordination/director.d.ts +7 -0
  13. package/dist/coordination/explore-companion.d.ts +9 -6
  14. package/dist/coordination/fleet-status-tool.d.ts +1 -1
  15. package/dist/coordination/index.d.ts +5 -1
  16. package/dist/coordination/index.js +2392 -405
  17. package/dist/coordination/kanban-dispatch-port.d.ts +30 -0
  18. package/dist/coordination/kanban-ops-port.d.ts +21 -0
  19. package/dist/coordination/mailbox-hooks.d.ts +1 -1
  20. package/dist/coordination/mailbox-project-server.js +14 -9
  21. package/dist/coordination/mutation-engine.d.ts +5 -3
  22. package/dist/core/context.d.ts +35 -44
  23. package/dist/core/conversation-state.d.ts +16 -52
  24. package/dist/core/index.js +92 -25
  25. package/dist/core/provider-runner.d.ts +2 -2
  26. package/dist/core/run-env.d.ts +7 -28
  27. package/dist/core/streaming-response-builder.d.ts +2 -2
  28. package/dist/execution/index.js +138 -162
  29. package/dist/goal/index.js +100 -22
  30. package/dist/hq/auth-store.d.ts +9 -0
  31. package/dist/hq/cost-bridge.d.ts +1 -1
  32. package/dist/hq/index.js +69 -7
  33. package/dist/index.d.ts +12 -5
  34. package/dist/index.js +21185 -26807
  35. package/dist/infrastructure/index.js +232 -135
  36. package/dist/infrastructure/provider-cache-ledger.d.ts +1 -1
  37. package/dist/infrastructure/token-counter.d.ts +5 -1
  38. package/dist/kernel/events/file-events.d.ts +6 -0
  39. package/dist/kernel/events/provider-events.d.ts +10 -7
  40. package/dist/kernel/events/session-events.d.ts +4 -4
  41. package/dist/kernel/events/tool-events.d.ts +12 -2
  42. package/dist/observability/index.js +1 -1
  43. package/dist/plugin/index.js +218 -47
  44. package/dist/prompts/index.js +360 -3
  45. package/dist/security/auto-approve-policy.d.ts +2 -2
  46. package/dist/security/index.d.ts +1 -0
  47. package/dist/security/index.js +224 -68
  48. package/dist/security/kanban-boundary.d.ts +1 -1
  49. package/dist/security/kanban-governance-port.d.ts +28 -0
  50. package/dist/security/permission-helpers.d.ts +11 -0
  51. package/dist/security/permission-policy.d.ts +10 -1
  52. package/dist/security/yolo-risk.d.ts +17 -0
  53. package/dist/session-catalog/index.js +34 -5
  54. package/dist/session-catalog/project-server.js +34 -5
  55. package/dist/session-catalog/protocol.d.ts +1 -1
  56. package/dist/session-catalog/registry.d.ts +1 -1
  57. package/dist/session-catalog/store-schema.d.ts +1 -1
  58. package/dist/session-catalog/store.d.ts +1 -1
  59. package/dist/skills/index.js +39 -6
  60. package/dist/storage/annotations-store.d.ts +1 -1
  61. package/dist/storage/board-store-port.d.ts +45 -0
  62. package/dist/storage/completed-work-checkpoint.d.ts +1 -1
  63. package/dist/storage/config-loader/types.d.ts +1 -1
  64. package/dist/storage/event-bus-port.d.ts +27 -0
  65. package/dist/storage/file-session-writer.d.ts +47 -5
  66. package/dist/storage/goal-coordination.d.ts +1 -1
  67. package/dist/storage/goal-store.d.ts +1 -1
  68. package/dist/storage/index.d.ts +3 -4
  69. package/dist/storage/index.js +1107 -1462
  70. package/dist/storage/plan-store.d.ts +1 -1
  71. package/dist/storage/queue-store.d.ts +1 -1
  72. package/dist/storage/replay-log-store.d.ts +1 -1
  73. package/dist/storage/session-recovery.d.ts +10 -0
  74. package/dist/storage/session-resume-validation.d.ts +13 -1
  75. package/dist/storage/session-store/events.d.ts +1 -1
  76. package/dist/storage/session-store/load-session-data.d.ts +1 -1
  77. package/dist/storage/session-store/rename-session.d.ts +1 -1
  78. package/dist/storage/session-store/resume-session.d.ts +3 -1
  79. package/dist/storage/session-store/session-store-index.d.ts +2 -1
  80. package/dist/storage/session-store/types.d.ts +1 -1
  81. package/dist/storage/session-store.d.ts +70 -0
  82. package/dist/storage/session-summary-tracker.d.ts +8 -0
  83. package/dist/storage/session-write-buffer.d.ts +31 -2
  84. package/dist/storage/task-store.d.ts +1 -1
  85. package/dist/storage/todos-checkpoint.d.ts +1 -1
  86. package/dist/storage/tool-audit-log.d.ts +1 -1
  87. package/dist/tasking/index.js +100 -22
  88. package/dist/tasking/task-tracker.d.ts +24 -1
  89. package/dist/types/compactor.d.ts +2 -2
  90. package/dist/types/context.d.ts +212 -0
  91. package/dist/types/conversation-state.d.ts +109 -0
  92. package/dist/types/error-handler.d.ts +2 -2
  93. package/dist/types/file-event-record.d.ts +6 -0
  94. package/dist/types/index.d.ts +3 -3
  95. package/dist/types/index.js +17 -1
  96. package/dist/types/permission.d.ts +3 -3
  97. package/dist/types/plugin.d.ts +3 -3
  98. package/dist/types/provider-runner.d.ts +2 -2
  99. package/dist/types/provider.d.ts +10 -0
  100. package/dist/types/run-env.d.ts +32 -0
  101. package/dist/types/session.d.ts +3 -0
  102. package/dist/types/slash-command.d.ts +2 -2
  103. package/dist/types/token-counter.d.ts +30 -1
  104. package/dist/types/tool-executor.d.ts +2 -2
  105. package/dist/types/tool.d.ts +20 -5
  106. package/dist/utils/context-breakdown.d.ts +2 -2
  107. package/dist/utils/context-evidence.d.ts +12 -12
  108. package/dist/utils/crash-shield.d.ts +9 -0
  109. package/dist/utils/heap-watchdog.js +11 -3
  110. package/dist/utils/index.d.ts +2 -1
  111. package/dist/utils/index.js +126 -160
  112. package/dist/utils/regex-guard.d.ts +7 -30
  113. package/dist/utils/terminal-sanitize.d.ts +41 -0
  114. package/dist/utils/todos-format.d.ts +1 -1
  115. package/dist/utils/tool-subject.d.ts +1 -1
  116. package/dist/utils/tree-kill.d.ts +2 -0
  117. package/dist/utils/tree-kill.js +1 -0
  118. package/instructions/agents/chaos-monkey.md +5 -1
  119. package/instructions/coordination/subagent-baseline.md +10 -0
  120. package/instructions/system-lite.md +2 -0
  121. package/instructions/system-pro.md +40 -0
  122. package/instructions/system.md +15 -0
  123. package/package.json +7 -10
  124. package/dist/defaults/index.d.ts +0 -69
  125. package/dist/defaults/index.js +0 -37755
  126. /package/dist/{fleet-notifier.d.ts → coordination/fleet-notifier.d.ts} +0 -0
  127. /package/dist/{session-registry-atomic-file.d.ts → session-catalog/session-registry-atomic-file.d.ts} +0 -0
  128. /package/dist/{session-registry-types.d.ts → session-catalog/session-registry-types.d.ts} +0 -0
  129. /package/dist/{session-registry.d.ts → session-catalog/session-registry.d.ts} +0 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * kanban-dispatch-port — composition seam for the Director's kanban
3
+ * dispatch and assignment operations (Roadmap #11).
4
+ *
5
+ * The coordination layer must not import `@wrongstack/kanban` at runtime;
6
+ * it resolves the concrete operations through this port, wired at the
7
+ * CLI composition root (see `setKanbanDispatch`). Type imports from
8
+ * `@wrongstack/kanban` are erased at compile time and do not create a
9
+ * runtime edge.
10
+ */
11
+ import type { CompleteDispatchInput, CompleteDispatchResult, FailDispatchInput, HeartbeatKanbanTaskAssignmentInput, KanbanAgentAssignment, KanbanAgentRunStatus, KanbanBoard, KanbanEventContext, KanbanSearchInput, KanbanSearchResult, ReserveDispatchInput, ReserveDispatchResult, StartDispatchInput, StartDispatchResult } from '@wrongstack/kanban';
12
+ export interface KanbanDispatchPort {
13
+ getBoard(projectRoot: string, boardId: string): Promise<KanbanBoard | null>;
14
+ listReadyTasks(projectRoot: string, input?: KanbanSearchInput & {
15
+ limit?: number | undefined;
16
+ }): Promise<KanbanSearchResult[]>;
17
+ reserveKanbanDispatch(projectRoot: string, input: ReserveDispatchInput): Promise<ReserveDispatchResult | null>;
18
+ startKanbanDispatch(projectRoot: string, input: StartDispatchInput): Promise<StartDispatchResult | null>;
19
+ completeKanbanDispatch(projectRoot: string, input: CompleteDispatchInput): Promise<CompleteDispatchResult | null>;
20
+ failKanbanDispatch(projectRoot: string, input: FailDispatchInput): Promise<KanbanBoard | null>;
21
+ updateTaskAssignment(projectRoot: string, boardId: string, taskId: string, patch: Partial<KanbanAgentAssignment> & {
22
+ status?: KanbanAgentRunStatus | undefined;
23
+ }, eventContext?: KanbanEventContext): Promise<KanbanBoard | null>;
24
+ heartbeatTaskAssignment(projectRoot: string, boardId: string, taskId: string, input?: HeartbeatKanbanTaskAssignmentInput): Promise<KanbanBoard | null>;
25
+ }
26
+ /** Composition-root hook: register the real kanban-backed implementation. */
27
+ export declare function setKanbanDispatch(impl: KanbanDispatchPort): void;
28
+ /** Runtime accessor used by director-tools; throws loudly when unwired. */
29
+ export declare function kanbanDispatch(): KanbanDispatchPort;
30
+ //# sourceMappingURL=kanban-dispatch-port.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Kanban operations port for the coordination area (director queue tools).
3
+ *
4
+ * The director queue helpers previously imported `describeKanbanBoundary`
5
+ * (a pure formatter) directly from `@wrongstack/kanban`, keeping a
6
+ * core → kanban runtime edge (roadmap #11 / report §2.1). This port is
7
+ * the leaf contract; the CLI composition root registers the real
8
+ * implementation at boot alongside the storage BoardStorePort.
9
+ *
10
+ * Type-only imports of kanban's data shapes remain permitted — they erase
11
+ * at compile time and do not create a runtime edge.
12
+ */
13
+ import type { KanbanBoundaryPolicy } from '@wrongstack/kanban';
14
+ export interface KanbanBoundaryOpsPort {
15
+ describeKanbanBoundary(policy: KanbanBoundaryPolicy | undefined): string;
16
+ }
17
+ /** Composition-root hook: register the real kanban-backed implementation. */
18
+ export declare function setKanbanBoundaryOps(impl: KanbanBoundaryOpsPort): void;
19
+ /** Resolve the boundary-ops port (throws when not wired, mirroring BoardStorePort). */
20
+ export declare function kanbanBoundaryOps(): KanbanBoundaryOpsPort;
21
+ //# sourceMappingURL=kanban-ops-port.d.ts.map
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @module mailbox-hooks
13
13
  */
14
- import type { Mailbox } from '../coordination/mailbox-types.js';
14
+ import type { Mailbox } from './mailbox-types.js';
15
15
  export interface MailboxHooksOptions {
16
16
  /** The mailbox instance. */
17
17
  mailbox: Mailbox;
@@ -384,7 +384,10 @@ var withFileLock = primitives.withFileLock;
384
384
  import * as fs from "node:fs";
385
385
  import * as fsp2 from "node:fs/promises";
386
386
  import * as path3 from "node:path";
387
- import { PerformanceObserver, constants as performanceConstants } from "node:perf_hooks";
387
+ import {
388
+ PerformanceObserver,
389
+ constants as performanceConstants
390
+ } from "node:perf_hooks";
388
391
  import * as v8 from "node:v8";
389
392
 
390
393
  // src/utils/memory-flight-recorder.ts
@@ -690,7 +693,8 @@ function createMemoryFlightRecorder(options = {}) {
690
693
  const now = options.now ?? Date.now;
691
694
  const startedAt2 = now();
692
695
  const root = options.diagnosticsRoot ?? path2.join(wstackGlobalRoot(), "diagnostics", "memory");
693
- const enabled = options.enabled ?? (process.env["WRONGSTACK_MEMORY_FLIGHT_RECORDER"] !== "0" && process.env["NODE_ENV"] !== "test");
696
+ const isBunRuntime = typeof globalThis.Bun !== "undefined";
697
+ const enabled = options.enabled ?? (!isBunRuntime && process.env["WRONGSTACK_MEMORY_FLIGHT_RECORDER"] !== "0" && process.env["NODE_ENV"] !== "test");
694
698
  const writer = options.captureWriter ?? (enabled ? new ContinuousMemoryCaptureWriter(root) : disabledWriter(path2.join(root, `${timestampSlug()}-pid-${process.pid}`)));
695
699
  const observations = [];
696
700
  const windowMs = options.windowMs ?? DEFAULT_WINDOW_MS;
@@ -800,7 +804,11 @@ function defaultHeapLogPath() {
800
804
  function takeHeapSample() {
801
805
  const m = process.memoryUsage();
802
806
  const heap = v8.getHeapStatistics();
803
- const spaces = v8.getHeapSpaceStatistics();
807
+ let spaces = [];
808
+ try {
809
+ spaces = v8.getHeapSpaceStatistics();
810
+ } catch {
811
+ }
804
812
  const spaceUsed = (name) => spaces.find((space) => space.space_name === name)?.space_used_size ?? 0;
805
813
  const limit = heap.heap_size_limit || 0;
806
814
  let activeResources = 0;
@@ -2230,8 +2238,8 @@ function previousCredentialTtlMs(credential) {
2230
2238
 
2231
2239
  // src/coordination/sqlite-mailbox-schema.ts
2232
2240
  import * as fs2 from "node:fs";
2233
- import { createRequire } from "node:module";
2234
2241
  import * as path5 from "node:path";
2242
+ import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
2235
2243
 
2236
2244
  // src/utils/sqlite-warning.ts
2237
2245
  var SQLITE_EXPERIMENTAL_WARNING_RE = /sqlite is an experimental feature/i;
@@ -2379,8 +2387,7 @@ var DatabaseSyncCtor;
2379
2387
  function loadDatabaseSync() {
2380
2388
  if (DatabaseSyncCtor) return DatabaseSyncCtor;
2381
2389
  return withSqliteExperimentalWarningSuppressed(() => {
2382
- const require2 = createRequire(import.meta.url);
2383
- DatabaseSyncCtor = require2("node:sqlite").DatabaseSync;
2390
+ DatabaseSyncCtor = loadRuntimeDatabaseSync();
2384
2391
  return DatabaseSyncCtor;
2385
2392
  });
2386
2393
  }
@@ -2536,9 +2543,7 @@ function migrateLegacyFiles(ctx) {
2536
2543
  }
2537
2544
  function readLegacyMessages(projectDir2) {
2538
2545
  try {
2539
- return parseMailboxFile(
2540
- fs2.readFileSync(path5.join(projectDir2, GLOBAL_MAILBOX_FILE), "utf8")
2541
- );
2546
+ return parseMailboxFile(fs2.readFileSync(path5.join(projectDir2, GLOBAL_MAILBOX_FILE), "utf8"));
2542
2547
  } catch (error) {
2543
2548
  if (error.code === "ENOENT") return [];
2544
2549
  throw error;
@@ -45,8 +45,10 @@ export interface PlanMutationsOptions {
45
45
  * Plan mutations for one file's source text.
46
46
  *
47
47
  * The scan is line-by-line with the file's own line splits preserved so ids
48
- * stay (line, column) anchored. Mutations inside comments and string
49
- * literals are filtered out by `isMasked` below.
48
+ * stay (line, column) anchored. Mutations inside comments, string literals,
49
+ * and template literals (single- or multi-line, interpolation contents
50
+ * excepted) are filtered out by the cross-line scanner `computeLineMasks`
51
+ * below.
50
52
  */
51
53
  export declare function planMutations(file: string, source: string, opts?: PlanMutationsOptions): MutationPlanItem[];
52
54
  /**
@@ -66,7 +68,7 @@ export declare function parseMutationReport(text: string): {
66
68
  file: string;
67
69
  line: number;
68
70
  kind: string;
69
- status: 'killed' | 'survived' | 'skipped';
71
+ status: 'killed' | 'survived' | 'skipped' | 'killed-by-hang';
70
72
  evidence?: string | undefined;
71
73
  }>;
72
74
  summary?: string | undefined;
@@ -3,36 +3,14 @@ import type { ContextEvidenceState } from '../types/context-evidence.js';
3
3
  import type { FileEventRecord } from '../types/file-event-record.js';
4
4
  import type { Message } from '../types/messages.js';
5
5
  import type { Provider, Usage } from '../types/provider.js';
6
- import type { SessionWriter } from '../types/session.js';
6
+ import type { SessionEvent, SessionWriter } from '../types/session.js';
7
7
  import type { TokenCounter } from '../types/token-counter.js';
8
8
  import type { Tool } from '../types/tool.js';
9
+ import type { AgentContext, ContextMessageLimits } from '../types/context.js';
10
+ import type { RunEnv } from '../types/run-env.js';
9
11
  import { ConversationState } from './conversation-state.js';
10
- import type { RunEnv } from './run-env.js';
11
- export interface TodoItem {
12
- id: string;
13
- content: string;
14
- status: 'pending' | 'in_progress' | 'completed';
15
- activeForm?: string | undefined;
16
- /** When promoted from a plan item, stores the plan item's id. */
17
- promotedFromPlan?: string | undefined;
18
- /** When promoted from a task, stores the task's id. */
19
- promotedFromTask?: string | undefined;
20
- /** Durable Kanban owner when the todo row is a UI projection of a real card. */
21
- kanbanBoardId?: string | undefined;
22
- /** Durable Kanban card represented by this todo row. */
23
- kanbanTaskId?: string | undefined;
24
- /**
25
- * Titles of the unfinished work this row waits on, derived from the Kanban
26
- * card's dependencies. Always board-derived, never model-supplied.
27
- *
28
- * A blocked item is genuinely `pending` — it has not started — so this is an
29
- * extra field rather than a fourth status. What was missing was never the
30
- * state but the *reason*: the board computes readiness on every mutation,
31
- * then the projection dropped it, leaving blocked work indistinguishable
32
- * from ready work on screen and in the model's context.
33
- */
34
- blockedBy?: string[] | undefined;
35
- }
12
+ import type { TodoItem } from '../types/context.js';
13
+ export type { TodoItem };
36
14
  export interface RunOptions {
37
15
  signal?: AbortSignal | undefined;
38
16
  model?: string | undefined;
@@ -103,7 +81,7 @@ export interface ProviderMemoryEvidence {
103
81
  * the agent and user to navigate within the project without spawning a new
104
82
  * process. All changes must stay inside `projectRoot`.
105
83
  */
106
- export declare class Context implements RunEnv {
84
+ export declare class Context implements RunEnv, AgentContext {
107
85
  messages: Message[];
108
86
  /**
109
87
  * Maximum number of messages retained in the conversation history.
@@ -243,6 +221,10 @@ export declare class Context implements RunEnv {
243
221
  * so storage operations can include it in `storage.*` events.
244
222
  */
245
223
  traceId: string | undefined;
224
+ /** Logical provider request whose response produced the current tool calls. */
225
+ activeLogicalRequestId: string | undefined;
226
+ /** Content-addressed prompt composition for {@link activeLogicalRequestId}. */
227
+ activePromptManifestId: string | undefined;
246
228
  /**
247
229
  * Session id pinned to the currently-executing run. Set by `Agent.run()`
248
230
  * at run start and cleared when the run ends. Event-emission sites must
@@ -266,13 +248,14 @@ export declare class Context implements RunEnv {
266
248
  */
267
249
  eventSessionId(): string;
268
250
  /** Callbacks fired when `setWorkingDir()` changes the working directory. */
269
- private _onWorkingDirChanged;
251
+ /** WorkingDir-change callbacks; public for structural typing (Roadmap 10A). */
252
+ readonly _onWorkingDirChanged: Array<(newDir: string, oldDir: string) => void>;
270
253
  /**
271
254
  * Serializes externally requested provider/model changes. Request creation
272
255
  * waits on this barrier so an automatic continuation cannot capture the old
273
256
  * model while a user-triggered switch is still building its provider.
274
257
  */
275
- private _modelTransition;
258
+ _modelTransition: Promise<void>;
276
259
  runModelTransition<T>(transition: () => T | Promise<T>): Promise<T>;
277
260
  waitForModelTransition(): Promise<void>;
278
261
  /**
@@ -333,23 +316,27 @@ export declare class Context implements RunEnv {
333
316
  * mutations that go through `state.appendMessage()` etc. fire
334
317
  * `onChange`. New code should prefer the wrapper API.
335
318
  */
336
- private _state;
337
- private readonly _conversationJournalQueue;
338
- private _conversationJournalBytes;
339
- private _conversationJournalDrain;
319
+ _state: ConversationState | null;
320
+ readonly _conversationJournalQueue: Array<{
321
+ event: SessionEvent;
322
+ bytes: number;
323
+ writer: SessionWriter;
324
+ }>;
325
+ _conversationJournalBytes: number;
326
+ _conversationJournalDrain: Promise<void> | null;
340
327
  private static readonly CONVERSATION_JOURNAL_MAX_EVENTS;
341
328
  private static readonly CONVERSATION_JOURNAL_MAX_BYTES;
342
329
  private static readonly MAX_FILE_EVENTS;
343
330
  private static readonly MAX_SIDE_EFFECTS;
344
331
  /** Wait until every exact conversation-state event queued so far is in the writer buffer. */
345
332
  flushConversationJournal(): Promise<void>;
346
- private conversationJournalBytes;
347
- private _journalDropCount;
348
- private _journalDropWarnAt;
333
+ conversationJournalBytes(event: SessionEvent): number;
334
+ _journalDropCount: number;
335
+ _journalDropWarnAt: number;
349
336
  /** Throttled notice that a conversation event never reached the journal. */
350
- private warnConversationJournalDrop;
351
- private enqueueConversationJournal;
352
- private startConversationJournalDrain;
337
+ warnConversationJournalDrop(eventType: SessionEvent['type']): void;
338
+ enqueueConversationJournal(event: SessionEvent, writer: SessionWriter): void;
339
+ startConversationJournalDrain(): void;
353
340
  get state(): ConversationState;
354
341
  /**
355
342
  * Register a teardown hook tied to the current run's abort signal.
@@ -364,7 +351,10 @@ export declare class Context implements RunEnv {
364
351
  * For hooks that must survive across run boundaries (mailbox heartbeat,
365
352
  * awareness polling, HQ publisher), prefer `registerAgentHook` instead.
366
353
  */
367
- private abortHooks;
354
+ /** Run-scoped abort hooks (drained by drainAbortHooks). Public for structural typing (Roadmap 10A). */
355
+ readonly abortHooks: Set<() => void | Promise<void>>;
356
+ /** Retention limits honoring runtime subclass overrides of the statics. */
357
+ get messageLimits(): ContextMessageLimits;
368
358
  registerAbortHook(fn: () => void | Promise<void>): () => void;
369
359
  drainAbortHooks(): Promise<void>;
370
360
  /**
@@ -377,7 +367,8 @@ export declare class Context implements RunEnv {
377
367
  * awareness polling interval, HQ publisher connection, and auto-compaction
378
368
  * timer — resources that must survive from the first run to the last.
379
369
  */
380
- private agentHooks;
370
+ /** Session-lifetime teardown hooks (drained by drainAgentHooks). Public for structural typing (Roadmap 10A). */
371
+ readonly agentHooks: Set<() => void | Promise<void>>;
381
372
  registerAgentHook(fn: () => void | Promise<void>): () => void;
382
373
  drainAgentHooks(): Promise<void>;
383
374
  /**
@@ -421,7 +412,7 @@ export declare class Context implements RunEnv {
421
412
  * the tool will re-stat the file and re-populate the entry. The agent
422
413
  * never fails or misbehaves; it just pays one extra stat call.
423
414
  */
424
- private trimTrackedFiles;
415
+ trimTrackedFiles(): void;
425
416
  private static trimSet;
426
417
  private static trimMap;
427
418
  /** Clear accumulated file-read metadata after compaction or at boundaries
@@ -508,5 +499,5 @@ export declare class Context implements RunEnv {
508
499
  * tests and lightweight embedders stub Context with partial objects whose
509
500
  * `session` may be missing despite the non-optional type.
510
501
  */
511
- export declare function resolveEventSessionId(ctx: Context): string;
502
+ export declare function resolveEventSessionId(ctx: AgentContext): string;
512
503
  //# sourceMappingURL=context.d.ts.map
@@ -1,6 +1,9 @@
1
1
  import type { ContentBlock } from '../types/blocks.js';
2
2
  import type { Message } from '../types/messages.js';
3
- import type { Context, TodoItem } from './context.js';
3
+ import type { AgentContext, TodoItem } from '../types/context.js';
4
+ import type { ConversationStateApi, ReadonlyConversationState, StateChange } from '../types/conversation-state.js';
5
+ export type { ConversationStateApi, ReadonlyConversationState, StateChange };
6
+ export type StateChangeHandler = (change: StateChange, state: ConversationStateApi) => void;
4
7
  /**
5
8
  * Observable wrapper for mutable conversation state. Production code should
6
9
  * mutate messages, todos, and meta through this API so subscribers see a
@@ -13,51 +16,13 @@ import type { Context, TodoItem } from './context.js';
13
16
  * that reads `ctx.messages` directly still works — they are NOT safe for
14
17
  * external writes.
15
18
  */
16
- export type StateChange = {
17
- kind: 'message_appended';
18
- message: Message;
19
- } | {
20
- kind: 'messages_replaced';
21
- messages: readonly Message[];
22
- }
23
- /** The oldest `count` messages were evicted; see the `messages_dropped` SessionEvent. */
24
- | {
25
- kind: 'messages_dropped';
26
- count: number;
27
- } | {
28
- kind: 'message_updated';
29
- index: number;
30
- message: Message;
31
- } | {
32
- kind: 'todos_replaced';
33
- todos: readonly TodoItem[];
34
- /**
35
- * Final all-completed snapshot when the tactical list auto-clears.
36
- * Observational mirrors use this to move cards to Done instead of
37
- * interpreting the empty active list as "the work vanished".
38
- */
39
- completedSnapshot?: readonly TodoItem[] | undefined;
40
- } | {
41
- kind: 'meta_set';
42
- key: string;
43
- value: unknown;
44
- } | {
45
- kind: 'meta_deleted';
46
- key: string;
47
- } | {
48
- kind: 'meta_cleared';
49
- };
50
- export type StateChangeHandler = (change: StateChange, state: ConversationState) => void;
51
- export interface ReadonlyConversationState {
52
- readonly messages: readonly Message[];
53
- readonly todos: readonly TodoItem[];
54
- readonly meta: Readonly<Record<string, unknown>>;
55
- }
56
19
  export declare class ConversationState {
57
- private readonly ctx;
58
- private readonly listeners;
59
- private _revision;
60
- constructor(ctx: Context);
20
+ /** Owning context; public for structural typing (Roadmap 10A). */
21
+ readonly ctx: AgentContext;
22
+ /** Subscribers; public for structural typing (Roadmap 10A). */
23
+ readonly listeners: Set<StateChangeHandler>;
24
+ _revision: number;
25
+ constructor(ctx: AgentContext);
61
26
  get messages(): readonly Message[];
62
27
  get todos(): readonly TodoItem[];
63
28
  get meta(): Readonly<Record<string, unknown>>;
@@ -77,16 +42,15 @@ export declare class ConversationState {
77
42
  appendMessage(message: Message): void;
78
43
  /**
79
44
  * How many of the oldest messages must be dropped to satisfy both retention
80
- * caps — count ({@link Context.MAX_MESSAGES}) and size
81
- * ({@link Context.MAX_MESSAGE_TOKENS}). Returns 0 when the history already
82
- * fits, which is the overwhelmingly common case.
45
+ * caps — count and size (see {@link AgentContext.messageLimits}). Returns 0
46
+ * when the history already fits, which is the overwhelmingly common case.
83
47
  *
84
48
  * The size pass reads the per-message `_estTokens` cache populated at
85
49
  * mutation time, so it is a sum over numbers rather than a re-walk of
86
50
  * content blocks. It runs whenever the token cap is enabled; the count
87
51
  * cap determines the starting index for the sum but does not gate it.
88
52
  */
89
- private overflowCount;
53
+ overflowCount(arr: readonly Message[]): number;
90
54
  /**
91
55
  * Front eviction must not retain a `tool_result` after evicting the
92
56
  * immediately preceding assistant `tool_use`. Long tool-heavy sessions sit
@@ -100,7 +64,7 @@ export declare class ConversationState {
100
64
  * the minimum lossless representation; once enough newer messages exist, the
101
65
  * next eviction boundary naturally moves past both halves together.
102
66
  */
103
- private protocolSafeDropCount;
67
+ protocolSafeDropCount(arr: readonly Message[], drop: number): number;
104
68
  /**
105
69
  * Append a content block to the trailing user message's content array.
106
70
  * Mutates only that one message (a single indexed assignment) — avoids
@@ -124,10 +88,10 @@ export declare class ConversationState {
124
88
  * the compatibility arrays are intentionally not observed.
125
89
  */
126
90
  onChange(listener: StateChangeHandler): () => void;
127
- private emit;
91
+ emit(change: StateChange): void;
128
92
  }
129
93
  /**
130
94
  * Convenience constructor. The wrapper holds a reference, not a copy.
131
95
  */
132
- export declare function wrapAsState(ctx: Context): ConversationState;
96
+ export declare function wrapAsState(ctx: AgentContext): ConversationState;
133
97
  //# sourceMappingURL=conversation-state.d.ts.map