@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.
- package/README.md +74 -0
- package/dist/index.cjs +4125 -0
- package/dist/index.d.cts +2049 -0
- package/dist/index.d.ts +2049 -0
- package/dist/index.js +4039 -0
- package/package.json +29 -0
package/dist/index.d.cts
ADDED
|
@@ -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 };
|