@kodax-ai/kodax 0.7.40 → 0.7.41

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 (47) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/chunks/{chunk-NDNILSTR.js → chunk-5TFLMGER.js} +1 -1
  3. package/dist/chunks/{chunk-FAVPT4P7.js → chunk-6OB4AJOM.js} +1 -1
  4. package/dist/chunks/chunk-HYWVRTFA.js +1233 -0
  5. package/dist/chunks/chunk-SX2IS5JP.js +16 -0
  6. package/dist/chunks/chunk-ZPJPNLBK.js +462 -0
  7. package/dist/chunks/{compaction-config-A7XZ6H5Y.js → compaction-config-LT5PEXPT.js} +1 -1
  8. package/dist/chunks/{construction-bootstrap-OFPUZTXQ.js → construction-bootstrap-HBCWJFHC.js} +1 -1
  9. package/dist/chunks/dist-V3BS2NKB.js +2 -0
  10. package/dist/chunks/{utils-DFMYJUTE.js → utils-FAFUQJ2A.js} +1 -1
  11. package/dist/index.d.ts +232 -7
  12. package/dist/index.js +2 -2
  13. package/dist/kodax_cli.js +922 -912
  14. package/dist/sdk-agent.d.ts +1459 -10
  15. package/dist/sdk-agent.js +1 -1
  16. package/dist/sdk-coding.d.ts +4543 -14
  17. package/dist/sdk-coding.js +1 -1
  18. package/dist/sdk-llm.d.ts +209 -10
  19. package/dist/sdk-repl.d.ts +2694 -13
  20. package/dist/sdk-repl.js +1 -1
  21. package/dist/sdk-skills.d.ts +487 -11
  22. package/dist/types-chunks/bash-prefix-extractor.d-B2iliwdi.d.ts +2432 -0
  23. package/dist/types-chunks/capability.d-BxNgd1-c.d.ts +368 -0
  24. package/dist/types-chunks/cost-tracker.d-C4dMlQuV.d.ts +342 -0
  25. package/dist/types-chunks/history-cleanup.d-q1vAvCss.d.ts +1266 -0
  26. package/dist/types-chunks/instance-discovery.d-DZhp77vb.d.ts +1217 -0
  27. package/dist/types-chunks/resolver.d-BwD6TKz7.d.ts +262 -0
  28. package/dist/types-chunks/storage.d-Bv9T99Qu.d.ts +584 -0
  29. package/dist/types-chunks/types.d-C5mHR87z.d.ts +119 -0
  30. package/package.json +8 -3
  31. package/dist/acp_events.d.ts +0 -109
  32. package/dist/acp_logger.d.ts +0 -20
  33. package/dist/acp_server.d.ts +0 -92
  34. package/dist/chunks/chunk-CLS57NPX.js +0 -460
  35. package/dist/chunks/chunk-QZEDWITG.js +0 -1226
  36. package/dist/chunks/chunk-Z5EBDA6R.js +0 -15
  37. package/dist/chunks/dist-OTUF22DA.js +0 -2
  38. package/dist/cli_commands.d.ts +0 -17
  39. package/dist/cli_option_helpers.d.ts +0 -49
  40. package/dist/cli_option_helpers.test.d.ts +0 -1
  41. package/dist/constructed_cli.d.ts +0 -82
  42. package/dist/constructed_cli.test.d.ts +0 -1
  43. package/dist/kodax_cli.d.ts +0 -7
  44. package/dist/self_modify_cli.d.ts +0 -81
  45. package/dist/self_modify_cli.test.d.ts +0 -9
  46. package/dist/skill_cli.d.ts +0 -15
  47. package/dist/skill_cli.test.d.ts +0 -1
@@ -0,0 +1,1217 @@
1
+ import { o as KodaXMessage, _ as KodaXToolDefinition, G as KodaXReasoningMode, W as KodaXThinkingBlock, J as KodaXRedactedThinkingBlock } from './capability.d-BxNgd1-c.js';
2
+
3
+ /**
4
+ * @kodax-ai/agent Types
5
+ *
6
+ * 通用 Agent 类型定义
7
+ */
8
+
9
+ type KodaXJsonPrimitive = string | number | boolean | null;
10
+ type KodaXJsonValue = KodaXJsonPrimitive | KodaXJsonValue[] | {
11
+ [key: string]: KodaXJsonValue;
12
+ };
13
+ /**
14
+ * Session error metadata - 会话错误元数据
15
+ * Used for error recovery and session cleanup - 用于错误恢复和会话清理
16
+ */
17
+ interface SessionErrorMetadata {
18
+ /** Last error message - 最后的错误消息 */
19
+ lastError?: string;
20
+ /** Last error timestamp - 最后错误时间戳 */
21
+ lastErrorTime?: number;
22
+ /** Consecutive error count - 连续错误计数 */
23
+ consecutiveErrors: number;
24
+ }
25
+ interface KodaXExtensionSessionRecord {
26
+ id: string;
27
+ extensionId: string;
28
+ type: string;
29
+ ts: number;
30
+ data?: KodaXJsonValue;
31
+ dedupeKey?: string;
32
+ }
33
+ type KodaXExtensionSessionState = Record<string, Record<string, KodaXJsonValue>>;
34
+ interface KodaXSessionEntryBase {
35
+ id: string;
36
+ parentId: string | null;
37
+ timestamp: string;
38
+ }
39
+ interface KodaXSessionMessageEntry extends KodaXSessionEntryBase {
40
+ type: 'message';
41
+ message: KodaXMessage;
42
+ }
43
+ interface KodaXSessionCompactionEntry extends KodaXSessionEntryBase {
44
+ type: 'compaction';
45
+ summary: string;
46
+ firstKeptEntryId?: string;
47
+ tokensBefore?: number;
48
+ tokensAfter?: number;
49
+ artifactLedgerId?: string;
50
+ reason?: string;
51
+ details?: KodaXJsonValue;
52
+ memorySeed?: KodaXCompactMemorySeed;
53
+ /**
54
+ * FEATURE_072: post-compact ledger summary + file-content messages that
55
+ * are inlined after the compaction summary at slicer time
56
+ * (`getSessionMessagesFromLineage`). Stored here so they leave the active
57
+ * path automatically when a new compaction entry is appended.
58
+ *
59
+ * NOTE: attachments are emitted by the slicer, NOT by `getContextMessagesForEntry`
60
+ * — preserving the latter's 1-to-1 contract that `entryMatchesContextMessage`
61
+ * and FEATURE_073's future slicing both depend on.
62
+ */
63
+ postCompactAttachments?: readonly KodaXMessage[];
64
+ }
65
+ interface KodaXSessionBranchSummaryEntry extends KodaXSessionEntryBase {
66
+ type: 'branch_summary';
67
+ summary: string;
68
+ fromId?: string;
69
+ details?: KodaXJsonValue;
70
+ }
71
+ interface KodaXSessionLabelEntry extends KodaXSessionEntryBase {
72
+ type: 'label';
73
+ targetId: string;
74
+ label?: string;
75
+ }
76
+ interface KodaXSessionArchiveMarkerEntry extends KodaXSessionEntryBase {
77
+ type: 'archive_marker';
78
+ /** Links to the corresponding batch in the .archive.jsonl sidecar file */
79
+ archiveBatchId: string;
80
+ /** Number of entries that were archived in this batch */
81
+ archivedEntryCount: number;
82
+ /** Brief summary of the archived content */
83
+ summary: string;
84
+ }
85
+ type KodaXSessionEntry = KodaXSessionMessageEntry | KodaXSessionCompactionEntry | KodaXSessionBranchSummaryEntry | KodaXSessionLabelEntry | KodaXSessionArchiveMarkerEntry;
86
+ interface KodaXSessionArtifactLedgerEntry {
87
+ id: string;
88
+ kind: 'file_read' | 'file_modified' | 'file_created' | 'file_deleted' | 'path_scope' | 'search_scope' | 'command_scope' | 'check_result' | 'decision' | 'image_input' | 'tombstone';
89
+ sourceTool?: string;
90
+ action?: string;
91
+ target: string;
92
+ displayTarget?: string;
93
+ summary?: string;
94
+ sessionEntryId?: string;
95
+ timestamp: string;
96
+ metadata?: Record<string, KodaXJsonValue>;
97
+ }
98
+ interface KodaXCompactMemoryProgress {
99
+ completed: string[];
100
+ inProgress: string[];
101
+ blockers: string[];
102
+ }
103
+ interface KodaXCompactMemorySeed {
104
+ objective?: string;
105
+ constraints: string[];
106
+ progress: KodaXCompactMemoryProgress;
107
+ keyDecisions: string[];
108
+ nextSteps: string[];
109
+ keyContext: string[];
110
+ importantTargets: string[];
111
+ tombstones: string[];
112
+ }
113
+ interface KodaXSessionLineage {
114
+ version: 2;
115
+ activeEntryId: string | null;
116
+ entries: KodaXSessionEntry[];
117
+ }
118
+ interface KodaXSessionNavigationOptions {
119
+ summarizeCurrentBranch?: boolean;
120
+ }
121
+ interface KodaXSessionTreeNode {
122
+ entry: Exclude<KodaXSessionEntry, KodaXSessionLabelEntry>;
123
+ children: KodaXSessionTreeNode[];
124
+ label?: string;
125
+ active: boolean;
126
+ }
127
+ type KodaXSessionScope = 'user' | 'managed-task-worker';
128
+ type KodaXSessionUiHistoryItemType = 'user' | 'assistant' | 'system' | 'thinking' | 'error' | 'event' | 'info' | 'hint';
129
+ interface KodaXSessionUiHistoryItem {
130
+ type: KodaXSessionUiHistoryItemType;
131
+ text: string;
132
+ icon?: string;
133
+ compactText?: string;
134
+ }
135
+ type KodaXSessionWorkspaceKind = 'detected' | 'managed';
136
+ interface KodaXSessionRuntimeInfo {
137
+ canonicalRepoRoot?: string;
138
+ workspaceRoot?: string;
139
+ executionCwd?: string;
140
+ branch?: string;
141
+ workspaceKind?: KodaXSessionWorkspaceKind;
142
+ }
143
+ interface KodaXSessionData {
144
+ messages: KodaXMessage[];
145
+ title: string;
146
+ gitRoot: string;
147
+ runtimeInfo?: KodaXSessionRuntimeInfo;
148
+ scope?: KodaXSessionScope;
149
+ uiHistory?: KodaXSessionUiHistoryItem[];
150
+ errorMetadata?: SessionErrorMetadata;
151
+ extensionState?: KodaXExtensionSessionState;
152
+ extensionRecords?: KodaXExtensionSessionRecord[];
153
+ lineage?: KodaXSessionLineage;
154
+ artifactLedger?: KodaXSessionArtifactLedgerEntry[];
155
+ }
156
+ interface KodaXSessionMeta {
157
+ _type: 'meta';
158
+ title: string;
159
+ id: string;
160
+ gitRoot: string;
161
+ runtimeInfo?: KodaXSessionRuntimeInfo;
162
+ createdAt: string;
163
+ scope?: KodaXSessionScope;
164
+ uiHistory?: KodaXSessionUiHistoryItem[];
165
+ extensionState?: KodaXExtensionSessionState;
166
+ extensionRecordCount?: number;
167
+ artifactLedgerCount?: number;
168
+ lineageVersion?: 2;
169
+ activeEntryId?: string | null;
170
+ lineageEntryCount?: number;
171
+ activeMessageCount?: number;
172
+ /** Error metadata for recovery - 错误元数据用于恢复 */
173
+ errorMetadata?: SessionErrorMetadata;
174
+ }
175
+ /**
176
+ * Extension-scoped persistence entry.
177
+ *
178
+ * Each entry belongs to a namespace (extensionId) and carries
179
+ * a string key, a JSON-safe value, and an opaque version tag
180
+ * used for optimistic concurrency control.
181
+ */
182
+ interface KodaXExtensionStoreEntry {
183
+ key: string;
184
+ value: KodaXJsonValue;
185
+ version: string;
186
+ updatedAt: number;
187
+ }
188
+ /**
189
+ * Extension persistence store interface (FEATURE_034 manual persistence).
190
+ *
191
+ * Implementations provide a durable key-value store scoped to a single
192
+ * extension identity. The store is independent of session lifecycle —
193
+ * data survives across sessions and restarts.
194
+ */
195
+ interface KodaXExtensionStore {
196
+ /**
197
+ * Read a single key.
198
+ * Returns `undefined` when the key does not exist.
199
+ */
200
+ get(key: string): Promise<KodaXExtensionStoreEntry | undefined>;
201
+ /**
202
+ * Write a key-value pair.
203
+ *
204
+ * When `expectedVersion` is provided the write only succeeds when the
205
+ * stored entry's version still matches (optimistic concurrency).
206
+ * Returns the new entry on success, or `false` on version mismatch.
207
+ */
208
+ put(key: string, value: KodaXJsonValue, options?: {
209
+ expectedVersion?: string;
210
+ }): Promise<KodaXExtensionStoreEntry | false>;
211
+ /**
212
+ * Remove a key.
213
+ * Returns `true` when the key existed and was removed.
214
+ */
215
+ delete(key: string): Promise<boolean>;
216
+ /**
217
+ * List all keys (optionally filtered by prefix).
218
+ */
219
+ list(options?: {
220
+ prefix?: string;
221
+ }): Promise<string[]>;
222
+ /**
223
+ * Clear all keys (optionally filtered by prefix).
224
+ * Returns the number of entries removed.
225
+ */
226
+ clear(options?: {
227
+ prefix?: string;
228
+ }): Promise<number>;
229
+ }
230
+ interface KodaXSessionStorage {
231
+ save(id: string, data: KodaXSessionData): Promise<void>;
232
+ load(id: string): Promise<KodaXSessionData | null>;
233
+ getLineage?(id: string): Promise<KodaXSessionLineage | null>;
234
+ setActiveEntry?(id: string, selector: string, options?: KodaXSessionNavigationOptions): Promise<KodaXSessionData | null>;
235
+ setLabel?(id: string, selector: string, label?: string): Promise<KodaXSessionData | null>;
236
+ rewind?(id: string, selector?: string): Promise<KodaXSessionData | null>;
237
+ fork?(id: string, selector?: string, options?: {
238
+ sessionId?: string;
239
+ title?: string;
240
+ }): Promise<{
241
+ sessionId: string;
242
+ data: KodaXSessionData;
243
+ } | null>;
244
+ list?(gitRoot?: string): Promise<Array<{
245
+ id: string;
246
+ title: string;
247
+ msgCount: number;
248
+ runtimeInfo?: KodaXSessionRuntimeInfo;
249
+ }>>;
250
+ delete?(id: string): Promise<void>;
251
+ deleteAll?(gitRoot?: string): Promise<void>;
252
+ }
253
+
254
+ /**
255
+ * Layer A Primitive: Agent / Handoff / Guardrail / AgentReasoningProfile
256
+ *
257
+ * FEATURE_080 (v0.7.23): Agent-as-data types. Declarative dataclass shape.
258
+ * The runtime counterpart is `Runner` in `./runner.ts`.
259
+ *
260
+ * History: extracted to `@kodax-ai/core` in FEATURE_082 (v0.7.24); merged back
261
+ * into `@kodax-ai/agent` in v0.7.35.1 FEATURE_142 (single-consumer rule —
262
+ * @kodax-ai/core had only @kodax-ai/coding as consumer). `@kodax-ai/coding` retains
263
+ * a barrel re-export for batteries-included consumers.
264
+ *
265
+ * Status: @experimental — API shape may be refined during v0.7.x. Used by
266
+ * the task-engine rewrite in FEATURE_084 (v0.7.26).
267
+ *
268
+ * Guardrail and AgentReasoningProfile are declared here but their runtime
269
+ * behavior is deferred:
270
+ * - Guardrail runtime → FEATURE_085 (v0.7.26)
271
+ * - AgentReasoningProfile behavior → FEATURE_078 (v0.7.29)
272
+ */
273
+
274
+ /**
275
+ * Reasoning depth / mode selector. Alias for `KodaXReasoningMode` to keep the
276
+ * Layer A surface independent of the `KodaX*` brand; unified during the prefix
277
+ * cleanup in FEATURE_086 (v0.7.27).
278
+ */
279
+ type ReasoningDepth = KodaXReasoningMode;
280
+ /**
281
+ * Tool binding accepted by an `Agent`. Layer A treats tools as opaque
282
+ * definitions; the executor lives in `@kodax-ai/coding` and is wired up by the
283
+ * Runner when it dispatches through `runKodaX`.
284
+ */
285
+ type AgentTool = KodaXToolDefinition;
286
+ /**
287
+ * Transport-level message reused from the AI layer. Kept as an alias so
288
+ * consumers of the Layer A primitives do not need to import from `@kodax-ai/llm`
289
+ * directly.
290
+ */
291
+ type AgentMessage = KodaXMessage;
292
+ /**
293
+ * Declarative reasoning profile attached to an Agent.
294
+ *
295
+ * In v0.7.23 this is a placeholder shape — only the `default` depth is read
296
+ * when the Runner dispatches to `runKodaX`. Escalation on revise/replan and
297
+ * max clamping are implemented in FEATURE_078 (v0.7.29).
298
+ */
299
+ interface AgentReasoningProfile {
300
+ readonly default: ReasoningDepth;
301
+ readonly max?: ReasoningDepth;
302
+ readonly escalateOnRevise?: boolean;
303
+ }
304
+ /**
305
+ * Declarative middleware reference attached to an Agent.
306
+ *
307
+ * FEATURE_100 (v0.7.29) introduces this field so the coding preset
308
+ * can declare the four substrate middlewares (auto-reroute,
309
+ * mutation-reflection, pre-answer-judge, post-tool-judge) on the
310
+ * Agent declaration itself. Today these middlewares fire inside
311
+ * the substrate body; the declaration field serves as the
312
+ * machine-readable contract that the substrate honours, and lets
313
+ * SDK consumers introspect / override middleware policy without
314
+ * touching `runKodaX` internals.
315
+ *
316
+ * `enabled` is the only knob today; future versions add config
317
+ * payload as additional fields (kept declarative — no fn callbacks).
318
+ */
319
+ interface AgentMiddlewareDeclaration {
320
+ readonly name: string;
321
+ readonly enabled: boolean;
322
+ }
323
+ /**
324
+ * Guardrail placeholder. Layer A declares the slot; the actual
325
+ * input/output/tool-call gating runtime lives in FEATURE_085 (v0.7.26).
326
+ *
327
+ * A guardrail targets one of three hook points:
328
+ * - `input`: inspect / veto prompts before they enter the agent loop.
329
+ * - `output`: inspect / rewrite assistant messages before they leave.
330
+ * - `tool`: inspect / veto tool invocations during the loop.
331
+ */
332
+ interface Guardrail {
333
+ readonly kind: 'input' | 'output' | 'tool';
334
+ readonly name: string;
335
+ }
336
+ /**
337
+ * Handoff between Agents.
338
+ *
339
+ * - `continuation`: ownership of the conversation transfers to `target` and
340
+ * the caller exits. Mirrors the Scout → Generator upgrade path.
341
+ * - `as-tool`: `target` is invoked like a tool from within the caller loop;
342
+ * only the generated input is passed, and control returns on completion.
343
+ * Mirrors FEATURE_067 `dispatch_child_task`.
344
+ *
345
+ * `inputFilter` is applied to the visible history before the target runs;
346
+ * default is no filtering.
347
+ */
348
+ interface Handoff<TTo = unknown> {
349
+ readonly target: Agent<TTo>;
350
+ readonly kind: 'continuation' | 'as-tool';
351
+ readonly description?: string;
352
+ readonly inputFilter?: (history: readonly AgentMessage[]) => readonly AgentMessage[];
353
+ }
354
+ /**
355
+ * Agent-as-data. A declarative specification of "who is running, with which
356
+ * instructions, tools, handoffs, and reasoning profile."
357
+ *
358
+ * Runtime note: in v0.7.23 the only Agent that is fully executed is the
359
+ * built-in coding preset (`createDefaultCodingAgent()`), which dispatches
360
+ * through `runKodaX`. Custom Agents defined by SDK consumers run through a
361
+ * generic Runner loop with limited capabilities (LLM call + Agent-declared
362
+ * tools only — no extensions, no managed-task harness). The full runtime
363
+ * arrives with FEATURE_084 (v0.7.26).
364
+ */
365
+ interface Agent<TContext = unknown> {
366
+ readonly name: string;
367
+ readonly instructions: string | ((ctx: TContext) => string);
368
+ readonly tools?: readonly AgentTool[];
369
+ readonly handoffs?: readonly Handoff[];
370
+ readonly reasoning?: AgentReasoningProfile;
371
+ readonly guardrails?: readonly Guardrail[];
372
+ /** Reserved for structured-output agents; not consumed in v0.7.23. */
373
+ readonly outputSchema?: unknown;
374
+ readonly model?: string;
375
+ readonly provider?: string;
376
+ /**
377
+ * FEATURE_100 (v0.7.29) substrate executor: when set, `Runner.run`
378
+ * delegates execution to this function instead of consulting the
379
+ * preset-dispatcher registry or running the generic LLM loop. The
380
+ * coding preset attaches `runKodaX`'s full execution pipeline here so
381
+ * the SDK surface `Runner.run(createDefaultCodingAgent(), prompt, opts)`
382
+ * directly drives substrate without a `registerPresetDispatcher`
383
+ * indirection (the v0.7.23 "Option Y" facade).
384
+ *
385
+ * Type is intentionally `unknown` to avoid a `core/agent.ts` ↔
386
+ * `core/runner.ts` module cycle. `Runner.run` casts to the
387
+ * `PresetDispatcher` shape declared in `runner.ts` at the call site.
388
+ */
389
+ readonly substrateExecutor?: unknown;
390
+ /**
391
+ * FEATURE_100 (v0.7.29) declarative middleware list. The coding
392
+ * preset declares the four substrate middlewares it ships with
393
+ * (auto-reroute, mutation-reflection, pre-answer-judge,
394
+ * post-tool-judge). Substrate consults this list on entry and
395
+ * skips the corresponding step when `enabled === false`. SDK
396
+ * consumers can introspect or override declared middleware
397
+ * without touching the substrate body.
398
+ */
399
+ readonly middleware?: readonly AgentMiddlewareDeclaration[];
400
+ }
401
+ /**
402
+ * Ergonomic factory. Equivalent to a plain object literal but freezes the
403
+ * shape so tests cannot mutate a shared Agent by accident.
404
+ */
405
+ declare function createAgent<TContext = unknown>(spec: Agent<TContext>): Agent<TContext>;
406
+ /**
407
+ * Ergonomic factory for Handoff.
408
+ */
409
+ declare function createHandoff<TTo = unknown>(spec: Handoff<TTo>): Handoff<TTo>;
410
+
411
+ /**
412
+ * SpanData variants — payload shapes carried by each `Span`.
413
+ *
414
+ * FEATURE_083 (v0.7.24): the Agent-era tracing model uses a discriminated
415
+ * union so consumers (OpenTelemetry adapter, Langfuse adapter, KodaX
416
+ * built-in file processor) can render each span kind with type safety.
417
+ *
418
+ * Variants mirror the semantic events KodaX emits today:
419
+ * - AgentSpanData : one `Runner.run(agent, ...)` round
420
+ * - GenerationSpanData: one provider LLM call
421
+ * - ToolCallSpanData : one tool invocation (including MCP tool)
422
+ * - HandoffSpanData : continuation or as-tool handoff between agents
423
+ * - CompactionSpanData: one compaction pass (token-threshold or lineage)
424
+ * - GuardrailSpanData : one guardrail check at input/output/tool
425
+ * - EvidenceSpanData : repo-intelligence / evidence acquisition
426
+ * - FanoutSpanData : parallel fanout bracket (winner-cancel capable)
427
+ *
428
+ * API surface is `@experimental` until v0.8.0 — shape may be refined as
429
+ * FEATURE_084 (v0.7.26) starts emitting these.
430
+ */
431
+ interface AgentSpanData {
432
+ readonly kind: 'agent';
433
+ readonly agentName: string;
434
+ readonly model?: string;
435
+ readonly provider?: string;
436
+ readonly tools?: readonly string[];
437
+ readonly handoffs?: readonly string[];
438
+ readonly outputMessages?: number;
439
+ readonly error?: string;
440
+ }
441
+ interface GenerationSpanData {
442
+ readonly kind: 'generation';
443
+ readonly agentName: string;
444
+ readonly provider: string;
445
+ readonly model: string;
446
+ readonly inputMessages?: number;
447
+ readonly outputTokens?: number;
448
+ readonly inputTokens?: number;
449
+ readonly reasoningTokens?: number;
450
+ readonly cachedTokens?: number;
451
+ readonly usage?: {
452
+ readonly inputTokens?: number;
453
+ readonly outputTokens?: number;
454
+ readonly totalTokens?: number;
455
+ readonly reasoningTokens?: number;
456
+ readonly cachedTokens?: number;
457
+ readonly costUsd?: number;
458
+ };
459
+ readonly finishReason?: string;
460
+ readonly error?: string;
461
+ }
462
+ interface ToolCallSpanData {
463
+ readonly kind: 'tool_call';
464
+ readonly toolName: string;
465
+ readonly providerId?: string;
466
+ readonly capabilityId?: string;
467
+ readonly inputPreview?: string;
468
+ readonly outputPreview?: string;
469
+ readonly status: 'ok' | 'error';
470
+ readonly error?: string;
471
+ }
472
+ interface HandoffSpanData {
473
+ readonly kind: 'handoff';
474
+ readonly fromAgent: string;
475
+ readonly toAgent: string;
476
+ readonly handoffKind: 'continuation' | 'as-tool';
477
+ readonly description?: string;
478
+ }
479
+ interface CompactionSpanData {
480
+ readonly kind: 'compaction';
481
+ readonly policyName: string;
482
+ readonly tokensUsed: number;
483
+ readonly budget: number;
484
+ readonly replacedMessageCount: number;
485
+ readonly summaryLength: number;
486
+ readonly error?: string;
487
+ }
488
+ interface GuardrailSpanData {
489
+ readonly kind: 'guardrail';
490
+ readonly guardrailName: string;
491
+ readonly hookPoint: 'input' | 'output' | 'tool';
492
+ readonly decision: 'pass' | 'veto' | 'rewrite' | 'error';
493
+ readonly reason?: string;
494
+ readonly error?: string;
495
+ }
496
+ interface EvidenceSpanData {
497
+ readonly kind: 'evidence';
498
+ readonly source: string;
499
+ readonly queryPreview?: string;
500
+ readonly resultCount?: number;
501
+ readonly cacheHit?: boolean;
502
+ readonly error?: string;
503
+ }
504
+ interface FanoutSpanData {
505
+ readonly kind: 'fanout';
506
+ readonly agentName: string;
507
+ readonly childCount: number;
508
+ readonly winnerChildId?: string;
509
+ readonly cancelledChildIds?: readonly string[];
510
+ }
511
+ /**
512
+ * Discriminated union of all span payload shapes. Additional variants may
513
+ * be added in future features — consumers should check `kind` before
514
+ * reading specific fields.
515
+ */
516
+ type SpanData = AgentSpanData | GenerationSpanData | ToolCallSpanData | HandoffSpanData | CompactionSpanData | GuardrailSpanData | EvidenceSpanData | FanoutSpanData;
517
+
518
+ /**
519
+ * Span — a single timed unit of work inside a Trace.
520
+ *
521
+ * FEATURE_083 (v0.7.24): minimal Span implementation modeled after the
522
+ * openai-agents-python Trace/Span pattern.
523
+ *
524
+ * Design constraints:
525
+ * - Span creation must be cheap (no await, no serialisation). Processors
526
+ * do their own batching / flushing.
527
+ * - `addChild()` is synchronous and immediately visible in the Trace tree.
528
+ * - `end()` is idempotent; calling it twice is a no-op.
529
+ * - `error` is an optional field that sets a flag on the span without
530
+ * throwing. The consumer decides how to surface errors.
531
+ */
532
+
533
+ interface SpanError {
534
+ readonly message: string;
535
+ readonly stack?: string;
536
+ readonly data?: unknown;
537
+ }
538
+ /**
539
+ * Public Span interface. Concrete implementation is `SpanImpl`.
540
+ */
541
+ interface Span {
542
+ readonly id: string;
543
+ readonly traceId: string;
544
+ readonly parentId?: string;
545
+ readonly name: string;
546
+ readonly data: SpanData;
547
+ readonly startedAt: number;
548
+ readonly endedAt?: number;
549
+ readonly error?: SpanError;
550
+ readonly children: readonly Span[];
551
+ addChild(name: string, data: SpanData): Span;
552
+ setError(err: SpanError | Error): void;
553
+ end(): void;
554
+ }
555
+
556
+ /**
557
+ * Runner Tool Loop — FEATURE_084 Shard 1 (v0.7.26).
558
+ *
559
+ * Extends the Layer A Runner generic-dispatch path with tool-call support.
560
+ * Before Shard 1 the Runner could only do a single `system+user → assistant`
561
+ * turn. Now the injected LLM callback may return a structured result that
562
+ * declares tool calls; the Runner executes them, appends tool_use +
563
+ * tool_result content blocks, and loops until the LLM stops emitting tool
564
+ * calls (or MAX_TOOL_LOOP_ITERATIONS is reached).
565
+ *
566
+ * This Shard only lands the capability. No built-in Agent consumes it yet —
567
+ * the coding preset (SA path) continues to dispatch through
568
+ * `registerPresetDispatcher` unchanged.
569
+ *
570
+ * @experimental Shape may be refined during the v0.7.26 shard rollout.
571
+ */
572
+
573
+ /**
574
+ * Hard ceiling on tool-loop iterations. A single run may invoke at most this
575
+ * many LLM turns (counting the initial turn); if the model keeps returning
576
+ * tool calls past this limit we abort to prevent runaway behaviour.
577
+ */
578
+ declare const MAX_TOOL_LOOP_ITERATIONS = 20;
579
+ /**
580
+ * One tool invocation requested by the LLM.
581
+ */
582
+ interface RunnerToolCall {
583
+ readonly id: string;
584
+ readonly name: string;
585
+ readonly input: Record<string, unknown>;
586
+ }
587
+ /**
588
+ * Structured LLM result. Returning this instead of a plain string lets the
589
+ * Runner drive a tool loop. If `toolCalls` is empty or omitted the loop
590
+ * terminates and `text` becomes the final output.
591
+ */
592
+ interface RunnerLlmResult {
593
+ readonly text: string;
594
+ readonly toolCalls?: readonly RunnerToolCall[];
595
+ readonly stopReason?: string;
596
+ /**
597
+ * v0.7.26 parity: extended-thinking blocks from the provider stream.
598
+ * Must be preserved on the assistant message so (a) session resume can
599
+ * re-render them and (b) Anthropic's extended-thinking API contract is
600
+ * honoured — provider rejects the next turn with a 400 when a tool_use
601
+ * turn's `thinking` block is missing from prior assistant history.
602
+ */
603
+ readonly thinkingBlocks?: readonly (KodaXThinkingBlock | KodaXRedactedThinkingBlock)[];
604
+ }
605
+ /**
606
+ * LLM callback return type. `string` preserves the v0.7.23 single-turn
607
+ * behaviour; `RunnerLlmResult` opts into the tool loop.
608
+ */
609
+ type RunnerLlmReturn = string | RunnerLlmResult;
610
+ /**
611
+ * Observer callbacks fired around every tool invocation. Preset
612
+ * dispatchers (e.g. the coding Runner-driven path) pass these through
613
+ * `RunOptions.toolObserver` so REPL / CLI consumers see live
614
+ * `onToolCall` / `onToolResult` events, matching the legacy task-engine
615
+ * event surface (v0.7.22 agent.ts fired `events.onToolResult` at three
616
+ * sites per invocation).
617
+ */
618
+ interface RunnerToolObserver {
619
+ /**
620
+ * Permission / policy gate fired BEFORE each tool invocation. Return
621
+ * `true` (or `undefined`) to allow, `false` to block with a generic
622
+ * message, or a `string` to block with that message as the tool result.
623
+ * Used to hook plan-mode / accept-edits / extension `tool:before`
624
+ * policies onto the Runner-driven path (v0.7.22 parity — legacy
625
+ * `events.beforeToolExecute` surface).
626
+ */
627
+ readonly beforeTool?: (call: RunnerToolCall) => Promise<boolean | string | undefined>;
628
+ readonly onToolCall?: (call: RunnerToolCall) => void;
629
+ readonly onToolResult?: (call: RunnerToolCall, result: RunnerToolResult) => void;
630
+ }
631
+ /**
632
+ * Context passed to a RunnableTool's `execute` function.
633
+ */
634
+ interface RunnerToolContext {
635
+ readonly agent: Agent;
636
+ readonly abortSignal?: AbortSignal;
637
+ /** The agent's Span, so tool implementations can nest custom spans if needed. */
638
+ readonly agentSpan?: Span | null;
639
+ /**
640
+ * Current tool_use call id. Passed through so tool wrappers can correlate
641
+ * progress events (`onToolProgress`) and other per-call side-effects with
642
+ * the REPL's tool-block in the transcript. Populated by `executeRunnerToolCall`.
643
+ */
644
+ readonly toolCallId?: string;
645
+ }
646
+ /**
647
+ * Value returned by `RunnableTool.execute`. The `content` string is what the
648
+ * LLM sees in the next turn as `tool_result`.
649
+ */
650
+ interface RunnerToolResult {
651
+ readonly content: string;
652
+ readonly isError?: boolean;
653
+ readonly metadata?: Record<string, unknown>;
654
+ }
655
+ /**
656
+ * A tool bundled with its executor. Extends `AgentTool` (the wire-format
657
+ * `KodaXToolDefinition`) so it can be passed through to the provider
658
+ * unchanged while also carrying a function the Runner can invoke.
659
+ */
660
+ interface RunnableTool extends AgentTool {
661
+ readonly execute: (input: Record<string, unknown>, ctx: RunnerToolContext) => Promise<RunnerToolResult>;
662
+ }
663
+ /**
664
+ * Narrowing helper — distinguishes a `RunnableTool` from a plain
665
+ * `AgentTool`. An agent may declare both: the Runner only executes the
666
+ * tools that carry an `execute` function.
667
+ */
668
+ declare function isRunnableTool(tool: AgentTool): tool is RunnableTool;
669
+ /**
670
+ * Narrowing helper for the LLM callback return shape.
671
+ */
672
+ declare function isRunnerLlmResult(value: unknown): value is RunnerLlmResult;
673
+ /**
674
+ * Execute one tool call against the agent's declared tools. Emits a
675
+ * ToolCallSpan under `ctx.agentSpan` when tracing is active. Returns a
676
+ * `RunnerToolResult` — tool errors do not throw, they are surfaced with
677
+ * `isError: true` so the LLM can see them in the next turn and react.
678
+ */
679
+ declare function executeRunnerToolCall(call: RunnerToolCall, agent: Agent, ctx: RunnerToolContext): Promise<RunnerToolResult>;
680
+ /**
681
+ * Build the assistant message that captures one LLM turn. Preserves
682
+ * thinking blocks (extended-thinking contract), text blocks, and tool_use
683
+ * blocks in the order Anthropic's wire format expects: thinking → text →
684
+ * tool_use. This mirrors v0.7.22 `agent.ts:2230`
685
+ * (`[...thinkingBlocks, ...textBlocks, ...visibleToolBlocks]`) which the
686
+ * Runner-driven path must preserve — without it Anthropic returns 400 on
687
+ * the next turn when extended thinking is active, and session resume
688
+ * loses the reasoning trace.
689
+ */
690
+ declare function buildAssistantMessageFromLlmResult(result: RunnerLlmResult): AgentMessage;
691
+ /**
692
+ * Build the user message that carries tool_result blocks back to the LLM.
693
+ * Provider serializers (Anthropic, OpenAI) both accept tool_result on the
694
+ * user turn.
695
+ */
696
+ declare function buildToolResultMessage(calls: readonly RunnerToolCall[], results: readonly RunnerToolResult[]): AgentMessage;
697
+
698
+ /**
699
+ * Guardrail Runtime — FEATURE_085 (v0.7.26).
700
+ *
701
+ * Three-tier runtime for Agent guardrails:
702
+ *
703
+ * - `InputGuardrail`: runs once before the first LLM turn, inspects the
704
+ * full input transcript, may allow / rewrite / block / escalate.
705
+ * - `OutputGuardrail`: runs once before returning, inspects the final
706
+ * assistant message, may allow / rewrite / block / escalate.
707
+ * - `ToolGuardrail`: runs before and/or after each tool invocation,
708
+ * inspects the call / result, may allow / rewrite / block / escalate.
709
+ *
710
+ * The four verdict actions:
711
+ *
712
+ * - `allow`: continue with the current value.
713
+ * - `rewrite`: replace the current value with `payload`.
714
+ * - `block`: throw `GuardrailBlockedError` (for input/output) or surface
715
+ * an error tool_result (for tool-before); the LLM / caller sees a
716
+ * rejection and must adapt.
717
+ * - `escalate`: throw `GuardrailEscalateError`; the SDK consumer catches
718
+ * and decides whether to prompt the user, retry under different
719
+ * constraints, etc.
720
+ *
721
+ * Every guardrail invocation emits a `GuardrailSpan` under the agent's
722
+ * span when tracing is active.
723
+ *
724
+ * @experimental API shape may adjust during v0.7.x rollout.
725
+ */
726
+
727
+ /**
728
+ * Shared execution context passed to every guardrail.
729
+ *
730
+ * `messages` is the live conversation transcript at the moment this
731
+ * guardrail fires. For tool-side guardrails this is the transcript at
732
+ * call-site time — it does NOT yet include the assistant turn that
733
+ * emitted the current tool_use, since that turn is appended only after
734
+ * the full tool batch settles. Optional so existing guardrails that
735
+ * don't read context still type-check; populated by the Runner for all
736
+ * production hook points.
737
+ *
738
+ * Added in FEATURE_092 (v0.7.33) so the auto-mode classifier guardrail
739
+ * can extract intent context (user prompt + prior tool_use / tool_result
740
+ * blocks) without reaching into Runner internals.
741
+ */
742
+ interface GuardrailContext {
743
+ readonly agent: Agent;
744
+ readonly abortSignal?: AbortSignal;
745
+ readonly messages?: readonly AgentMessage[];
746
+ }
747
+ /**
748
+ * Outcome of a single guardrail check. `payload` shape depends on the hook
749
+ * point — see the specific guardrail interface for the expected type.
750
+ */
751
+ type GuardrailVerdict = {
752
+ readonly action: 'allow';
753
+ } | {
754
+ readonly action: 'rewrite';
755
+ readonly payload: unknown;
756
+ readonly reason?: string;
757
+ } | {
758
+ readonly action: 'block';
759
+ readonly reason: string;
760
+ } | {
761
+ readonly action: 'escalate';
762
+ readonly reason: string;
763
+ };
764
+ /**
765
+ * Input-side guardrail. Expected `rewrite` payload shape:
766
+ * `readonly AgentMessage[]` — the replacement transcript.
767
+ */
768
+ interface InputGuardrail extends Guardrail {
769
+ readonly kind: 'input';
770
+ check(input: readonly AgentMessage[], ctx: GuardrailContext): Promise<GuardrailVerdict>;
771
+ }
772
+ /**
773
+ * Output-side guardrail. Expected `rewrite` payload shape:
774
+ * `AgentMessage` — the replacement final assistant message.
775
+ */
776
+ interface OutputGuardrail extends Guardrail {
777
+ readonly kind: 'output';
778
+ check(output: AgentMessage, ctx: GuardrailContext): Promise<GuardrailVerdict>;
779
+ }
780
+ /**
781
+ * Tool-side guardrail. `beforeTool` rewrite payload shape: `RunnerToolCall`
782
+ * (replacement call). `afterTool` rewrite payload shape: `RunnerToolResult`
783
+ * (replacement result). Either hook is optional.
784
+ */
785
+ interface ToolGuardrail extends Guardrail {
786
+ readonly kind: 'tool';
787
+ beforeTool?(call: RunnerToolCall, ctx: GuardrailContext): Promise<GuardrailVerdict>;
788
+ afterTool?(call: RunnerToolCall, result: RunnerToolResult, ctx: GuardrailContext): Promise<GuardrailVerdict>;
789
+ }
790
+ /**
791
+ * Thrown when any guardrail returns `{ action: 'block' }`. The Runner
792
+ * propagates this up to the caller — the run is aborted at that point.
793
+ */
794
+ declare class GuardrailBlockedError extends Error {
795
+ readonly guardrailName: string;
796
+ readonly hookPoint: 'input' | 'output' | 'tool';
797
+ constructor(guardrailName: string, hookPoint: 'input' | 'output' | 'tool', reason: string);
798
+ }
799
+ /**
800
+ * Thrown when any guardrail returns `{ action: 'escalate' }`. Callers can
801
+ * catch and prompt the user or apply a stricter policy before retrying.
802
+ */
803
+ declare class GuardrailEscalateError extends Error {
804
+ readonly guardrailName: string;
805
+ readonly hookPoint: 'input' | 'output' | 'tool';
806
+ constructor(guardrailName: string, hookPoint: 'input' | 'output' | 'tool', reason: string);
807
+ }
808
+ /** Filter a guardrail list by hook-point. */
809
+ declare function collectGuardrails(guardrails: readonly Guardrail[] | undefined): {
810
+ input: readonly InputGuardrail[];
811
+ output: readonly OutputGuardrail[];
812
+ tool: readonly ToolGuardrail[];
813
+ };
814
+ /**
815
+ * Run all input guardrails in declaration order. Returns the (possibly
816
+ * rewritten) transcript. Throws on block / escalate.
817
+ */
818
+ declare function runInputGuardrails(transcript: readonly AgentMessage[], guardrails: readonly InputGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<readonly AgentMessage[]>;
819
+ /**
820
+ * Run all output guardrails in declaration order. Returns the (possibly
821
+ * rewritten) final assistant message. Throws on block / escalate.
822
+ */
823
+ declare function runOutputGuardrails(output: AgentMessage, guardrails: readonly OutputGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<AgentMessage>;
824
+ /**
825
+ * Outcome of the before-tool guardrail stage.
826
+ * - `{ kind: 'allow', call }`: continue to executeRunnerToolCall with `call`
827
+ * - `{ kind: 'block', result }`: skip execution; return `result` as the
828
+ * tool_result to the LLM (so it sees the rejection and can adapt)
829
+ */
830
+ type ToolBeforeOutcome = {
831
+ readonly kind: 'allow';
832
+ readonly call: RunnerToolCall;
833
+ } | {
834
+ readonly kind: 'block';
835
+ readonly result: RunnerToolResult;
836
+ };
837
+ /**
838
+ * Run before-tool guardrails in declaration order. Rewrite replaces the
839
+ * tool call. Block surfaces an error tool_result to the LLM instead of
840
+ * throwing — the LLM sees the rejection and adapts. Escalate still throws.
841
+ */
842
+ declare function runToolBeforeGuardrails(call: RunnerToolCall, guardrails: readonly ToolGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<ToolBeforeOutcome>;
843
+ /**
844
+ * Run after-tool guardrails in declaration order. Rewrite replaces the
845
+ * result content. Block replaces with an error result. Escalate throws.
846
+ */
847
+ declare function runToolAfterGuardrails(call: RunnerToolCall, result: RunnerToolResult, guardrails: readonly ToolGuardrail[], ctx: GuardrailContext, agentSpan: Span | null): Promise<RunnerToolResult>;
848
+
849
+ /**
850
+ * Child task registry primitive — generic fan-out tracking.
851
+ *
852
+ * FEATURE_120 v0.7.39 Step 0 (package-attribution migration, ADR-021).
853
+ * Lifted from `@kodax-ai/coding`'s `KodaXToolExecutionContext.childTaskRegistry`
854
+ * field + inline cleanup chain in `tools/dispatch-child-tasks.ts`. The
855
+ * coding side now consumes this primitive specialized to its
856
+ * `KodaXChildExecutionResult` type; any other agent-flavor downstream
857
+ * can specialize on its own child-result type without re-implementing
858
+ * the cleanup contract.
859
+ *
860
+ * The shape is intentionally minimal: a Map plus a `register` helper
861
+ * that bundles the v0.7.38 FEATURE_155 Bug A hotfix (`c1bdaf4e`)
862
+ * cleanup chain into a single call site. The helper exists because
863
+ * the cleanup is **not optional** — without it, every settled promise
864
+ * stays in the registry forever, gets re-wrapped by the next
865
+ * idle-yield `waitForWakeEvent` call, and fires spurious
866
+ * `child-completed` wakes (production symptom: Evaluator gets
867
+ * bombarded by duplicate `<task-completed>` notifications, consuming
868
+ * an LLM turn each up to `IDLE_YIELD_MAX_ITERATIONS=64`).
869
+ */
870
+ /**
871
+ * Map of `task_id` → in-flight child-execution promise. Generic over
872
+ * the child-result type so the agent layer doesn't depend on any
873
+ * specific agent flavor's result shape.
874
+ *
875
+ * Mutation contract:
876
+ * - Owned by the runner's per-turn execution context. The dispatch
877
+ * tool writes via `registerChildTask`; the idle-yield outer loop
878
+ * reads via `Map.prototype.entries()` / `.size`.
879
+ * - **Never delete entries manually** — call `registerChildTask`
880
+ * and the cleanup chain it installs will run on settle.
881
+ */
882
+ type ChildTaskRegistry<T> = Map<string, Promise<T>>;
883
+ /**
884
+ * Register an in-flight child-execution promise in the registry and
885
+ * install the cleanup chain that removes the entry once the promise
886
+ * settles (success or failure).
887
+ *
888
+ * The cleanup chain is two stages:
889
+ * 1. `.finally(() => registry.delete(childId))` — runs on settle
890
+ * regardless of outcome, removing the entry before the next
891
+ * idle-yield outer-loop iteration observes the registry.
892
+ * 2. `.catch(() => {})` — swallows the rejection on the cleanup
893
+ * chain so a child that crashes before any consumer awaits it
894
+ * doesn't surface as `unhandledRejection` on Node. Must come
895
+ * AFTER `.finally` because `.finally` returns a NEW promise
896
+ * that rejects with the same reason.
897
+ *
898
+ * The original `promise` argument is **not** returned — the helper's
899
+ * value-add is the cleanup side-effect, not promise transformation.
900
+ * Callers that need to await the result read from `registry.get(id)`
901
+ * or hold their own reference.
902
+ *
903
+ * @throws Error when `childId` already exists in the registry. Caller
904
+ * should report this to the LLM as a tool-error (duplicate task_id);
905
+ * the helper does NOT swallow the conflict because that would
906
+ * silently overwrite an in-flight child's tracking entry.
907
+ */
908
+ declare function registerChildTask<T>(registry: ChildTaskRegistry<T>, childId: string, promise: Promise<T>): void;
909
+
910
+ /**
911
+ * Generic per-task abort primitive — `requestTaskStop`.
912
+ *
913
+ * FEATURE_120 v0.7.39 Phase 3a (ADR-021). Coordinator-style agents need
914
+ * to request that a specific in-flight child task exit gracefully. The
915
+ * @kodax-ai/agent layer owns the abort-controller registry shape and
916
+ * the abort-dispatch decision; agent-flavor wrappers (e.g. the coding
917
+ * `task_stop` tool, Phase 3b) layer in domain framing such as the
918
+ * `<coordinator-stop-request>` message tag.
919
+ *
920
+ * What this primitive owns:
921
+ * - A `TaskAbortRegistry` type alias = `Map<string, AbortController>`.
922
+ * The map is owned + mutated by the caller; the primitive only
923
+ * reads it. Callers use `registry.set(id, controller)` /
924
+ * `registry.delete(id)` directly — the standard `Map` mutators
925
+ * are simple enough that wrapping them adds no value.
926
+ * - `requestTaskStop({taskId, registry, reason?})` — looks up the
927
+ * controller, decides whether to abort, calls `controller.abort`,
928
+ * returns a structured outcome.
929
+ *
930
+ * Abort semantics (matches the existing FEATURE_115 soft-pause
931
+ * principle): aborting fires the signal but does NOT interrupt any
932
+ * synchronous tool that's already executing. The child's next abort
933
+ * check (`signal.throwIfAborted()` or an `signal.aborted` poll)
934
+ * surfaces the abort. This matches Node's AbortController contract.
935
+ *
936
+ * What this primitive does NOT do (deliberate):
937
+ * - Enqueue a coordinator-stop-request message — that's a
938
+ * coding-flavor convenience and uses the existing
939
+ * `routeMessage` primitive at the tool layer.
940
+ * - Track abort lifecycle / auto-cleanup the registry — the
941
+ * controller's lifetime is tied to its owning task's Promise;
942
+ * the caller removes the registry entry when the task settles
943
+ * (typically in a `.finally` chain alongside the child-task
944
+ * registry cleanup).
945
+ * - Time-out enforcement / retry — orthogonal concerns owned at
946
+ * higher layers if needed.
947
+ */
948
+ /**
949
+ * Registry mapping task ids to their owning AbortController.
950
+ * Lifetime: created per parent-run, populated at child dispatch,
951
+ * cleared when the child Promise settles.
952
+ */
953
+ type TaskAbortRegistry = Map<string, AbortController>;
954
+ interface RequestTaskStopOptions {
955
+ /** Target task id. Must exist as a key in `registry`. */
956
+ readonly taskId: string;
957
+ /** Registry of in-flight task abort controllers. */
958
+ readonly registry: ReadonlyMap<string, AbortController>;
959
+ /**
960
+ * Optional cause forwarded to `AbortController.abort(reason)`.
961
+ * - Error → passed through verbatim (preserves stack / custom
962
+ * subclasses).
963
+ * - string → wrapped in `new Error(reason)`.
964
+ * - undefined → a default Error mentioning the taskId is
965
+ * fabricated so the child receives a non-empty signal.reason.
966
+ */
967
+ readonly reason?: string | Error;
968
+ }
969
+ type RequestTaskStopResult = {
970
+ readonly ok: true;
971
+ readonly taskId: string;
972
+ } | {
973
+ readonly ok: false;
974
+ readonly reason: 'unknown-target';
975
+ readonly taskId: string;
976
+ } | {
977
+ readonly ok: false;
978
+ readonly reason: 'already-aborted';
979
+ readonly taskId: string;
980
+ };
981
+ /**
982
+ * Look up `taskId` in `registry`. If found and not yet aborted, abort
983
+ * the controller with the supplied reason. Returns a discriminated
984
+ * outcome so callers can render success / error UX without string
985
+ * matching.
986
+ *
987
+ * `already-aborted` is reported separately from success because the
988
+ * first-abort `signal.reason` is preserved verbatim — debugging
989
+ * chains depend on the original cause not being overwritten by
990
+ * subsequent stop requests.
991
+ *
992
+ * Synchronous: `AbortController.abort` is synchronous; no async work
993
+ * is performed by this primitive.
994
+ */
995
+ declare function requestTaskStop(opts: RequestTaskStopOptions): RequestTaskStopResult;
996
+
997
+ /**
998
+ * FEATURE_125 (v0.7.41) — Team Mode Layer 1: per-instance state broadcast.
999
+ *
1000
+ * Each running KodaX session registers a directory under
1001
+ * `<agentConfigHome>/instances/<pid>/` containing three files:
1002
+ *
1003
+ * meta.json — written once at registration; cwd / startedAt /
1004
+ * optional git branch + remote. Static for the session.
1005
+ * state.json — re-written whenever the session's `currentIntent`,
1006
+ * `agentPhase`, or active/recently-modified file set
1007
+ * changes. Read by sibling sessions for context.
1008
+ * heartbeat — empty file whose mtime is touched on every refresh.
1009
+ * Sibling sessions use the mtime to declare an instance
1010
+ * stale (default 30s of no heartbeat → cleanup).
1011
+ *
1012
+ * Atomic write strategy:
1013
+ * - state.json is written via `<path>.tmp` + `rename()`. On POSIX the
1014
+ * rename is atomic; on Windows it is atomic when source + target sit
1015
+ * on the same filesystem (always true for `<agentConfigHome>/...`).
1016
+ * - heartbeat is touched via `utimesSync()`. Cheap, no rename needed.
1017
+ *
1018
+ * Lifecycle:
1019
+ * - `createStateWriter` writes meta.json + state.json + heartbeat once,
1020
+ * then starts an interval timer (default 1000ms) that refreshes
1021
+ * state.json and touches heartbeat.
1022
+ * - `update(patch)` shallow-merges the patch into the in-memory state
1023
+ * and flushes immediately so peer sessions see the change at the
1024
+ * next tool boundary, not at the next heartbeat tick.
1025
+ * - `shutdown()` clears the timer, removes the instance directory,
1026
+ * and resolves. Idempotent — safe to call multiple times.
1027
+ *
1028
+ * Crash recovery:
1029
+ * - If a process is killed mid-run, the directory is left on disk.
1030
+ * The next session's discovery scan (S2, `instance-discovery.ts`)
1031
+ * detects the stale heartbeat and removes the directory.
1032
+ *
1033
+ * DI-clean: every fs / clock dependency is injectable for hermetic tests.
1034
+ */
1035
+ /**
1036
+ * Live session state surfaced to sibling KodaX sessions. Mirrors the
1037
+ * shape documented in `docs/features/v0.7.41.md#feature_125-step-1`.
1038
+ */
1039
+ interface SessionStateSnapshot {
1040
+ readonly agentPhase: 'idle' | 'awaiting_llm' | 'running_tool';
1041
+ /** Single-line description of what the agent is currently doing. */
1042
+ readonly currentIntent?: string;
1043
+ /** Files the session is actively editing right now. */
1044
+ readonly activeFiles?: readonly string[];
1045
+ /** Files modified in the recent past (sibling sessions read this to detect "their content may be stale"). */
1046
+ readonly recentlyModifiedFiles?: readonly RecentlyModifiedFile[];
1047
+ /**
1048
+ * FEATURE_170 (v0.7.41) — optional one-line summary of the active
1049
+ * todo list. Lets sibling sessions display "they're currently
1050
+ * working on: <X>" without owning the todo store.
1051
+ */
1052
+ readonly currentTodoSummary?: CurrentTodoSummary;
1053
+ }
1054
+ interface RecentlyModifiedFile {
1055
+ readonly path: string;
1056
+ readonly modifiedAt: number;
1057
+ }
1058
+ interface CurrentTodoSummary {
1059
+ readonly inProgress?: string;
1060
+ readonly pendingCount: number;
1061
+ readonly completedCount: number;
1062
+ }
1063
+ interface SessionMeta {
1064
+ readonly cwd: string;
1065
+ readonly startedAt: number;
1066
+ readonly gitBranch?: string;
1067
+ readonly gitRemote?: string;
1068
+ }
1069
+ /**
1070
+ * Stored shape of `state.json` on disk — additive over SessionStateSnapshot.
1071
+ *
1072
+ * Reader contract (S2 `instance-discovery.ts`): parse the JSON, verify
1073
+ * `version === '1'` before reading any other field. On an unknown
1074
+ * version, log + skip the instance — this lets a newer writer coexist
1075
+ * with an older reader during an in-place upgrade.
1076
+ *
1077
+ * Fields are camelCase + a nested `meta` object (cwd / startedAt /
1078
+ * gitBranch / gitRemote). Do NOT assume the snake_case / flat shape
1079
+ * shown in early design-doc drafts — the typed interface here is the
1080
+ * ground truth; the doc has been updated to match.
1081
+ */
1082
+ interface PersistedSessionState extends SessionStateSnapshot {
1083
+ readonly version: '1';
1084
+ readonly pid: number;
1085
+ readonly updatedAt: number;
1086
+ readonly meta: SessionMeta;
1087
+ }
1088
+ /** Minimal injectable fs surface — lets tests drive the writer without disk I/O. */
1089
+ interface StateWriterFs {
1090
+ mkdirSync(dirPath: string, options: {
1091
+ recursive: true;
1092
+ }): void;
1093
+ writeFileSync(filePath: string, data: string): void;
1094
+ /** Atomic write helper: writes to `${filePath}.tmp` then renames. */
1095
+ atomicWriteSync(filePath: string, data: string): void;
1096
+ utimesSync(filePath: string, atime: number, mtime: number): void;
1097
+ rmSync(dirPath: string, options: {
1098
+ recursive: true;
1099
+ force: true;
1100
+ }): void;
1101
+ existsSync(targetPath: string): boolean;
1102
+ }
1103
+ interface StateWriterOptions {
1104
+ /** Defaults to `process.pid`. Tests / multi-instance fixtures override. */
1105
+ readonly pid?: number;
1106
+ readonly meta: SessionMeta;
1107
+ readonly initialState: SessionStateSnapshot;
1108
+ /** Defaults to 1000ms. Tests pass a faster tick. */
1109
+ readonly heartbeatIntervalMs?: number;
1110
+ /** Defaults to `Date.now`. Tests inject a controllable clock. */
1111
+ readonly clock?: () => number;
1112
+ /** Defaults to {@link REAL_FS}. Tests inject an in-memory fs. */
1113
+ readonly fs?: StateWriterFs;
1114
+ /**
1115
+ * Root directory under which `<pid>/` is created. Defaults to
1116
+ * `getAgentConfigPath('instances')`. Tests can point at a temp dir.
1117
+ */
1118
+ readonly instancesRoot?: string;
1119
+ }
1120
+ interface StateWriter {
1121
+ readonly pid: number;
1122
+ readonly instanceDir: string;
1123
+ /** Apply a partial update to the in-memory state and flush to disk. */
1124
+ update(patch: Partial<SessionStateSnapshot>): void;
1125
+ /** Touch the heartbeat and re-write state.json without changing state. */
1126
+ refresh(): void;
1127
+ /** Stop the interval, remove the instance directory, resolve when done. */
1128
+ shutdown(): Promise<void>;
1129
+ /** Read-only snapshot of the current state. Useful for tests. */
1130
+ getState(): SessionStateSnapshot;
1131
+ }
1132
+ /**
1133
+ * Construct a writer, register the instance directory, and start the
1134
+ * heartbeat interval. Returns synchronously so the caller can rely on
1135
+ * `instanceDir` being live the moment the function returns.
1136
+ */
1137
+ declare function createStateWriter(options: StateWriterOptions): StateWriter;
1138
+
1139
+ /**
1140
+ * FEATURE_125 (v0.7.41) — Team Mode Layer 2a: sibling instance discovery.
1141
+ *
1142
+ * Scans `<agentConfigHome>/instances/`, filters out the caller's own
1143
+ * pid, drops any directory whose `heartbeat` file is stale (>30s of no
1144
+ * touch), parses `state.json`, validates `version === '1'`, and returns
1145
+ * a typed list of live sibling instances. Stale directories are
1146
+ * optionally reaped (`reapStale: true`) — the next session entering
1147
+ * Team Mode does the cleanup so crashed processes don't accumulate
1148
+ * forever.
1149
+ *
1150
+ * Per-instance failures (corrupt JSON, vanished file mid-read, permission
1151
+ * error) are isolated: the bad directory is logged + skipped, the rest
1152
+ * of the scan completes. Discovery NEVER throws to its caller — a
1153
+ * Team-Mode-disabled return is `[]`, not an exception. This keeps the
1154
+ * worker LLM call path resilient to one peer session's bad state.
1155
+ *
1156
+ * DI-clean: every fs / clock / logger dependency is injectable so
1157
+ * hermetic tests can simulate stale / corrupt / mid-scan-deletion
1158
+ * scenarios without real disk.
1159
+ */
1160
+
1161
+ /** A sibling KodaX session that passed stale + version-guard checks. */
1162
+ interface DiscoveredInstance {
1163
+ readonly pid: number;
1164
+ readonly state: PersistedSessionState;
1165
+ /** Heartbeat mtime in ms (epoch). Useful for ordering "freshest first". */
1166
+ readonly heartbeatMtimeMs: number;
1167
+ }
1168
+ /** Minimal injectable fs surface used by `discoverInstances`. */
1169
+ interface InstanceDiscoveryFs {
1170
+ existsSync(targetPath: string): boolean;
1171
+ readdirSync(dirPath: string): string[];
1172
+ /** Returns the mtime of the path in ms, or `null` if missing / unreadable. */
1173
+ statMtimeMs(filePath: string): number | null;
1174
+ readFileSync(filePath: string, encoding: 'utf8'): string;
1175
+ rmSync(dirPath: string, options: {
1176
+ recursive: true;
1177
+ force: true;
1178
+ }): void;
1179
+ }
1180
+ interface DiscoveryOptions {
1181
+ /**
1182
+ * pid to exclude from the result. Defaults to `process.pid` — the
1183
+ * caller's own state.json should not appear in its own sibling list.
1184
+ */
1185
+ readonly excludePid?: number;
1186
+ /**
1187
+ * Heartbeat mtime older than `now - staleThresholdMs` → directory is
1188
+ * stale. Default 30_000 (matches v0.7.41 spec).
1189
+ */
1190
+ readonly staleThresholdMs?: number;
1191
+ /**
1192
+ * When true, stale directories are removed during the scan (best-
1193
+ * effort `rmSync(force:true)`; failure is swallowed). When false,
1194
+ * stale directories are skipped but left on disk. Defaults to false
1195
+ * — wire from the session-startup path with `true` so crashed-process
1196
+ * dirs don't accumulate.
1197
+ */
1198
+ readonly reapStale?: boolean;
1199
+ readonly clock?: () => number;
1200
+ readonly fs?: InstanceDiscoveryFs;
1201
+ readonly instancesRoot?: string;
1202
+ /** Per-instance failure log; defaults to a no-op. Pass `console.warn` in dev. */
1203
+ readonly logger?: (message: string) => void;
1204
+ }
1205
+ /**
1206
+ * Synchronous discovery scan. Returns a freshness-sorted array
1207
+ * (newest heartbeat first) so callers that want only the N most-recent
1208
+ * siblings can slice without re-sorting.
1209
+ *
1210
+ * Never throws. A missing `<instancesRoot>` directory means the user
1211
+ * is the first session ever on this machine → `[]`. A scan failure on
1212
+ * one entry is logged + skipped, not propagated.
1213
+ */
1214
+ declare function discoverInstances(options?: DiscoveryOptions): DiscoveredInstance[];
1215
+
1216
+ export { MAX_TOOL_LOOP_ITERATIONS as R, buildAssistantMessageFromLlmResult as af, buildToolResultMessage as ag, collectGuardrails as ah, createAgent as ai, createHandoff as aj, createStateWriter as ak, discoverInstances as al, executeRunnerToolCall as am, isRunnableTool as an, isRunnerLlmResult as ao, registerChildTask as ap, requestTaskStop as aq, runInputGuardrails as ar, runOutputGuardrails as as, runToolAfterGuardrails as at, runToolBeforeGuardrails as au, GuardrailBlockedError as g, GuardrailEscalateError as i };
1217
+ export type { RunnerToolCall as $, Agent as A, KodaXSessionMessageEntry as B, ChildTaskRegistry as C, DiscoveredInstance as D, KodaXSessionMeta as E, KodaXSessionNavigationOptions as F, Guardrail as G, Handoff as H, InputGuardrail as I, KodaXSessionRuntimeInfo as J, KodaXCompactMemoryProgress as K, KodaXSessionScope as L, KodaXSessionStorage as M, KodaXSessionTreeNode as N, KodaXSessionUiHistoryItem as O, KodaXSessionUiHistoryItemType as P, KodaXSessionWorkspaceKind as Q, OutputGuardrail as S, PersistedSessionState as T, ReasoningDepth as U, RecentlyModifiedFile as V, RequestTaskStopOptions as W, RequestTaskStopResult as X, RunnableTool as Y, RunnerLlmResult as Z, RunnerLlmReturn as _, AgentMessage as a, RunnerToolContext as a0, RunnerToolObserver as a1, RunnerToolResult as a2, SessionErrorMetadata as a3, SessionMeta as a4, SessionStateSnapshot as a5, Span as a6, SpanData as a7, SpanError as a8, StateWriter as a9, StateWriterFs as aa, StateWriterOptions as ab, TaskAbortRegistry as ac, ToolBeforeOutcome as ad, ToolGuardrail as ae, AgentMiddlewareDeclaration as b, AgentReasoningProfile as c, AgentTool as d, CurrentTodoSummary as e, DiscoveryOptions as f, GuardrailContext as h, GuardrailVerdict as j, InstanceDiscoveryFs as k, KodaXCompactMemorySeed as l, KodaXExtensionSessionRecord as m, KodaXExtensionSessionState as n, KodaXExtensionStore as o, KodaXExtensionStoreEntry as p, KodaXJsonValue as q, KodaXSessionArchiveMarkerEntry as r, KodaXSessionArtifactLedgerEntry as s, KodaXSessionBranchSummaryEntry as t, KodaXSessionCompactionEntry as u, KodaXSessionData as v, KodaXSessionEntry as w, KodaXSessionEntryBase as x, KodaXSessionLabelEntry as y, KodaXSessionLineage as z };