@rowan-agent/agent 0.4.4

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.
@@ -0,0 +1,2049 @@
1
+ import { AgentContextMessage, AgentContextSkill, LlmModelRef, LlmModelUsage, ToolCall, ToolResult, Outcome, LlmToolChoice, ContentBlock, LlmRequest, ProviderConfig, StreamFn, AgentEventListener, AgentEvent, LlmMessage } from '@rowan-agent/models';
2
+ export { AgentEvent, AgentEventListener, LlmModelRef, Outcome, StreamFn, ToolResult } from '@rowan-agent/models';
3
+ import Type from 'typebox';
4
+
5
+ type AgentRunLimits = {
6
+ /** Maximum number of phase iterations before forcing stop. Default: 50. */
7
+ maxIterations?: number;
8
+ /** Maximum consecutive "continue" rounds within a single phase before forcing transition. Default: 10. */
9
+ maxPhaseRounds?: number;
10
+ };
11
+ type LoopMetrics = {
12
+ /** Number of phase iterations executed. */
13
+ iterations: number;
14
+ /** Phase transition history. */
15
+ phaseTransitions: Array<{
16
+ from: string;
17
+ to: string;
18
+ ts: string;
19
+ }>;
20
+ /** Number of times compaction was triggered. */
21
+ compactionCount: number;
22
+ /** Number of retry attempts due to transient errors. */
23
+ retryCount: number;
24
+ /** Loop start timestamp. */
25
+ startedAt: string;
26
+ /** Loop start time as epoch ms (for duration calculation). */
27
+ startedAtMs: number;
28
+ /** Loop end timestamp (set on completion). */
29
+ endedAt?: string;
30
+ /** Total wall-clock duration in ms. */
31
+ durationMs?: number;
32
+ };
33
+ type AgentRunState = {
34
+ agentState: AgentState;
35
+ currentPhase: string;
36
+ attempt: number;
37
+ transcript: AgentMessage$1[];
38
+ /** Loop execution metrics. */
39
+ metrics: LoopMetrics;
40
+ };
41
+
42
+ type AgentContextState = {
43
+ version: string;
44
+ id: string;
45
+ parentSessionId?: string;
46
+ systemPrompt: string;
47
+ input: string;
48
+ messages: AgentContextMessage[];
49
+ skills: AgentContextSkill[];
50
+ createdAt: string;
51
+ updatedAt: string;
52
+ title?: string;
53
+ };
54
+ /** Unified phase output — model decides routing via route. */
55
+ type PhaseOutput = {
56
+ message: string;
57
+ /** Route to next phase, or "continue" to re-execute current phase, or "stop" to end */
58
+ route: string;
59
+ /** Tool calls from the model invocation (used by framework for route extraction) */
60
+ toolCalls?: Array<{
61
+ id: string;
62
+ name: string;
63
+ args: unknown;
64
+ }>;
65
+ /** Route reason extracted from route tool call (for hooks to inspect) */
66
+ routeReason?: string;
67
+ };
68
+
69
+ type LoopPhase = "chat" | "plan" | "execute" | "verify";
70
+
71
+ type ExecutionTurnEntry = {
72
+ kind: "prompt";
73
+ message: Pick<AgentContextMessage, "role" | "content">;
74
+ } | {
75
+ kind: "assistant_text";
76
+ text: string;
77
+ } | {
78
+ kind: "tool_call";
79
+ toolCall: ToolCall;
80
+ } | {
81
+ kind: "tool_result";
82
+ result: ToolResult;
83
+ };
84
+ type ExecutionTurn = {
85
+ id: string;
86
+ sessionId: string;
87
+ parentSessionId?: string;
88
+ phase: LoopPhase;
89
+ requestedAtMs: number;
90
+ completedAtMs: number;
91
+ model: LlmModelRef;
92
+ usage?: LlmModelUsage;
93
+ entries: ExecutionTurnEntry[];
94
+ };
95
+ type StepFilter = {
96
+ phase?: LoopPhase;
97
+ afterMs?: number;
98
+ };
99
+
100
+ declare const AGENT_STATE_SCHEMA_VERSION = "0.4.4";
101
+ type AgentMessage$1 = AgentContextMessage;
102
+ type Skill$1 = AgentContextSkill;
103
+ type AgentState = {
104
+ version: string;
105
+ id: string;
106
+ parentSessionId?: string;
107
+ systemPrompt: string;
108
+ input: string;
109
+ messages: AgentMessage$1[];
110
+ skills: Skill$1[];
111
+ createdAt: string;
112
+ updatedAt: string;
113
+ title?: string;
114
+ };
115
+ type CreateAgentStateInput = {
116
+ id?: string;
117
+ systemPrompt: string;
118
+ input: string;
119
+ skills?: Skill$1[];
120
+ parentSessionId?: string;
121
+ title?: string;
122
+ messages?: AgentMessage$1[];
123
+ };
124
+ type ToolContext$1 = {
125
+ state: AgentState;
126
+ toolCallId: string;
127
+ };
128
+ type ToolExecutionMode$1 = "sequential" | "parallel";
129
+ type Tool$1<TArgs = unknown> = {
130
+ name: string;
131
+ description: string;
132
+ parameters: Type.TSchema;
133
+ /** One-line snippet shown in the system prompt tool list. */
134
+ promptSnippet?: string;
135
+ /** Additional guidelines appended to the system prompt when this tool is active. */
136
+ promptGuidelines?: string[];
137
+ /** Whether this tool can run concurrently with others. Default: "parallel". */
138
+ executionMode?: ToolExecutionMode$1;
139
+ execute(args: TArgs, context: ToolContext$1, signal?: AbortSignal): Promise<ToolResult>;
140
+ };
141
+ /** Context snapshot passed into the low-level agent loop. */
142
+ type AgentContext = {
143
+ /** System prompt included with the request. */
144
+ systemPrompt: string;
145
+ /** Transcript visible to the model. */
146
+ messages: AgentMessage$1[];
147
+ /** Tools available for this run. */
148
+ tools?: Tool$1[];
149
+ /** Skills available for this run. */
150
+ skills?: Skill$1[];
151
+ };
152
+ type BeforeToolCall = (input: {
153
+ tool: Tool$1;
154
+ args: unknown;
155
+ }) => Promise<{
156
+ allow: true;
157
+ } | {
158
+ allow: false;
159
+ reason: string;
160
+ }>;
161
+ type AfterToolCall = (input: {
162
+ tool: Tool$1;
163
+ result: ToolResult;
164
+ }) => Promise<ToolResult>;
165
+ type RunResult = {
166
+ sessionId: string;
167
+ messages: AgentMessage$1[];
168
+ outcome: Outcome;
169
+ metrics: LoopMetrics;
170
+ };
171
+ type Unsubscribe = () => void;
172
+ declare function createMessage(role: AgentMessage$1["role"], content: string, metadata?: Record<string, unknown>): AgentMessage$1;
173
+ declare function createAgentState(input: CreateAgentStateInput): AgentState;
174
+
175
+ declare function createId(prefix: string): string;
176
+ declare function createTimestamp(date?: Date): string;
177
+ declare const createJson: {
178
+ "new"<T>(value: T): T;
179
+ stringify(value: unknown): string;
180
+ };
181
+
182
+ /** Unified phase input — contains everything the model needs. */
183
+ type PhaseInput = {
184
+ phase: string;
185
+ systemPrompt: string;
186
+ messages: AgentMessage$1[];
187
+ /** All tools (for systemPrompt display, cache-friendly) */
188
+ tools: Tool$1[];
189
+ /** All skills (for systemPrompt display) */
190
+ skills: Skill$1[];
191
+ /** Phase-specific filtered tools (for LlmRequest.tools) */
192
+ phaseTools?: Tool$1[];
193
+ /** Phase-specific filtered skills */
194
+ phaseSkills?: Skill$1[];
195
+ /** Additional guideline bullets appended to the system prompt. */
196
+ promptGuidelines?: string[];
197
+ /** Text to append after the system prompt. */
198
+ appendSystemPrompt?: string;
199
+ /** Tool choice configuration from phase definition */
200
+ toolChoice?: LlmToolChoice;
201
+ };
202
+ type PhaseManifest = {
203
+ id: string;
204
+ name: string;
205
+ description: string;
206
+ /** Tools available in this phase. If omitted, all tools are available. */
207
+ tools?: string[];
208
+ /** Skills available in this phase. If omitted, all skills are available. */
209
+ skills?: string[];
210
+ };
211
+ type PhaseRun = (context: PhaseContext, input: PhaseInput) => Promise<PhaseOutput | void>;
212
+ type PhaseDefinition = PhaseManifest & {
213
+ run?: PhaseRun;
214
+ buildPrompt?(input: PhaseInput): LlmRequest;
215
+ };
216
+ type ModelInvokeOutput = {
217
+ text: string;
218
+ contentBlocks: ContentBlock[];
219
+ toolCalls: ToolCall[];
220
+ stopReason?: string;
221
+ };
222
+ type ModelInvokeInput = {
223
+ input: PhaseInput;
224
+ /** Auto-execute tools and record results to message history */
225
+ autoExecuteTools?: boolean;
226
+ /** Max tool execution rounds (default: 10) */
227
+ maxToolRounds?: number;
228
+ /** Tool names to exclude from auto-execution (e.g. ["route"]) */
229
+ excludeTools?: string[];
230
+ };
231
+ /** Message lifecycle manager for streaming updates */
232
+ /** Snapshot of message state, used for restore */
233
+ type MessageSnapshot = {
234
+ transcriptLength: number;
235
+ stateMessagesLength: number;
236
+ };
237
+ type PhaseMessageManager = {
238
+ /** Get all visible messages in the transcript */
239
+ visible(): AgentMessage$1[];
240
+ /** Start a new message stream, returns message id */
241
+ start(role: "assistant" | "tool", content: string, metadata?: Record<string, unknown>): string;
242
+ /** Stream a text delta */
243
+ update(messageId: string, delta: string): Promise<void>;
244
+ /** End the message stream, appends to transcript */
245
+ end(messageId: string): Promise<void>;
246
+ /** Delete a single message by id or index */
247
+ delete(target: string | number): void;
248
+ /** Insert a message before a target (by id or index) */
249
+ insert(target: string | number, message: AgentMessage$1): void;
250
+ /** Clear all messages from transcript and state */
251
+ clear(): void;
252
+ /** Capture current message state for later restore */
253
+ snapshot(): MessageSnapshot;
254
+ /** Restore message state to a previous snapshot, discarding messages added after it */
255
+ restore(snap: MessageSnapshot): void;
256
+ };
257
+ /** Tool execution lifecycle manager */
258
+ type PhaseToolExecutionManager = {
259
+ /** Start tool execution */
260
+ start(toolCallId: string, toolName: string, args: unknown): Promise<void>;
261
+ /** Update tool execution progress */
262
+ update(toolCallId: string, partialResult: unknown): Promise<void>;
263
+ /** End tool execution */
264
+ end(toolCallId: string, toolName: string, result: ToolResult, isError: boolean): Promise<void>;
265
+ };
266
+ type PhaseContext = {
267
+ phaseId: string;
268
+ state: AgentRunState;
269
+ messages: PhaseMessageManager;
270
+ toolExecution: PhaseToolExecutionManager;
271
+ model: {
272
+ invoke(input: ModelInvokeInput): Promise<ModelInvokeOutput>;
273
+ };
274
+ tools: {
275
+ execute(input: {
276
+ toolCall: ToolCall;
277
+ }): Promise<ToolResult>;
278
+ };
279
+ skills: AgentState["skills"];
280
+ turn<T>(fn: () => Promise<T>): Promise<T>;
281
+ maxAttempts?: number;
282
+ incrementAttempt(): void;
283
+ availablePhases: Array<{
284
+ id: string;
285
+ name: string;
286
+ description: string;
287
+ }>;
288
+ /** Extract route decision from tool calls. Returns undefined if no route tool call found. */
289
+ routeDecision(toolCalls: ToolCall[]): {
290
+ route: string;
291
+ reason?: string;
292
+ } | undefined;
293
+ };
294
+ type PhaseRegistry = {
295
+ entryPhaseId: string;
296
+ phases: PhaseDefinition[];
297
+ };
298
+ type PhaseRegistryInput = {
299
+ entryPhaseId?: string;
300
+ phases?: PhaseDefinition[];
301
+ };
302
+ declare function definePhase(definition: PhaseDefinition): PhaseDefinition;
303
+ declare function createPhaseRegistry(input: PhaseRegistryInput): PhaseRegistry;
304
+ declare const DEFAULT_PHASE_ID: string;
305
+
306
+ /**
307
+ * Source info — tracks where an extension registration came from.
308
+ */
309
+ interface SourceInfo {
310
+ /** Source type: "local" for filesystem, "builtin" for built-in, etc. */
311
+ source: string;
312
+ /** Base directory for resolving relative paths. */
313
+ baseDir?: string;
314
+ /** Display name for error messages. */
315
+ displayName?: string;
316
+ }
317
+ declare function createSourceInfo(extensionPath: string, options?: {
318
+ source?: string;
319
+ baseDir?: string;
320
+ }): SourceInfo;
321
+
322
+ /**
323
+ * Extension types — simplified for the new hook-based system.
324
+ */
325
+
326
+ /** Declarative prompt configuration — alternative to implementing buildPrompt. */
327
+ type PhasePromptConfig = {
328
+ /** Lines to append as a user message with phase instructions. */
329
+ instructions?: string[];
330
+ };
331
+ type PhaseRegistration = Partial<PhaseManifest> & {
332
+ /** Optional execution override — takes over model invocation */
333
+ run?: PhaseRun;
334
+ /** Declarative prompt config — framework generates buildPrompt from this */
335
+ prompt?: PhasePromptConfig;
336
+ /** Custom prompt builder — overrides prompt config if provided */
337
+ buildPrompt?: (input: PhaseInput) => LlmRequest;
338
+ };
339
+ type RegisteredPhase = {
340
+ definition: PhaseDefinition;
341
+ handler: {
342
+ buildPrompt?: (input: PhaseInput) => LlmRequest;
343
+ };
344
+ source: {
345
+ extensionPath: string;
346
+ };
347
+ };
348
+ type ExtensionPackageManifest = {
349
+ rowan?: {
350
+ extensions?: string[];
351
+ phase?: PhaseManifest;
352
+ };
353
+ };
354
+ /**
355
+ * Tool definition for registering LLM-callable tools via `api.registerTool()`.
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * api.registerTool({
360
+ * name: "search_docs",
361
+ * description: "Search documentation",
362
+ * parameters: { type: "object", properties: { query: { type: "string" } } },
363
+ * execute: async (args, ctx) => {
364
+ * return { content: [{ type: "text", text: "result" }] };
365
+ * },
366
+ * });
367
+ * ```
368
+ */
369
+ interface ToolDefinition {
370
+ /** Tool name (used in LLM tool calls) */
371
+ name: string;
372
+ /** Description for LLM */
373
+ description: string;
374
+ /** Parameter schema (JSON Schema) */
375
+ parameters: Record<string, unknown>;
376
+ /** Execute the tool */
377
+ execute: (args: unknown, signal?: AbortSignal) => Promise<ToolExecutionResult>;
378
+ /** Optional: per-tool execution mode override */
379
+ executionMode?: "sequential" | "parallel";
380
+ }
381
+ /**
382
+ * Result from tool execution.
383
+ */
384
+ interface ToolExecutionResult {
385
+ /** Content blocks to return to the LLM */
386
+ content: Array<{
387
+ type: string;
388
+ text?: string;
389
+ [key: string]: unknown;
390
+ }>;
391
+ /** Whether this is an error result */
392
+ isError?: boolean;
393
+ }
394
+ /**
395
+ * Registered tool with source metadata.
396
+ */
397
+ interface RegisteredTool {
398
+ definition: ToolDefinition;
399
+ sourceInfo: SourceInfo;
400
+ }
401
+ /**
402
+ * Structured extension error with attribution.
403
+ */
404
+ interface ExtensionError {
405
+ /** Path of the extension that caused the error */
406
+ extensionPath: string;
407
+ /** Event or operation that caused the error */
408
+ event: string;
409
+ /** Error message */
410
+ error: string;
411
+ /** Optional stack trace */
412
+ stack?: string;
413
+ }
414
+ /** Error listener callback type. */
415
+ type ExtensionErrorListener = (error: ExtensionError) => void;
416
+ type ExecOptions = {
417
+ /** Working directory for the command. Defaults to cwd passed to runtime. */
418
+ cwd?: string;
419
+ /** Environment variables to add/override. */
420
+ env?: Record<string, string>;
421
+ /** Timeout in milliseconds. */
422
+ timeout?: number;
423
+ /** AbortSignal for cancellation. */
424
+ signal?: AbortSignal;
425
+ };
426
+ type ExecResult = {
427
+ exitCode: number;
428
+ stdout: string;
429
+ stderr: string;
430
+ };
431
+ type BeforePhaseHookResult = {
432
+ abort?: Outcome;
433
+ skip?: {
434
+ route: string;
435
+ message: string;
436
+ };
437
+ input?: PhaseInput;
438
+ };
439
+ type AfterPhaseHookResult = {
440
+ abort?: Outcome;
441
+ retry?: PhaseInput;
442
+ output?: PhaseOutput;
443
+ };
444
+ type HandlerFn = (...args: unknown[]) => Promise<unknown>;
445
+ /**
446
+ * Loaded extension with all registered items.
447
+ * Tracks what each extension registered for attribution and cleanup.
448
+ */
449
+ interface Extension {
450
+ /** Extension path (may be synthetic like `<builtin:phase:chat>`) */
451
+ path: string;
452
+ /** Resolved absolute path */
453
+ resolvedPath: string;
454
+ /** Source info for error messages */
455
+ sourceInfo: SourceInfo;
456
+ /** Event handlers registered by this extension */
457
+ handlers: Map<string, HandlerFn[]>;
458
+ /** Tools registered by this extension */
459
+ tools: Map<string, RegisteredTool>;
460
+ /** Phases registered by this extension */
461
+ phases: Map<string, RegisteredPhase>;
462
+ }
463
+ /**
464
+ * Create an Extension object with empty collections.
465
+ */
466
+ declare function createExtension(extensionPath: string, resolvedPath: string, sourceInfo: SourceInfo): Extension;
467
+ /**
468
+ * Shared runtime state created by loader, used during registration and runtime.
469
+ * All ExtensionAPI instances reference this shared state.
470
+ *
471
+ * Key features:
472
+ * - `invalidate()` / `assertActive()` — prevents stale context usage
473
+ * - Pending provider registration queue
474
+ * - Shared action implementations replaceable post-bind
475
+ */
476
+ interface ExtensionRuntime {
477
+ /** Throws when this extension instance is stale after runtime replacement. */
478
+ assertActive: () => void;
479
+ /** Marks this extension instance as stale after runtime replacement or reload. */
480
+ invalidate: (message?: string) => void;
481
+ /** Provider registrations queued during extension loading, processed when runner binds */
482
+ pendingProviderRegistrations: Array<{
483
+ name: string;
484
+ config: ProviderConfig;
485
+ extensionPath: string;
486
+ }>;
487
+ /**
488
+ * Register a provider.
489
+ * Before bind(): queues registrations.
490
+ * After bind(): calls provider registration directly.
491
+ */
492
+ registerProvider: (name: string, config: ProviderConfig, extensionPath?: string) => void;
493
+ /**
494
+ * Unregister a provider.
495
+ * Before bind(): removes from queue.
496
+ * After bind(): calls provider unregistration directly.
497
+ */
498
+ unregisterProvider: (name: string, extensionPath?: string) => void;
499
+ }
500
+ /**
501
+ * Create an ExtensionRuntime with throwing stubs.
502
+ * Runner.bind() replaces these with real implementations.
503
+ */
504
+ declare function createExtensionRuntime(): ExtensionRuntime;
505
+ /**
506
+ * Result of loading extensions from filesystem.
507
+ * The runner takes these and creates Extension tracking objects.
508
+ */
509
+ type LoadExtensionsResult = {
510
+ extensions: LoadedExtension[];
511
+ errors: Array<{
512
+ path: string;
513
+ error: string;
514
+ }>;
515
+ };
516
+ /**
517
+ * Pre-initialization extension form — factory + metadata.
518
+ * Runner.loadExtensions() calls the factory and creates the full Extension object.
519
+ */
520
+ interface LoadedExtension {
521
+ path: string;
522
+ resolvedPath: string;
523
+ name: string;
524
+ factory: (api: any) => void | Promise<void>;
525
+ manifest?: ExtensionManifest;
526
+ }
527
+ /** Extension manifest from package.json `rowan` field. */
528
+ interface ExtensionManifest {
529
+ entry?: string;
530
+ name?: string;
531
+ phase?: {
532
+ id?: string;
533
+ name?: string;
534
+ description?: string;
535
+ tools?: string[];
536
+ skills?: string[];
537
+ };
538
+ }
539
+
540
+ /**
541
+ * EventBus — simple pub/sub for inter-extension communication.
542
+ *
543
+ * Extensions can emit and subscribe to arbitrary events via `api.events`.
544
+ * This allows extensions to coordinate without direct coupling.
545
+ *
546
+ * @example
547
+ * ```typescript
548
+ * // Extension A
549
+ * api.events.on("my-plugin:ready", (data) => {
550
+ * console.log("Plugin ready:", data);
551
+ * });
552
+ *
553
+ * // Extension B
554
+ * api.events.emit("my-plugin:ready", { version: "1.0" });
555
+ * ```
556
+ */
557
+ type Listener = (...args: unknown[]) => void;
558
+ interface EventBus {
559
+ /** Subscribe to an event. Returns unsubscribe function. */
560
+ on(event: string, listener: Listener): () => void;
561
+ /** Emit an event to all subscribers. */
562
+ emit(event: string, ...args: unknown[]): void;
563
+ /** Remove all listeners for an event, or all listeners if no event specified. */
564
+ off(event?: string): void;
565
+ /** Check if there are listeners for an event. */
566
+ has(event: string): boolean;
567
+ /** Get listener count for an event. */
568
+ count(event: string): number;
569
+ }
570
+ declare function createEventBus(): EventBus;
571
+
572
+ /**
573
+ * @module extensions/hooks
574
+ *
575
+ * Type-safe hook system
576
+ *
577
+ * ## Overview
578
+ *
579
+ * The hook system allows extensions to intercept and modify Agent behavior at specific points.
580
+ *
581
+ * ## Hook Categories
582
+ *
583
+ * ### Modifiable (return result to change behavior)
584
+ *
585
+ * | Hook | Return | Effect |
586
+ * |------|--------|--------|
587
+ * | `before_phase` | `{ abort?, skip?, input? }` | Abort, skip, or modify phase input |
588
+ * | `after_phase` | `{ abort?, retry?, output? }` | Abort, retry, or replace phase output |
589
+ * | `before_prompt` | `{ input? }` | Modify input sent to LLM |
590
+ * | `before_tool_call` | `{ allow, reason? }` | Allow/block tool execution |
591
+ * | `after_tool_call` | `{ result? }` | Modify tool execution result |
592
+ *
593
+ * ### Listen-only (return void)
594
+ *
595
+ * | Hook | Trigger |
596
+ * |------|---------|
597
+ * | `agent_start` | Agent starts |
598
+ * | `agent_end` | Agent ends |
599
+ * | `turn_start` | Conversation turn starts |
600
+ * | `turn_end` | Conversation turn ends |
601
+ * | `message_start` | Message streaming starts |
602
+ * | `message_update` | Message streaming update |
603
+ * | `message_end` | Message completes |
604
+ * | `tool_execution_start` | Tool execution starts |
605
+ * | `tool_execution_update` | Tool execution progress update |
606
+ * | `tool_execution_end` | Tool execution completes |
607
+ * | `queue_update` | Queue state update |
608
+ * | `save_point` | Session save point |
609
+ * | `abort` | Agent aborted |
610
+ * | `settled` | Agent idle |
611
+ *
612
+ * ## Usage Example
613
+ *
614
+ * ```typescript
615
+ * import type { ExtensionAPI } from "@rowan-agent/agent";
616
+ *
617
+ * export default function(api: ExtensionAPI) {
618
+ * // Block dangerous tools
619
+ * api.on("before_tool_call", (event) => {
620
+ * if (event.tool.name === "bash") {
621
+ * const cmd = (event.args as any).command;
622
+ * if (cmd.includes("rm -rf")) {
623
+ * return { allow: false, reason: "Dangerous command" };
624
+ * }
625
+ * }
626
+ * return { allow: true };
627
+ * });
628
+ *
629
+ * // Inject context
630
+ * api.on("before_prompt", (event) => {
631
+ * return {
632
+ * input: {
633
+ * ...event.input,
634
+ * systemPrompt: event.input.systemPrompt + "\n\nExtra context",
635
+ * },
636
+ * };
637
+ * });
638
+ *
639
+ * // Log tool calls
640
+ * api.on("tool_execution_end", (event) => {
641
+ * console.log(`Tool ${event.toolName}: ${event.result.ok ? "success" : "failed"}`);
642
+ * });
643
+ * }
644
+ * ```
645
+ */
646
+
647
+ /**
648
+ * before_phase event - triggered before phase execution
649
+ *
650
+ * Return `{ abort }` to abort the agent.
651
+ * Return `{ skip: { route, message } }` to skip the phase.
652
+ * Return `{ input }` to replace the phase input.
653
+ */
654
+ interface BeforePhaseEvent {
655
+ type: "before_phase";
656
+ /** Phase ID about to execute */
657
+ phaseId: string;
658
+ /** Phase input */
659
+ input: PhaseInput;
660
+ }
661
+ /**
662
+ * after_phase event - triggered after phase execution
663
+ *
664
+ * Return `{ abort }` to abort the agent.
665
+ * Return `{ retry }` to re-execute the phase with new input.
666
+ * Return `{ output }` to replace the phase output.
667
+ */
668
+ interface AfterPhaseEvent {
669
+ type: "after_phase";
670
+ /** Phase ID that completed */
671
+ phaseId: string;
672
+ /** Phase output */
673
+ output: PhaseOutput;
674
+ }
675
+ /**
676
+ * before_prompt event - triggered before building LLM request
677
+ *
678
+ * Return `{ input }` to replace the input sent to LLM.
679
+ */
680
+ interface BeforePromptEvent {
681
+ type: "before_prompt";
682
+ /** Current phase ID */
683
+ phaseId: string;
684
+ /** Phase input (modifiable) */
685
+ input: PhaseInput;
686
+ }
687
+ /**
688
+ * before_tool_call event - triggered before tool execution
689
+ *
690
+ * Return `{ allow: false, reason }` to block execution.
691
+ * Return `{ allow: true }` to allow execution.
692
+ */
693
+ interface BeforeToolCallEvent {
694
+ type: "before_tool_call";
695
+ /** Tool definition */
696
+ tool: Tool$1;
697
+ /** Tool arguments */
698
+ args: unknown;
699
+ }
700
+ /**
701
+ * after_tool_call event - triggered after tool execution
702
+ *
703
+ * Return `{ result }` to replace the tool execution result.
704
+ */
705
+ interface AfterToolCallEvent {
706
+ type: "after_tool_call";
707
+ /** Tool definition */
708
+ tool: Tool$1;
709
+ /** Tool execution result */
710
+ result: ToolResult;
711
+ }
712
+ /**
713
+ * agent_start event - triggered when agent starts
714
+ */
715
+ interface AgentStartEvent {
716
+ type: "agent_start";
717
+ /** Session ID */
718
+ sessionId: string;
719
+ }
720
+ /**
721
+ * agent_end event - triggered when agent ends
722
+ */
723
+ interface AgentEndEvent {
724
+ type: "agent_end";
725
+ /** Session ID */
726
+ sessionId: string;
727
+ /** Execution outcome */
728
+ outcome: Outcome;
729
+ /** All messages */
730
+ messages: AgentMessage$1[];
731
+ }
732
+ /**
733
+ * turn_start event - triggered when conversation turn starts
734
+ */
735
+ interface TurnStartEvent {
736
+ type: "turn_start";
737
+ /** Current message list */
738
+ messages: AgentMessage$1[];
739
+ }
740
+ /**
741
+ * turn_end event - triggered when conversation turn ends
742
+ */
743
+ interface TurnEndEvent {
744
+ type: "turn_end";
745
+ /** Message list */
746
+ messages: AgentMessage$1[];
747
+ /** Turn outcome (optional) */
748
+ outcome?: Outcome;
749
+ }
750
+ /**
751
+ * message_start event - triggered when message streaming starts
752
+ */
753
+ interface MessageStartEvent {
754
+ type: "message_start";
755
+ /** Message object */
756
+ message: AgentMessage$1;
757
+ }
758
+ /**
759
+ * message_update event - triggered on message streaming update
760
+ */
761
+ interface MessageUpdateEvent {
762
+ type: "message_update";
763
+ /** Message object */
764
+ message: AgentMessage$1;
765
+ /** Delta text */
766
+ delta: string;
767
+ }
768
+ /**
769
+ * message_end event - triggered when message completes
770
+ */
771
+ interface MessageEndEvent {
772
+ type: "message_end";
773
+ /** Message object */
774
+ message: AgentMessage$1;
775
+ }
776
+ /**
777
+ * tool_execution_start event - triggered when tool execution starts
778
+ */
779
+ interface ToolExecutionStartEvent {
780
+ type: "tool_execution_start";
781
+ /** Tool call ID */
782
+ toolCallId: string;
783
+ /** Tool name */
784
+ toolName: string;
785
+ /** Tool arguments */
786
+ args: unknown;
787
+ }
788
+ /**
789
+ * tool_execution_update event - triggered on tool execution progress
790
+ */
791
+ interface ToolExecutionUpdateEvent {
792
+ type: "tool_execution_update";
793
+ /** Tool call ID */
794
+ toolCallId: string;
795
+ /** Tool name */
796
+ toolName: string;
797
+ }
798
+ /**
799
+ * tool_execution_end event - triggered when tool execution completes
800
+ */
801
+ interface ToolExecutionEndEvent {
802
+ type: "tool_execution_end";
803
+ /** Tool call ID */
804
+ toolCallId: string;
805
+ /** Tool name */
806
+ toolName: string;
807
+ /** Tool execution result */
808
+ result: ToolResult;
809
+ }
810
+ /**
811
+ * queue_update event - triggered on queue state update
812
+ */
813
+ interface QueueUpdateEvent {
814
+ type: "queue_update";
815
+ /** Pending message count */
816
+ pendingCount: number;
817
+ }
818
+ /**
819
+ * save_point event - triggered at session save point
820
+ */
821
+ interface SavePointEvent {
822
+ type: "save_point";
823
+ /** Whether there are pending mutations */
824
+ hadPendingMutations: boolean;
825
+ }
826
+ /**
827
+ * abort event - triggered when agent is aborted
828
+ */
829
+ interface AbortEvent {
830
+ type: "abort";
831
+ /** Abort reason */
832
+ reason?: string;
833
+ }
834
+ /**
835
+ * settled event - triggered when agent is idle
836
+ */
837
+ interface SettledEvent {
838
+ type: "settled";
839
+ }
840
+ /** Union type of all hook events */
841
+ type HookEvent = BeforePhaseEvent | AfterPhaseEvent | BeforePromptEvent | BeforeToolCallEvent | AfterToolCallEvent | AgentStartEvent | AgentEndEvent | TurnStartEvent | TurnEndEvent | MessageStartEvent | MessageUpdateEvent | MessageEndEvent | ToolExecutionStartEvent | ToolExecutionUpdateEvent | ToolExecutionEndEvent | QueueUpdateEvent | SavePointEvent | AbortEvent | SettledEvent;
842
+ /**
843
+ * before_phase hook return value
844
+ *
845
+ * - `abort`: Abort the entire agent
846
+ * - `skip`: Skip current phase, route to specified phase
847
+ * - `input`: Replace phase input
848
+ */
849
+ interface BeforePhaseResult {
850
+ /** Abort agent */
851
+ abort?: Outcome;
852
+ /** Skip current phase */
853
+ skip?: {
854
+ route: string;
855
+ message: string;
856
+ };
857
+ /** Replace phase input */
858
+ input?: PhaseInput;
859
+ }
860
+ /**
861
+ * after_phase hook return value
862
+ *
863
+ * - `abort`: Abort the entire agent
864
+ * - `retry`: Re-execute phase with new input
865
+ * - `output`: Replace phase output
866
+ */
867
+ interface AfterPhaseResult {
868
+ /** Abort agent */
869
+ abort?: Outcome;
870
+ /** Re-execute phase */
871
+ retry?: PhaseInput;
872
+ /** Replace phase output */
873
+ output?: PhaseOutput;
874
+ }
875
+ /**
876
+ * before_prompt hook return value
877
+ *
878
+ * - `input`: Replace input sent to LLM
879
+ */
880
+ interface BeforePromptResult {
881
+ /** Replace phase input */
882
+ input?: PhaseInput;
883
+ }
884
+ /**
885
+ * before_tool_call hook return value
886
+ *
887
+ * - `allow`: Whether to allow execution
888
+ * - `reason`: Rejection reason (when allow=false)
889
+ */
890
+ interface BeforeToolCallResult {
891
+ /** Whether to allow execution */
892
+ allow: boolean;
893
+ /** Rejection reason */
894
+ reason?: string;
895
+ }
896
+ /**
897
+ * after_tool_call hook return value
898
+ *
899
+ * - `result`: Replace tool execution result
900
+ */
901
+ interface AfterToolCallResult {
902
+ /** Replace tool execution result */
903
+ result?: ToolResult;
904
+ }
905
+ /**
906
+ * Hook result mapping table.
907
+ *
908
+ * Defines the return type for each hook event:
909
+ * - Modifiable hooks return specific objects
910
+ * - Listen-only hooks return undefined
911
+ */
912
+ interface HookResultMap {
913
+ before_phase: BeforePhaseResult | undefined;
914
+ after_phase: AfterPhaseResult | undefined;
915
+ before_prompt: BeforePromptResult | undefined;
916
+ before_tool_call: BeforeToolCallResult | undefined;
917
+ after_tool_call: AfterToolCallResult | undefined;
918
+ agent_start: undefined;
919
+ agent_end: undefined;
920
+ turn_start: undefined;
921
+ turn_end: undefined;
922
+ message_start: undefined;
923
+ message_update: undefined;
924
+ message_end: undefined;
925
+ tool_execution_start: undefined;
926
+ tool_execution_update: undefined;
927
+ tool_execution_end: undefined;
928
+ queue_update: undefined;
929
+ save_point: undefined;
930
+ abort: undefined;
931
+ settled: undefined;
932
+ }
933
+ /** Hook event type string */
934
+ type HookEventType = HookEvent["type"];
935
+ /**
936
+ * Hook handler type.
937
+ *
938
+ * @typeParam K - Hook event type
939
+ * @param event - Event object
940
+ * @returns Result object or void
941
+ */
942
+ type HookHandler<K extends HookEventType> = (event: Extract<HookEvent, {
943
+ type: K;
944
+ }>) => HookResultMap[K] | Promise<HookResultMap[K]> | void | Promise<void>;
945
+ /**
946
+ * Hook execution error
947
+ */
948
+ declare class HookError extends Error {
949
+ /** Event type that caused the error */
950
+ readonly eventType: string;
951
+ constructor(
952
+ /** Event type that caused the error */
953
+ eventType: string, message: string, cause?: Error);
954
+ }
955
+ /**
956
+ * Type-safe hook manager.
957
+ *
958
+ * ## Usage
959
+ *
960
+ * ```typescript
961
+ * const hooks = new HooksManager();
962
+ *
963
+ * // Register hook
964
+ * hooks.on("before_tool_call", (event) => {
965
+ * return { allow: false, reason: "Blocked" };
966
+ * });
967
+ *
968
+ * // Emit event (listen-only)
969
+ * await hooks.emit("agent_start", { type: "agent_start", sessionId: "123" });
970
+ *
971
+ * // Emit event and collect result
972
+ * const result = await hooks.emitFirst("before_tool_call", { type: "before_tool_call", tool, args });
973
+ * ```
974
+ */
975
+ declare class HooksManager {
976
+ private handlers;
977
+ /**
978
+ * Register a hook handler.
979
+ * Handlers execute in registration order.
980
+ *
981
+ * @param eventType - Event type
982
+ * @param handler - Handler function
983
+ */
984
+ on<K extends HookEventType>(eventType: K, handler: HookHandler<K>): void;
985
+ /**
986
+ * Unregister a hook handler.
987
+ */
988
+ off<K extends HookEventType>(eventType: K, handler: HookHandler<K>): void;
989
+ /**
990
+ * Clear all handlers, or clear handlers for specified event type.
991
+ */
992
+ clear(eventType?: HookEventType): void;
993
+ /**
994
+ * Check if there are handlers registered for specified event type.
995
+ */
996
+ has(eventType: HookEventType): boolean;
997
+ /**
998
+ * Get handler count for specified event type.
999
+ */
1000
+ count(eventType: HookEventType): number;
1001
+ /**
1002
+ * Emit event (listen-only, ignore return values).
1003
+ * Errors are collected and thrown.
1004
+ *
1005
+ * @param eventType - Event type
1006
+ * @param event - Event object
1007
+ */
1008
+ emit<K extends HookEventType>(eventType: K, event: Extract<HookEvent, {
1009
+ type: K;
1010
+ }>): Promise<void>;
1011
+ /**
1012
+ * Emit event and collect all non-undefined results.
1013
+ *
1014
+ * @param eventType - Event type
1015
+ * @param event - Event object
1016
+ * @returns Array of non-undefined results
1017
+ */
1018
+ emitCollect<K extends HookEventType>(eventType: K, event: Extract<HookEvent, {
1019
+ type: K;
1020
+ }>): Promise<Array<NonNullable<HookResultMap[K]>>>;
1021
+ /**
1022
+ * Emit event and return first non-undefined result (short-circuit).
1023
+ *
1024
+ * @param eventType - Event type
1025
+ * @param event - Event object
1026
+ * @returns First non-undefined result, or undefined
1027
+ */
1028
+ emitFirst<K extends HookEventType>(eventType: K, event: Extract<HookEvent, {
1029
+ type: K;
1030
+ }>): Promise<HookResultMap[K] | undefined>;
1031
+ /**
1032
+ * Emit event and aggregate results with reducer.
1033
+ *
1034
+ * @param eventType - Event type
1035
+ * @param event - Event object
1036
+ * @param reducer - Aggregation function
1037
+ * @param initial - Initial value
1038
+ * @returns Aggregated result
1039
+ */
1040
+ emitReduce<K extends HookEventType, T>(eventType: K, event: Extract<HookEvent, {
1041
+ type: K;
1042
+ }>, reducer: (acc: T, result: NonNullable<HookResultMap[K]>) => T, initial: T): Promise<T>;
1043
+ }
1044
+ /**
1045
+ * Get global hooks manager instance (singleton).
1046
+ */
1047
+ declare function getGlobalHooks(): HooksManager;
1048
+ /**
1049
+ * Reset global hooks manager (mainly for testing).
1050
+ */
1051
+ declare function resetGlobalHooks(): void;
1052
+
1053
+ /**
1054
+ * @module extensions/context
1055
+ *
1056
+ * ExtensionAPI - Main API for extension developers
1057
+ *
1058
+ * ## Quick Start
1059
+ *
1060
+ * ```typescript
1061
+ * import type { ExtensionAPI } from "@rowan-agent/agent";
1062
+ *
1063
+ * export default function(api: ExtensionAPI) {
1064
+ * // 1. Subscribe to hooks
1065
+ * api.on("before_tool_call", (event) => {
1066
+ * console.log(`Tool: ${event.tool.name}`);
1067
+ * return { allow: true };
1068
+ * });
1069
+ *
1070
+ * // 2. Register custom tool
1071
+ * api.registerTool({
1072
+ * name: "search_docs",
1073
+ * description: "Search documentation",
1074
+ * parameters: { type: "object", properties: { query: { type: "string" } } },
1075
+ * execute: async (args) => {
1076
+ * return { content: [{ type: "text", text: "result" }] };
1077
+ * },
1078
+ * });
1079
+ *
1080
+ * // 3. Register custom phase
1081
+ * api.registerPhase({
1082
+ * ...api.manifest?.phase, // Read metadata from package.json
1083
+ * id: "my-phase",
1084
+ * run: async (context, input) => {
1085
+ * return { message: "Done", route: "stop" };
1086
+ * },
1087
+ * });
1088
+ *
1089
+ * // 4. Register model provider
1090
+ * api.registerProvider({
1091
+ * name: "custom",
1092
+ * baseUrl: "https://api.example.com",
1093
+ * api: "openai-completions",
1094
+ * models: [...],
1095
+ * });
1096
+ *
1097
+ * // 5. Inter-extension communication
1098
+ * api.events.on("other-plugin:ready", (data) => {
1099
+ * console.log("Plugin ready:", data);
1100
+ * });
1101
+ * }
1102
+ * ```
1103
+ *
1104
+ * ## Available Hooks
1105
+ *
1106
+ * | Hook | Trigger | Return |
1107
+ * |------|---------|--------|
1108
+ * | `before_phase` | Before phase execution | `{ abort?, skip?, input? }` |
1109
+ * | `after_phase` | After phase execution | `{ abort?, retry?, output? }` |
1110
+ * | `before_prompt` | Before building LLM request | `{ input? }` |
1111
+ * | `before_tool_call` | Before tool execution | `{ allow, reason? }` |
1112
+ * | `after_tool_call` | After tool execution | `{ result? }` |
1113
+ * | `agent_start` | Agent starts | Listen only |
1114
+ * | `agent_end` | Agent ends | Listen only |
1115
+ * | `message_*` | Message lifecycle | Listen only |
1116
+ * | `tool_execution_*` | Tool execution lifecycle | Listen only |
1117
+ */
1118
+
1119
+ /**
1120
+ * Extension API object passed to extension factory function.
1121
+ *
1122
+ * @example
1123
+ * ```typescript
1124
+ * export default function(api: ExtensionAPI) {
1125
+ * // api provides all extension APIs
1126
+ * }
1127
+ * ```
1128
+ */
1129
+ interface ExtensionAPI {
1130
+ /**
1131
+ * Subscribe to a hook event.
1132
+ *
1133
+ * @param eventType - Hook type, e.g. "before_tool_call"
1134
+ * @param handler - Hook handler, can return result to modify behavior
1135
+ *
1136
+ * @example
1137
+ * ```typescript
1138
+ * ctx.on("before_tool_call", (event) => {
1139
+ * // event contains { tool, args }
1140
+ * if (event.tool.name === "bash") {
1141
+ * return { allow: false, reason: "Blocked" };
1142
+ * }
1143
+ * return { allow: true };
1144
+ * });
1145
+ * ```
1146
+ */
1147
+ on<K extends HookEventType>(eventType: K, handler: HookHandler<K>): void;
1148
+ /**
1149
+ * Unsubscribe from a hook event.
1150
+ */
1151
+ off<K extends HookEventType>(eventType: K, handler: HookHandler<K>): void;
1152
+ /**
1153
+ * Register a custom LLM-callable tool.
1154
+ *
1155
+ * @param tool - Tool definition with name, description, parameters, and execute function
1156
+ *
1157
+ * @example
1158
+ * ```typescript
1159
+ * api.registerTool({
1160
+ * name: "search_docs",
1161
+ * description: "Search project documentation",
1162
+ * parameters: {
1163
+ * type: "object",
1164
+ * properties: { query: { type: "string" } },
1165
+ * required: ["query"],
1166
+ * },
1167
+ * execute: async (args, signal) => {
1168
+ * const query = (args as any).query;
1169
+ * return { content: [{ type: "text", text: `Results for: ${query}` }] };
1170
+ * },
1171
+ * });
1172
+ * ```
1173
+ */
1174
+ registerTool(tool: ToolDefinition): void;
1175
+ /**
1176
+ * Register a custom phase.
1177
+ *
1178
+ * Phases are state machine nodes that can be referenced by the routing system.
1179
+ *
1180
+ * @param registration - Phase registration info
1181
+ *
1182
+ * @example
1183
+ * ```typescript
1184
+ * ctx.registerPhase({
1185
+ * id: "review",
1186
+ * name: "Code Review",
1187
+ * description: "Review code changes",
1188
+ *
1189
+ * // Optional: declarative prompt config
1190
+ * prompt: {
1191
+ * instructions: [
1192
+ * "Phase: review",
1193
+ * "Review code changes, call route tool if looks good",
1194
+ * ],
1195
+ * },
1196
+ *
1197
+ * // Optional: custom execution logic
1198
+ * async run(context, input) {
1199
+ * const result = await context.model.invoke({ input });
1200
+ * return { message: result.text, route: "stop" };
1201
+ * },
1202
+ * });
1203
+ * ```
1204
+ */
1205
+ registerPhase(registration: PhaseRegistration): void;
1206
+ /**
1207
+ * Register a model provider.
1208
+ *
1209
+ * @param config - Provider configuration
1210
+ *
1211
+ * @example
1212
+ * ```typescript
1213
+ * ctx.registerProvider({
1214
+ * name: "custom-llm",
1215
+ * baseUrl: "https://api.custom.com/v1",
1216
+ * api: "openai-completions",
1217
+ * models: [{
1218
+ * id: "custom-7b",
1219
+ * name: "Custom 7B",
1220
+ * api: "openai-completions",
1221
+ * reasoning: false,
1222
+ * input: ["text"],
1223
+ * cost: { input: 0.1, output: 0.2, cacheRead: 0, cacheWrite: 0 },
1224
+ * contextWindow: 8192,
1225
+ * maxTokens: 4096,
1226
+ * }],
1227
+ * });
1228
+ * ```
1229
+ */
1230
+ registerProvider(config: ProviderConfig): void;
1231
+ /**
1232
+ * Unregister a model provider.
1233
+ */
1234
+ unregisterProvider(name: string): void;
1235
+ /**
1236
+ * Extension manifest from package.json `rowan` field.
1237
+ *
1238
+ * Can be used to auto-fill phase metadata:
1239
+ * ```typescript
1240
+ * ctx.registerPhase({
1241
+ * ...ctx.manifest?.phase, // Auto-fill id, name, description
1242
+ * run: async (context, input) => { ... },
1243
+ * });
1244
+ * ```
1245
+ */
1246
+ manifest?: ExtensionManifest;
1247
+ /**
1248
+ * Utility functions.
1249
+ */
1250
+ utils: ExtensionUtils;
1251
+ /**
1252
+ * Runtime context — provides access to agent state, cwd, and utilities.
1253
+ *
1254
+ * Available after extension loading completes. Use for runtime operations
1255
+ * like executing shell commands or checking agent state.
1256
+ */
1257
+ context: ExtensionContext;
1258
+ /**
1259
+ * Shared event bus for inter-extension communication.
1260
+ *
1261
+ * Extensions can emit and subscribe to arbitrary events to coordinate
1262
+ * without direct coupling.
1263
+ *
1264
+ * @example
1265
+ * ```typescript
1266
+ * // Extension A
1267
+ * api.events.on("my-plugin:ready", (data) => {
1268
+ * console.log("Plugin ready:", data);
1269
+ * });
1270
+ *
1271
+ * // Extension B
1272
+ * api.events.emit("my-plugin:ready", { version: "1.0" });
1273
+ * ```
1274
+ */
1275
+ events: EventBus;
1276
+ }
1277
+ /**
1278
+ * Runtime context available to extensions during event handler execution.
1279
+ *
1280
+ * Provides access to agent state, working directory, and utility methods.
1281
+ * Values are resolved lazily via getters, so changes via `runner.bind()` are
1282
+ * reflected immediately without recreating the context.
1283
+ *
1284
+ * This is distinct from ExtensionAPI (which is for registration) —
1285
+ * ExtensionContext gives runtime state during hook execution.
1286
+ *
1287
+ * @example
1288
+ * ```typescript
1289
+ * api.on("before_tool_call", (event, ctx) => {
1290
+ * console.log(`cwd: ${ctx.cwd}`);
1291
+ * if (ctx.isIdle()) { ... }
1292
+ * });
1293
+ * ```
1294
+ */
1295
+ interface ExtensionContext {
1296
+ /** Current working directory */
1297
+ cwd: string;
1298
+ /** Abort signal — fires when the agent operation is cancelled */
1299
+ signal: AbortSignal | undefined;
1300
+ /** Whether the agent is currently idle (not streaming) */
1301
+ isIdle(): boolean;
1302
+ /** Abort the current agent operation */
1303
+ abort(): void;
1304
+ /**
1305
+ * Execute a shell command.
1306
+ *
1307
+ * @param command - The command to run
1308
+ * @param args - Command arguments
1309
+ * @param options - Execution options (cwd, env, timeout, signal)
1310
+ * @returns Execution result with exitCode, stdout, stderr
1311
+ */
1312
+ exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
1313
+ /** Extension manifest from package.json `rowan` field */
1314
+ manifest?: ExtensionManifest;
1315
+ /** Current model ID, if available */
1316
+ modelId?: string;
1317
+ /** Get current system prompt */
1318
+ getSystemPrompt?(): string;
1319
+ }
1320
+ /**
1321
+ * Utility functions available to extensions.
1322
+ */
1323
+ interface ExtensionUtils {
1324
+ /**
1325
+ * Generate unique ID.
1326
+ * @param prefix - ID prefix
1327
+ * @returns Format: `{prefix}_{timestamp}_{counter}`
1328
+ */
1329
+ createId(prefix: string): string;
1330
+ /**
1331
+ * JSON serialization (with indentation).
1332
+ * @param value - Value to serialize
1333
+ * @returns JSON string
1334
+ */
1335
+ formatJson(value: unknown): string;
1336
+ /**
1337
+ * Build LlmRequest from PhaseInput.
1338
+ * @param input - Phase input
1339
+ * @returns LLM request object
1340
+ */
1341
+ buildModelRequest(input: PhaseInput): LlmRequest;
1342
+ /**
1343
+ * Create a prompt builder.
1344
+ * @param instructions - Instruction list
1345
+ * @returns Builder function
1346
+ *
1347
+ * @example
1348
+ * ```typescript
1349
+ * const builder = ctx.utils.createPromptBuilder([
1350
+ * "Phase: review",
1351
+ * "Review code changes",
1352
+ * ]);
1353
+ *
1354
+ * // Use in buildPrompt
1355
+ * ctx.registerPhase({
1356
+ * id: "review",
1357
+ * buildPrompt: builder,
1358
+ * });
1359
+ * ```
1360
+ */
1361
+ createPromptBuilder(instructions: string[]): (input: PhaseInput) => LlmRequest;
1362
+ }
1363
+ /**
1364
+ * Extension factory function.
1365
+ * Receives ExtensionAPI for registering hooks, phases, and providers.
1366
+ *
1367
+ * @param api - Extension API
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * const factory: ExtensionFactory = (api) => {
1372
+ * api.on("before_tool_call", handler);
1373
+ * };
1374
+ * ```
1375
+ */
1376
+ type ExtensionFactory = (api: ExtensionAPI) => void | Promise<void>;
1377
+
1378
+ /**
1379
+ * Extension runner — manages extension loading and hook execution.
1380
+ *
1381
+ * Architecture reference: PI's ExtensionRunner
1382
+ * - Per-extension tracking via Extension objects
1383
+ * - Shared ExtensionRuntime with invalidate/assertActive
1384
+ * - Direct `on()` API for hook registration
1385
+ * - Error listener pattern for structured error handling
1386
+ * - Tool registration support
1387
+ */
1388
+
1389
+ type ExtensionRunnerOptions = {
1390
+ entryPhaseId?: string;
1391
+ validatePhaseOverride?: (phaseId: string, extensionPath: string) => boolean;
1392
+ cwd?: string;
1393
+ };
1394
+ /**
1395
+ * Manages extensions and provides hooks for the agent loop.
1396
+ *
1397
+ * Features:
1398
+ * - Per-extension tracking (handlers, tools, phases)
1399
+ * - Shared runtime with lifecycle protection (invalidate/assertActive)
1400
+ * - Error listener pattern for structured error handling
1401
+ * - Direct hook API and extension-loaded hook API
1402
+ * - Tool registration for LLM-callable tools
1403
+ * - EventBus for inter-extension communication
1404
+ *
1405
+ * @example
1406
+ * ```ts
1407
+ * const runner = createExtensionRunner();
1408
+ *
1409
+ * // Direct hook registration
1410
+ * const unsub = runner.on("before_tool_call", (event) => {
1411
+ * return { allow: false, reason: "Blocked" };
1412
+ * });
1413
+ *
1414
+ * // Error handling
1415
+ * runner.onError((error) => {
1416
+ * console.error(`Extension error in ${error.extensionPath}:`, error.error);
1417
+ * });
1418
+ *
1419
+ * // Load extensions
1420
+ * await runner.loadExtensions(extensions);
1421
+ * runner.bind();
1422
+ * ```
1423
+ */
1424
+ declare class ExtensionRunner {
1425
+ readonly hooks: HooksManager;
1426
+ readonly runtime: ExtensionRuntime;
1427
+ readonly events: EventBus;
1428
+ private readonly validatePhaseOverride?;
1429
+ private readonly cwd;
1430
+ private readonly abortController;
1431
+ private _idle;
1432
+ private readonly extensions;
1433
+ private readonly phases;
1434
+ private _phaseCache;
1435
+ private readonly pendingProviders;
1436
+ private bound;
1437
+ private readonly errorListeners;
1438
+ private readonly loadedExtensions;
1439
+ constructor(options?: ExtensionRunnerOptions);
1440
+ /** Whether the agent is currently idle (not streaming). */
1441
+ get isIdle(): boolean;
1442
+ /** Set idle state — called by the agent loop. */
1443
+ setIdle(idle: boolean): void;
1444
+ /** Abort signal for the current runner instance. */
1445
+ get signal(): AbortSignal;
1446
+ /** Abort the current runner operation. */
1447
+ abort(): void;
1448
+ /**
1449
+ * Register an error listener.
1450
+ * Returns an unsubscribe function.
1451
+ */
1452
+ onError(listener: ExtensionErrorListener): () => void;
1453
+ /**
1454
+ * Emit a structured extension error to all listeners.
1455
+ */
1456
+ emitError(error: ExtensionError): void;
1457
+ /**
1458
+ * Mark all extension contexts as stale.
1459
+ * After calling this, any captured ExtensionAPI or ExtensionContext will throw
1460
+ * on use. Used during session replacement or reload.
1461
+ */
1462
+ invalidate(message?: string): void;
1463
+ /**
1464
+ * Subscribe to a specific hook event type.
1465
+ * Returns an unsubscribe function.
1466
+ *
1467
+ * @example
1468
+ * ```ts
1469
+ * const unsub = runner.on("before_tool_call", (event) => {
1470
+ * return { allow: false, reason: "Blocked" };
1471
+ * });
1472
+ * unsub(); // Cancel subscription
1473
+ * ```
1474
+ */
1475
+ on<K extends HookEventType>(type: K, handler: HookHandler<K>): () => void;
1476
+ /**
1477
+ * Subscribe to all events (read-only).
1478
+ * Returns an unsubscribe function.
1479
+ *
1480
+ * @example
1481
+ * ```ts
1482
+ * const unsub = runner.subscribe((event) => {
1483
+ * console.log(event.type);
1484
+ * });
1485
+ * ```
1486
+ */
1487
+ subscribe(listener: (event: {
1488
+ type: HookEventType;
1489
+ }) => void): () => void;
1490
+ private getAllEventTypes;
1491
+ /**
1492
+ * Load and initialize extensions.
1493
+ * Creates Extension tracking objects and calls each factory with an ExtensionAPI.
1494
+ */
1495
+ loadExtensions(extensions: LoadedExtension[]): Promise<void>;
1496
+ /**
1497
+ * Get all registered tools from all extensions (first registration per name wins).
1498
+ */
1499
+ getAllRegisteredTools(): RegisteredTool[];
1500
+ /**
1501
+ * Get a tool definition by name. Returns undefined if not found.
1502
+ */
1503
+ getToolDefinition(toolName: string): RegisteredTool["definition"] | undefined;
1504
+ /**
1505
+ * Check if there are handlers registered for specified event type.
1506
+ */
1507
+ hasHandlers(eventType: HookEventType): boolean;
1508
+ /**
1509
+ * Get the number of handlers for specified event type.
1510
+ */
1511
+ handlerCount(eventType: HookEventType): number;
1512
+ getPhase(id: string): PhaseDefinition | undefined;
1513
+ getPhases(): PhaseDefinition[];
1514
+ getPhaseHandler(id: string): RegisteredPhase["handler"] | undefined;
1515
+ createPhaseRegistry(input?: {
1516
+ entryPhaseId?: string;
1517
+ }): PhaseRegistry;
1518
+ /**
1519
+ * Bind the runner — flushes pending provider registrations and
1520
+ * replaces runtime stubs with real implementations.
1521
+ */
1522
+ bind(): void;
1523
+ /**
1524
+ * Generic emit — fire-and-forget for any event type.
1525
+ */
1526
+ emit<K extends HookEventType>(eventType: K, event: Parameters<HookHandler<K>>[0]): Promise<void>;
1527
+ /**
1528
+ * Unified hook emission — returns the first non-undefined result.
1529
+ */
1530
+ private emitHook;
1531
+ emitBeforePhase(phaseId: string, input: PhaseInput): Promise<{
1532
+ abort?: any;
1533
+ skip?: any;
1534
+ input?: PhaseInput;
1535
+ }>;
1536
+ emitAfterPhase(phaseId: string, output: PhaseOutput): Promise<{
1537
+ abort?: any;
1538
+ retry?: PhaseInput;
1539
+ output?: PhaseOutput;
1540
+ }>;
1541
+ emitBeforePrompt(phaseId: string, input: PhaseInput): Promise<PhaseInput>;
1542
+ emitBeforeToolCall(tool: Tool$1, args: unknown): Promise<{
1543
+ allow: boolean;
1544
+ reason?: string;
1545
+ }>;
1546
+ emitAfterToolCall(tool: Tool$1, result: ToolResult): Promise<ToolResult>;
1547
+ emitAgentStart(sessionId: string): Promise<void>;
1548
+ emitAgentEnd(sessionId: string, outcome: any, messages: any[]): Promise<void>;
1549
+ emitTurnStart(messages: any[]): Promise<void>;
1550
+ emitTurnEnd(messages: any[], outcome?: any): Promise<void>;
1551
+ emitMessageStart(message: any): Promise<void>;
1552
+ emitMessageUpdate(message: any, delta: string): Promise<void>;
1553
+ emitMessageEnd(message: any): Promise<void>;
1554
+ emitToolExecutionStart(toolCallId: string, toolName: string, args: unknown): Promise<void>;
1555
+ emitToolExecutionUpdate(toolCallId: string, toolName: string, _progress?: string): Promise<void>;
1556
+ emitToolExecutionEnd(toolCallId: string, toolName: string, result: ToolResult): Promise<void>;
1557
+ emitSavePoint(hadPendingMutations: boolean): Promise<void>;
1558
+ emitAbort(reason?: string): Promise<void>;
1559
+ emitSettled(): Promise<void>;
1560
+ /**
1561
+ * Emit an AgentEvent by routing to the appropriate typed hook.
1562
+ */
1563
+ emitAgentEvent(event: any): Promise<void>;
1564
+ /**
1565
+ * Create an ExtensionAPI for a specific extension.
1566
+ * Registration methods write to the extension tracking object.
1567
+ * Action methods delegate to the shared runtime.
1568
+ */
1569
+ private createExtensionAPI;
1570
+ private registerTool;
1571
+ private registerPhase;
1572
+ private registerProvider;
1573
+ private unregisterProvider;
1574
+ private flushPendingProviders;
1575
+ private getRegisteredPhase;
1576
+ private collectRegisteredPhases;
1577
+ }
1578
+ declare function createExtensionRunner(options?: ExtensionRunnerOptions): ExtensionRunner;
1579
+
1580
+ /** Check if a path is a built-in extension source (synthetic path). */
1581
+ declare function isBuiltinSource(path: string): boolean;
1582
+ /** Check if an external extension is attempting to override a built-in phase. */
1583
+ declare function isBuiltinPhaseOverride(phaseId: string, extensionPath: string): boolean;
1584
+ type CreateDefaultPhaseRegistryOptions = {
1585
+ cwd?: string;
1586
+ entryPhaseId?: string;
1587
+ };
1588
+ declare function getBuiltinExtensions(): Promise<LoadedExtension[]>;
1589
+ declare function getBuiltinRunner(): ExtensionRunner;
1590
+ declare function createBuiltinPhaseRegistry(input?: {
1591
+ entryPhaseId?: string;
1592
+ }): Promise<PhaseRegistry>;
1593
+ declare function createDefaultPhaseRegistry(options?: CreateDefaultPhaseRegistryOptions): Promise<PhaseRegistry>;
1594
+
1595
+ /**
1596
+ * Extension loader — discovers and loads extensions from the filesystem.
1597
+ *
1598
+ * Uses the new LoadedExtension type that works with ExtensionRunner.
1599
+ */
1600
+
1601
+ /**
1602
+ * Load a single extension from a factory function.
1603
+ */
1604
+ declare function loadExtensionFromFactory(factory: ExtensionFactory, cwd: string, extensionPath?: string): LoadedExtension;
1605
+ declare const loadExtensionFromFactorySync: typeof loadExtensionFromFactory;
1606
+ /**
1607
+ * Load extensions from file paths.
1608
+ */
1609
+ declare function loadExtensions(paths: string[], cwd: string): Promise<{
1610
+ extensions: LoadedExtension[];
1611
+ errors: Array<{
1612
+ path: string;
1613
+ error: string;
1614
+ }>;
1615
+ }>;
1616
+ /**
1617
+ * Discover and load extensions from .rowan/extensions directory.
1618
+ */
1619
+ declare function discoverAndLoadExtensions(cwd: string): Promise<{
1620
+ extensions: LoadedExtension[];
1621
+ errors: Array<{
1622
+ path: string;
1623
+ error: string;
1624
+ }>;
1625
+ }>;
1626
+
1627
+ type ExtensionRunnerRef = {
1628
+ current?: ExtensionRunner;
1629
+ };
1630
+ type AgentOptions = {
1631
+ context: AgentContext;
1632
+ model: LlmModelRef;
1633
+ stream: StreamFn;
1634
+ cwd?: string;
1635
+ phaseConfig?: PhaseRegistry;
1636
+ extensionRunnerRef?: ExtensionRunnerRef;
1637
+ sessionId?: string;
1638
+ maxAttempts?: number;
1639
+ limits?: AgentRunLimits;
1640
+ beforeToolCall?: BeforeToolCall;
1641
+ afterToolCall?: AfterToolCall;
1642
+ };
1643
+ type RunOptions = Partial<Omit<AgentOptions, "context">> & {
1644
+ context: AgentContext;
1645
+ };
1646
+ type AgentStatus = {
1647
+ sessionId?: string;
1648
+ context: AgentContext;
1649
+ model: LlmModelRef;
1650
+ tools: Tool$1[];
1651
+ isRunning: boolean;
1652
+ currentResult?: RunResult;
1653
+ error?: string;
1654
+ };
1655
+ declare class Agent {
1656
+ readonly state: AgentStatus;
1657
+ private options;
1658
+ private readonly listeners;
1659
+ private readonly pendingListenerTasks;
1660
+ private readonly listenerErrors;
1661
+ private activeRun?;
1662
+ constructor(options: AgentOptions);
1663
+ subscribe(listener: AgentEventListener): Unsubscribe;
1664
+ private emitToListeners;
1665
+ flushEvents(): Promise<void>;
1666
+ private processEvents;
1667
+ /**
1668
+ * Hook for before_tool_call — called before a tool executes.
1669
+ * Extensions can block execution by setting allow=false.
1670
+ */
1671
+ private handleBeforeToolCall;
1672
+ /**
1673
+ * Hook for after_tool_call — called after a tool executes.
1674
+ * Extensions can mutate the result.
1675
+ */
1676
+ private handleAfterToolCall;
1677
+ /**
1678
+ * Hook for before_phase — called before a phase executes.
1679
+ * Extensions can abort, skip, or replace the phase input.
1680
+ */
1681
+ private handleBeforePhase;
1682
+ /**
1683
+ * Hook for after_phase — called after a phase executes.
1684
+ * Extensions can abort, retry, or replace the output.
1685
+ */
1686
+ private handleAfterPhase;
1687
+ /**
1688
+ * Hook for before_prompt — called before buildPrompt, allowing extensions to transform PhaseInput.
1689
+ * Extensions can transform the PhaseInput (messages, tools, systemPrompt, etc.).
1690
+ */
1691
+ private handleBeforePrompt;
1692
+ private handleRunFailure;
1693
+ private runWithLifecycle;
1694
+ private finishRun;
1695
+ run(config?: RunOptions): Promise<RunResult>;
1696
+ abort(reason?: string): void;
1697
+ waitForIdle(): Promise<void>;
1698
+ private resolveRunConfig;
1699
+ private createContextSnapshot;
1700
+ }
1701
+
1702
+ /**
1703
+ * Push-based async iterable with a final result.
1704
+ *
1705
+ * Producers call `push(event)` to deliver events. Consumers iterate with
1706
+ * `for await (const event of stream)`. The stream terminates when an event
1707
+ * matches the `isComplete` predicate; `result()` resolves with the extracted
1708
+ * final value.
1709
+ */
1710
+ declare class EventStream<T, R = T> implements AsyncIterable<T> {
1711
+ private queue;
1712
+ private waiting;
1713
+ private done;
1714
+ private finalResultPromise;
1715
+ private resolveFinalResult;
1716
+ private isComplete;
1717
+ private extractResult;
1718
+ constructor(isComplete: (event: T) => boolean, extractResult: (event: T) => R);
1719
+ push(event: T): void;
1720
+ end(result?: R): void;
1721
+ [Symbol.asyncIterator](): AsyncIterator<T>;
1722
+ result(): Promise<R>;
1723
+ }
1724
+ /**
1725
+ * Agent-level event stream that terminates on `agent_end`.
1726
+ * `result()` resolves with the final messages array.
1727
+ */
1728
+ declare class AgentEventStream extends EventStream<AgentEvent, AgentMessage$1[]> {
1729
+ constructor();
1730
+ }
1731
+
1732
+ declare const SESSION_SCHEMA_VERSION = "0.4.4";
1733
+ type AgentMessageMetadata = Record<string, unknown> & {
1734
+ phase?: string;
1735
+ };
1736
+ declare const AgentMessageSchema: Type.TObject<{
1737
+ id: Type.TString;
1738
+ role: Type.TUnion<[Type.TLiteral<"system">, Type.TLiteral<"user">, Type.TLiteral<"assistant">, Type.TLiteral<"tool">]>;
1739
+ content: Type.TString;
1740
+ createdAt: Type.TString;
1741
+ metadata: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
1742
+ }>;
1743
+ type AgentMessage = Type.Static<typeof AgentMessageSchema>;
1744
+ declare const SkillSchema: Type.TObject<{
1745
+ name: Type.TString;
1746
+ description: Type.TString;
1747
+ filePath: Type.TString;
1748
+ baseDir: Type.TString;
1749
+ disableModelInvocation: Type.TBoolean;
1750
+ }>;
1751
+ type Skill = Type.Static<typeof SkillSchema>;
1752
+ type Session<TLogEvent = never> = {
1753
+ version: string;
1754
+ id: string;
1755
+ parentSessionId?: string;
1756
+ systemPrompt: string;
1757
+ input: string;
1758
+ messages: AgentMessage[];
1759
+ log: TLogEvent[];
1760
+ skills: Skill[];
1761
+ createdAt: string;
1762
+ updatedAt: string;
1763
+ title?: string;
1764
+ };
1765
+ declare function createSession<TLogEvent = never>(input: {
1766
+ id?: string;
1767
+ systemPrompt: string;
1768
+ input: string;
1769
+ skills?: Skill[];
1770
+ parentSessionId?: string;
1771
+ title?: string;
1772
+ }): Session<TLogEvent>;
1773
+ declare function appendUserTurn<TLogEvent>(session: Session<TLogEvent>, input: string): Session<TLogEvent>;
1774
+
1775
+ declare const SESSION_MANAGER_SCHEMA_VERSION = "0.4.4";
1776
+ type SessionHeader = {
1777
+ type: "header";
1778
+ id: string;
1779
+ version: string;
1780
+ createdAt: string;
1781
+ updatedAt: string;
1782
+ systemPrompt: string;
1783
+ input: string;
1784
+ parentSessionId?: string;
1785
+ skills: Skill[];
1786
+ title?: string;
1787
+ currentLeafId?: string | null;
1788
+ };
1789
+ type SessionEntryBase = {
1790
+ id: string;
1791
+ parentId: string | null;
1792
+ timestamp: string;
1793
+ };
1794
+ type MessageSessionEntry = SessionEntryBase & {
1795
+ type: "message";
1796
+ message: AgentMessage;
1797
+ };
1798
+ type OutcomeSessionEntry = SessionEntryBase & {
1799
+ type: "outcome";
1800
+ outcome: Outcome;
1801
+ };
1802
+ type ExecutionTurnSessionEntry = SessionEntryBase & {
1803
+ type: "execution_turn";
1804
+ turn: ExecutionTurn;
1805
+ };
1806
+ type CompactionSessionEntry = SessionEntryBase & {
1807
+ type: "compaction";
1808
+ summary: string;
1809
+ firstKeptEntryId: string;
1810
+ };
1811
+ type BranchSummarySessionEntry = SessionEntryBase & {
1812
+ type: "branch_summary";
1813
+ fromId: string;
1814
+ summary: string;
1815
+ };
1816
+ type SessionInfoSessionEntry = SessionEntryBase & {
1817
+ type: "session_info";
1818
+ title: string;
1819
+ };
1820
+ type CustomSessionEntry = SessionEntryBase & {
1821
+ type: "custom";
1822
+ customType: string;
1823
+ data: unknown;
1824
+ };
1825
+ type SessionEntry = MessageSessionEntry | OutcomeSessionEntry | ExecutionTurnSessionEntry | CompactionSessionEntry | BranchSummarySessionEntry | SessionInfoSessionEntry | CustomSessionEntry;
1826
+ type SessionRecord = SessionHeader | SessionEntry;
1827
+ type SessionAgentContext<TTool = unknown> = {
1828
+ systemPrompt: string;
1829
+ messages: AgentMessage[];
1830
+ tools: TTool[];
1831
+ skills: Skill[];
1832
+ };
1833
+ type BuildAgentContextInput<TTool = unknown> = {
1834
+ leafId?: string | null;
1835
+ tools?: TTool[];
1836
+ skills?: Skill[];
1837
+ };
1838
+ type CreateSessionManagerInput = {
1839
+ id?: string;
1840
+ systemPrompt: string;
1841
+ input: string;
1842
+ parentSessionId?: string;
1843
+ skills?: Skill[];
1844
+ title?: string;
1845
+ };
1846
+ type SessionListItem = {
1847
+ id: string;
1848
+ title?: string;
1849
+ createdAt: string;
1850
+ updatedAt: string;
1851
+ messageCount: number;
1852
+ latestMessage?: string;
1853
+ };
1854
+ type SessionManager = {
1855
+ getSessionId(): string;
1856
+ getSessionFile(): string | undefined;
1857
+ getHeader(): Promise<SessionHeader>;
1858
+ appendMessage(message: AgentMessage): Promise<string>;
1859
+ appendOutcome(outcome: Outcome): Promise<string>;
1860
+ appendExecutionTurn(turn: ExecutionTurn): Promise<string>;
1861
+ appendCompaction(input: {
1862
+ summary: string;
1863
+ firstKeptEntryId: string;
1864
+ }): Promise<string>;
1865
+ appendBranchSummary(input: {
1866
+ fromId: string;
1867
+ summary: string;
1868
+ }): Promise<string>;
1869
+ appendSessionInfo(input: {
1870
+ title: string;
1871
+ }): Promise<string>;
1872
+ appendCustom(input: {
1873
+ customType: string;
1874
+ data: unknown;
1875
+ }): Promise<string>;
1876
+ branch(entryId: string | null): Promise<void>;
1877
+ buildAgentContext<TTool = unknown>(input?: BuildAgentContextInput<TTool>): Promise<SessionAgentContext<TTool>>;
1878
+ listEntries(): Promise<SessionEntry[]>;
1879
+ loadExecutionTurns(filter?: StepFilter): Promise<ExecutionTurn[]>;
1880
+ };
1881
+ declare function createSessionHeader(input: CreateSessionManagerInput): SessionHeader;
1882
+ declare class InMemorySessionManager implements SessionManager {
1883
+ private header;
1884
+ private readonly entries;
1885
+ private constructor();
1886
+ static create(input: CreateSessionManagerInput): InMemorySessionManager;
1887
+ static fromRecords(records: SessionRecord[]): InMemorySessionManager;
1888
+ getSessionId(): string;
1889
+ getSessionFile(): string | undefined;
1890
+ getHeader(): Promise<SessionHeader>;
1891
+ appendMessage(message: AgentMessage): Promise<string>;
1892
+ appendOutcome(outcome: Outcome): Promise<string>;
1893
+ appendExecutionTurn(turn: ExecutionTurn): Promise<string>;
1894
+ appendCompaction(input: {
1895
+ summary: string;
1896
+ firstKeptEntryId: string;
1897
+ }): Promise<string>;
1898
+ appendBranchSummary(input: {
1899
+ fromId: string;
1900
+ summary: string;
1901
+ }): Promise<string>;
1902
+ appendSessionInfo(input: {
1903
+ title: string;
1904
+ }): Promise<string>;
1905
+ appendCustom(input: {
1906
+ customType: string;
1907
+ data: unknown;
1908
+ }): Promise<string>;
1909
+ branch(entryId: string | null): Promise<void>;
1910
+ buildAgentContext<TTool = unknown>(input?: BuildAgentContextInput<TTool>): Promise<SessionAgentContext<TTool>>;
1911
+ listEntries(): Promise<SessionEntry[]>;
1912
+ loadExecutionTurns(filter?: StepFilter): Promise<ExecutionTurn[]>;
1913
+ protected appendImportedEntry(entry: SessionEntry): void;
1914
+ private appendEntry;
1915
+ private entriesForLeaf;
1916
+ }
1917
+ declare function summarizeSessionManagerRecords(records: readonly SessionRecord[]): SessionListItem;
1918
+
1919
+ declare class LocalJsonlSessionManager implements SessionManager {
1920
+ private readonly sessionsDir;
1921
+ private readonly filePath;
1922
+ private readonly inner;
1923
+ private constructor();
1924
+ static create(sessionsDir: string, input: CreateSessionManagerInput): Promise<LocalJsonlSessionManager>;
1925
+ static open(sessionsDir: string, id: string): Promise<LocalJsonlSessionManager | undefined>;
1926
+ static list(sessionsDir: string): Promise<SessionListItem[]>;
1927
+ static delete(sessionsDir: string, id: string): Promise<boolean>;
1928
+ getSessionId(): string;
1929
+ getSessionFile(): string | undefined;
1930
+ getHeader(): Promise<SessionHeader>;
1931
+ appendMessage(message: AgentMessage): Promise<string>;
1932
+ appendOutcome(outcome: Outcome): Promise<string>;
1933
+ appendExecutionTurn(turn: ExecutionTurn): Promise<string>;
1934
+ appendCompaction(input: {
1935
+ summary: string;
1936
+ firstKeptEntryId: string;
1937
+ }): Promise<string>;
1938
+ appendBranchSummary(input: {
1939
+ fromId: string;
1940
+ summary: string;
1941
+ }): Promise<string>;
1942
+ appendSessionInfo(input: {
1943
+ title: string;
1944
+ }): Promise<string>;
1945
+ appendCustom(input: {
1946
+ customType: string;
1947
+ data: unknown;
1948
+ }): Promise<string>;
1949
+ branch(entryId: string | null): Promise<void>;
1950
+ buildAgentContext<TTool = unknown>(input?: BuildAgentContextInput<TTool>): Promise<SessionAgentContext<TTool>>;
1951
+ listEntries(): Promise<SessionEntry[]>;
1952
+ loadExecutionTurns(filter?: StepFilter): Promise<ExecutionTurn[]>;
1953
+ private appendThroughInner;
1954
+ }
1955
+
1956
+ type ToolContext = {
1957
+ state: AgentContextState;
1958
+ toolCallId: string;
1959
+ };
1960
+ type ToolExecutionMode = "sequential" | "parallel";
1961
+ type Tool<TArgs = unknown> = {
1962
+ name: string;
1963
+ description: string;
1964
+ parameters: Type.TSchema;
1965
+ /** One-line snippet shown in the system prompt tool list. */
1966
+ promptSnippet?: string;
1967
+ /** Additional guidelines appended to the system prompt when this tool is active. */
1968
+ promptGuidelines?: string[];
1969
+ /** Whether this tool can run concurrently with others. Default: "parallel". */
1970
+ executionMode?: ToolExecutionMode;
1971
+ execute(args: TArgs, context: ToolContext, signal?: AbortSignal): Promise<ToolResult>;
1972
+ };
1973
+
1974
+ type CoreToolContext = {
1975
+ root?: string;
1976
+ maxReadBytes?: number;
1977
+ bashTimeoutMs?: number;
1978
+ maxBashOutputBytes?: number;
1979
+ };
1980
+ declare function createCoreTools(input?: CoreToolContext): Tool[];
1981
+
1982
+ type RuntimeMode = "source" | "binary";
1983
+ type WorkspacePaths = {
1984
+ mode: RuntimeMode;
1985
+ cwd: string;
1986
+ rowanDir: string;
1987
+ };
1988
+ type ResolveWorkspaceOptions = {
1989
+ cwd?: string;
1990
+ env?: NodeJS.ProcessEnv;
1991
+ execPath?: string;
1992
+ entrypoint?: string;
1993
+ homeDir?: string;
1994
+ mode?: RuntimeMode;
1995
+ };
1996
+ declare function resolveWorkspacePaths(options?: ResolveWorkspaceOptions): WorkspacePaths;
1997
+ declare function resolveInWorkspace(path: string, rootOrPaths: string | Pick<WorkspacePaths, "cwd">): string;
1998
+
1999
+ declare function resolveSkillPath(input: string, workspace?: WorkspacePaths): string;
2000
+ declare function loadSkill(path: string, workspace?: WorkspacePaths): Promise<AgentContextSkill>;
2001
+ declare function loadSkills(paths?: string[], workspace?: WorkspacePaths): Promise<AgentContextSkill[]>;
2002
+
2003
+ interface SystemPromptOptions {
2004
+ /** Base system prompt. */
2005
+ systemPrompt: string;
2006
+ /** Additional guideline bullets appended to the default runtime instructions. */
2007
+ promptGuidelines?: string[];
2008
+ /** Text to append after the default runtime instructions. */
2009
+ appendSystemPrompt?: string;
2010
+ /** Active tools — snippets and guidelines are included in the prompt. */
2011
+ tools?: Array<{
2012
+ name: string;
2013
+ description?: string;
2014
+ promptSnippet?: string;
2015
+ promptGuidelines?: string[];
2016
+ }>;
2017
+ /** Loaded skills — serialized into the prompt. */
2018
+ skills?: Array<{
2019
+ name: string;
2020
+ description: string;
2021
+ filePath: string;
2022
+ }>;
2023
+ /** Working directory. */
2024
+ cwd?: string;
2025
+ }
2026
+ declare function buildSystemPrompt(options: SystemPromptOptions): string;
2027
+
2028
+ type PromptTool = {
2029
+ name: string;
2030
+ description: string;
2031
+ parameters: unknown;
2032
+ };
2033
+ type SerializableTool = {
2034
+ name: string;
2035
+ description: string;
2036
+ parameters: unknown;
2037
+ };
2038
+ declare function serializeSkills(skills: AgentContextSkill[]): Array<{
2039
+ name: string;
2040
+ description: string;
2041
+ filePath: string;
2042
+ }>;
2043
+ declare function latestUserInput(input: PhaseInput): string;
2044
+ declare function conversationMessages(messages: AgentContextMessage[]): LlmMessage[];
2045
+ declare function buildModelRequest(input: PhaseInput, options?: {
2046
+ model?: LlmModelRef;
2047
+ }): LlmRequest;
2048
+
2049
+ export { AGENT_STATE_SCHEMA_VERSION, type AbortEvent, type AfterPhaseEvent, type AfterPhaseHookResult, type AfterPhaseResult, type AfterToolCall, type AfterToolCallEvent, type AfterToolCallResult, Agent, type AgentContext, type AgentEndEvent, AgentEventStream, type AgentMessage$1 as AgentMessage, type AgentMessageMetadata, AgentMessageSchema, type AgentOptions, type AgentRunLimits, type AgentStartEvent, type AgentState, type AgentStatus, type BeforePhaseEvent, type BeforePhaseHookResult, type BeforePhaseResult, type BeforePromptEvent, type BeforePromptResult, type BeforeToolCall, type BeforeToolCallEvent, type BeforeToolCallResult, type BranchSummarySessionEntry, type BuildAgentContextInput, type CompactionSessionEntry, type CoreToolContext, type CreateAgentStateInput, type CreateDefaultPhaseRegistryOptions, type CreateSessionManagerInput, type CustomSessionEntry, DEFAULT_PHASE_ID, type EventBus, EventStream, type ExecOptions, type ExecResult, type ExecutionTurn, type ExecutionTurnEntry, type ExecutionTurnSessionEntry, type Extension, type ExtensionAPI, type ExtensionContext, type ExtensionError, type ExtensionErrorListener, type ExtensionFactory, type ExtensionManifest, type ExtensionPackageManifest, ExtensionRunner, type ExtensionRunnerOptions, type ExtensionRunnerRef, type ExtensionRuntime, type ExtensionUtils, HookError, type HookEvent, type HookEventType, type HookHandler, type HookResultMap, HooksManager, InMemorySessionManager, type LoadExtensionsResult, type LoadedExtension, LocalJsonlSessionManager, type LoopMetrics, type MessageEndEvent, type MessageSessionEntry, type MessageSnapshot, type MessageStartEvent, type MessageUpdateEvent, type ModelInvokeInput, type ModelInvokeOutput, type OutcomeSessionEntry, type PhaseContext, type PhaseDefinition, type PhaseInput, type PhaseManifest, type PhaseMessageManager, type PhaseOutput, type PhaseRegistration, type PhaseRegistry, type PhaseRegistryInput, type PhaseRun, type PhaseToolExecutionManager, type PromptTool, type QueueUpdateEvent, type RegisteredPhase, type RegisteredTool, type RunOptions, type RunResult, SESSION_MANAGER_SCHEMA_VERSION, SESSION_SCHEMA_VERSION, type SavePointEvent, type SerializableTool, type Session, type SessionAgentContext, type SessionEntry, type SessionHeader, type SessionInfoSessionEntry, type SessionListItem, type SessionManager, type SessionRecord, type SettledEvent, type Skill$1 as Skill, SkillSchema, type SourceInfo, type StepFilter, type SystemPromptOptions, type Tool$1 as Tool, type ToolDefinition, type ToolExecutionEndEvent, type ToolExecutionMode$1 as ToolExecutionMode, type ToolExecutionResult, type ToolExecutionStartEvent, type ToolExecutionUpdateEvent, type TurnEndEvent, type TurnStartEvent, type Unsubscribe, type WorkspacePaths, appendUserTurn, buildModelRequest, buildSystemPrompt, conversationMessages, createAgentState, createBuiltinPhaseRegistry, createCoreTools, createDefaultPhaseRegistry, createEventBus, createExtension, createExtensionRunner, createExtensionRuntime, createId, createJson, createMessage, createPhaseRegistry, createSession, createSessionHeader, createSourceInfo, createTimestamp, definePhase, discoverAndLoadExtensions, getBuiltinExtensions, getBuiltinRunner, getGlobalHooks, isBuiltinPhaseOverride, isBuiltinSource, latestUserInput, loadExtensionFromFactory, loadExtensionFromFactorySync, loadExtensions, loadSkill, loadSkills, resetGlobalHooks, resolveInWorkspace, resolveSkillPath, resolveWorkspacePaths, serializeSkills, summarizeSessionManagerRecords };