@rowan-agent/agent 0.5.0 → 0.5.2
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 +3 -1
- package/dist/index.d.ts +209 -180
- package/dist/index.js +69 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -264,6 +264,8 @@ Per iteration:
|
|
|
264
264
|
5. Transition, continue, or stop
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
+
**`entryPhaseId`** specifies which phase the loop enters first. When phases are loaded from `.rowan/phases/`, the first discovered phase becomes the entry. When none are configured, the Agent normalises to `"default"`. This field is an internal routing hint for the phase loop — it is **not** exposed to the LLM, since the agent does not need to know which phase is the entry point to make routing decisions.
|
|
268
|
+
|
|
267
269
|
### Example Phase Flow
|
|
268
270
|
|
|
269
271
|
```
|
|
@@ -377,7 +379,7 @@ interface PhaseContext {
|
|
|
377
379
|
messages: AgentMessage[];
|
|
378
380
|
tools: Tool[];
|
|
379
381
|
skills: Skill[];
|
|
380
|
-
state: PhaseState; // { current, available, iterations, payload }
|
|
382
|
+
state: PhaseState; // { current, available, entryPhaseId, iterations, payload }
|
|
381
383
|
}
|
|
382
384
|
|
|
383
385
|
type PhaseOutput = {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _rowan_agent_models from '@rowan-agent/models';
|
|
2
|
-
import { LlmRequest, LlmResponse, LlmModelRef, LlmModelUsage, AgentMessage,
|
|
2
|
+
import { LlmRequest, LlmResponse, LlmModelRef, LlmModelUsage, AgentMessage, ContentBlock, ToolCall, ToolResult, Outcome, ProviderConfig, Skill as Skill$1, StreamFn, AgentEventListener, Protocol, ModelCost, AgentEvent, LlmMessage } from '@rowan-agent/models';
|
|
3
3
|
export { AgentEvent, AgentEventListener, AgentMessage, LlmModelRef, Outcome, Skill, StreamFn, ToolResult, createDispatchStream, registerBuiltInApiProviders } from '@rowan-agent/models';
|
|
4
4
|
import Type from 'typebox';
|
|
5
5
|
|
|
@@ -23,87 +23,6 @@ type ModelTranscript = {
|
|
|
23
23
|
response: LlmResponse;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
type LoopMetrics = {
|
|
27
|
-
/** Number of phase iterations executed. */
|
|
28
|
-
iterations: number;
|
|
29
|
-
/** Phase transition history. */
|
|
30
|
-
phaseTransitions: Array<{
|
|
31
|
-
from: string;
|
|
32
|
-
to: string;
|
|
33
|
-
ts: string;
|
|
34
|
-
}>;
|
|
35
|
-
/** Number of times compaction was triggered. */
|
|
36
|
-
compactionCount: number;
|
|
37
|
-
/** Number of retry attempts due to transient errors. */
|
|
38
|
-
retryCount: number;
|
|
39
|
-
/** Loop start timestamp. */
|
|
40
|
-
startedAt: string;
|
|
41
|
-
/** Loop start time as epoch ms (for duration calculation). */
|
|
42
|
-
startedAtMs: number;
|
|
43
|
-
/** Loop end timestamp (set on completion). */
|
|
44
|
-
endedAt?: string;
|
|
45
|
-
/** Total wall-clock duration in ms. */
|
|
46
|
-
durationMs?: number;
|
|
47
|
-
};
|
|
48
|
-
type SessionState = {
|
|
49
|
-
currentPhase: string;
|
|
50
|
-
attempt: number;
|
|
51
|
-
metrics: LoopMetrics;
|
|
52
|
-
status: "idle" | "running" | "completed" | "aborted" | "failed";
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
type ToolContext = Pick<AgentContext, "skills"> & {
|
|
56
|
-
toolCallId: string;
|
|
57
|
-
};
|
|
58
|
-
type ToolExecutionMode = "sequential" | "parallel";
|
|
59
|
-
type Tool<TArgs = unknown> = {
|
|
60
|
-
name: string;
|
|
61
|
-
description: string;
|
|
62
|
-
parameters: Type.TSchema;
|
|
63
|
-
/** One-line snippet shown in the system prompt tool list. */
|
|
64
|
-
promptSnippet?: string;
|
|
65
|
-
/** Additional guidelines appended to the system prompt when this tool is active. */
|
|
66
|
-
promptGuidelines?: string[];
|
|
67
|
-
/** Whether this tool can run concurrently with others. Default: "parallel". */
|
|
68
|
-
executionMode?: ToolExecutionMode;
|
|
69
|
-
execute(args: TArgs, context: ToolContext, signal?: AbortSignal): Promise<ToolResult>;
|
|
70
|
-
};
|
|
71
|
-
/** Context snapshot passed into the low-level agent loop. */
|
|
72
|
-
type AgentContext = {
|
|
73
|
-
/** System prompt included with the request. */
|
|
74
|
-
systemPrompt: string;
|
|
75
|
-
/** Transcript visible to the model. */
|
|
76
|
-
messages: AgentMessage[];
|
|
77
|
-
/** Tools available for this run. */
|
|
78
|
-
tools: Tool[];
|
|
79
|
-
/** Skills available for this run. */
|
|
80
|
-
skills: Skill$1[];
|
|
81
|
-
/** Custom phases for this run. Agent normalizes this with the built-in default phase. */
|
|
82
|
-
phases?: PhaseRegistry;
|
|
83
|
-
};
|
|
84
|
-
type BeforeToolCall = (input: {
|
|
85
|
-
tool: Tool;
|
|
86
|
-
args: unknown;
|
|
87
|
-
}) => Promise<{
|
|
88
|
-
allow: true;
|
|
89
|
-
} | {
|
|
90
|
-
allow: false;
|
|
91
|
-
reason: string;
|
|
92
|
-
}>;
|
|
93
|
-
type AfterToolCall = (input: {
|
|
94
|
-
tool: Tool;
|
|
95
|
-
result: ToolResult;
|
|
96
|
-
}) => Promise<ToolResult>;
|
|
97
|
-
type RunResult = {
|
|
98
|
-
sessionId: string;
|
|
99
|
-
messages: AgentMessage[];
|
|
100
|
-
outcome: Outcome;
|
|
101
|
-
metrics: LoopMetrics;
|
|
102
|
-
};
|
|
103
|
-
type Unsubscribe = () => void;
|
|
104
|
-
declare function createMessage(role: AgentMessage["role"], content: AgentMessage["content"], metadata?: Record<string, unknown>): AgentMessage;
|
|
105
|
-
declare function messageContentText(content: AgentMessage["content"]): string;
|
|
106
|
-
|
|
107
26
|
type ModelInvokeOutput = {
|
|
108
27
|
text: string;
|
|
109
28
|
contentBlocks: ContentBlock[];
|
|
@@ -127,89 +46,6 @@ type PhaseExecution = {
|
|
|
127
46
|
executeTool(context: AgentContext, toolCall: ToolCall): Promise<ToolResult>;
|
|
128
47
|
};
|
|
129
48
|
|
|
130
|
-
/** Unified phase output — model decides routing via route. */
|
|
131
|
-
type PhaseOutput = {
|
|
132
|
-
message: string;
|
|
133
|
-
/** Route to next phase, or "continue" to re-execute current phase, or "stop" to end */
|
|
134
|
-
route: string;
|
|
135
|
-
/** Phase name that produced this output */
|
|
136
|
-
phase?: string;
|
|
137
|
-
/** Tool calls from the model invocation (used by framework for route extraction) */
|
|
138
|
-
toolCalls?: Array<{
|
|
139
|
-
id: string;
|
|
140
|
-
name: string;
|
|
141
|
-
args: unknown;
|
|
142
|
-
}>;
|
|
143
|
-
/** Route reason extracted from route tool call (for hooks to inspect) */
|
|
144
|
-
routeReason?: string;
|
|
145
|
-
/** Structured data from this phase, passed to the next phase */
|
|
146
|
-
payload?: unknown;
|
|
147
|
-
};
|
|
148
|
-
/** Phase machine state — tracks position and inter-phase data */
|
|
149
|
-
interface PhaseState {
|
|
150
|
-
current: string;
|
|
151
|
-
available: string[];
|
|
152
|
-
iterations: number;
|
|
153
|
-
payload?: unknown;
|
|
154
|
-
}
|
|
155
|
-
/** Everything a phase needs to execute */
|
|
156
|
-
interface PhaseContext {
|
|
157
|
-
systemPrompt: string;
|
|
158
|
-
messages: AgentMessage[];
|
|
159
|
-
/** Phase-filtered tools */
|
|
160
|
-
tools: Tool[];
|
|
161
|
-
/** Phase-filtered skills */
|
|
162
|
-
skills: Skill$1[];
|
|
163
|
-
/** Phase machine state */
|
|
164
|
-
state: PhaseState;
|
|
165
|
-
/** Additional guideline bullets appended to the system prompt */
|
|
166
|
-
promptGuidelines?: string[];
|
|
167
|
-
/** Text to append after the system prompt */
|
|
168
|
-
appendSystemPrompt?: string;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Loaded Phase object
|
|
172
|
-
*/
|
|
173
|
-
interface Phase {
|
|
174
|
-
/** Unique identifier */
|
|
175
|
-
id: string;
|
|
176
|
-
/** Display name */
|
|
177
|
-
name: string;
|
|
178
|
-
/** Description */
|
|
179
|
-
description: string;
|
|
180
|
-
/** Restricted tools (undefined = all tools available) */
|
|
181
|
-
tools?: string[];
|
|
182
|
-
/** Restricted skills (undefined = all skills available) */
|
|
183
|
-
skills?: string[];
|
|
184
|
-
/** Forced next phase */
|
|
185
|
-
target?: string;
|
|
186
|
-
/** Expected input fields (key → description) */
|
|
187
|
-
input?: Record<string, string>;
|
|
188
|
-
/** If true, phase gets a fresh context when executed in parallel */
|
|
189
|
-
isolated?: boolean;
|
|
190
|
-
/** Path to PHASE.md file */
|
|
191
|
-
filePath: string;
|
|
192
|
-
/** Phase directory path */
|
|
193
|
-
baseDir: string;
|
|
194
|
-
/** PHASE.md body content */
|
|
195
|
-
content: string;
|
|
196
|
-
/** Model override for this phase (resolved from frontmatter) */
|
|
197
|
-
model?: LlmModelRef;
|
|
198
|
-
/** ExtensionAPI factory function (default export pattern) */
|
|
199
|
-
factory?: (api: ExtensionAPI) => Promise<void>;
|
|
200
|
-
/** Legacy run function */
|
|
201
|
-
run?: (context: PhaseContext, execution: PhaseExecution) => Promise<PhaseOutput | void>;
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Phase registry containing all loaded phases
|
|
205
|
-
*/
|
|
206
|
-
interface PhaseRegistry {
|
|
207
|
-
/** Map of phase id to Phase object */
|
|
208
|
-
phases: Map<string, Phase>;
|
|
209
|
-
/** Entry phase id (null until Agent applies its default phase) */
|
|
210
|
-
entryPhaseId: string | null;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
49
|
/**
|
|
214
50
|
* Extension types — simplified for the new hook-based system.
|
|
215
51
|
*/
|
|
@@ -1307,10 +1143,202 @@ declare class ExtensionRunner {
|
|
|
1307
1143
|
}
|
|
1308
1144
|
declare function createExtensionRunner(options?: ExtensionRunnerOptions): ExtensionRunner;
|
|
1309
1145
|
|
|
1146
|
+
type LoopMetrics = {
|
|
1147
|
+
/** Number of phase iterations executed. */
|
|
1148
|
+
iterations: number;
|
|
1149
|
+
/** Phase transition history. */
|
|
1150
|
+
phaseTransitions: Array<{
|
|
1151
|
+
from: string;
|
|
1152
|
+
to: string;
|
|
1153
|
+
ts: string;
|
|
1154
|
+
}>;
|
|
1155
|
+
/** Number of times compaction was triggered. */
|
|
1156
|
+
compactionCount: number;
|
|
1157
|
+
/** Number of retry attempts due to transient errors. */
|
|
1158
|
+
retryCount: number;
|
|
1159
|
+
/** Loop start timestamp. */
|
|
1160
|
+
startedAt: string;
|
|
1161
|
+
/** Loop start time as epoch ms (for duration calculation). */
|
|
1162
|
+
startedAtMs: number;
|
|
1163
|
+
/** Loop end timestamp (set on completion). */
|
|
1164
|
+
endedAt?: string;
|
|
1165
|
+
/** Total wall-clock duration in ms. */
|
|
1166
|
+
durationMs?: number;
|
|
1167
|
+
};
|
|
1168
|
+
type SessionState = {
|
|
1169
|
+
currentPhase: string;
|
|
1170
|
+
attempt: number;
|
|
1171
|
+
metrics: LoopMetrics;
|
|
1172
|
+
status: "idle" | "running" | "completed" | "aborted" | "failed";
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
type ToolContext = Pick<AgentContext, "skills"> & {
|
|
1176
|
+
toolCallId: string;
|
|
1177
|
+
};
|
|
1178
|
+
type ToolExecutionMode = "sequential" | "parallel";
|
|
1179
|
+
type Tool<TArgs = unknown> = {
|
|
1180
|
+
name: string;
|
|
1181
|
+
description: string;
|
|
1182
|
+
parameters: Type.TSchema;
|
|
1183
|
+
/** One-line snippet shown in the system prompt tool list. */
|
|
1184
|
+
promptSnippet?: string;
|
|
1185
|
+
/** Additional guidelines appended to the system prompt when this tool is active. */
|
|
1186
|
+
promptGuidelines?: string[];
|
|
1187
|
+
/** Whether this tool can run concurrently with others. Default: "parallel". */
|
|
1188
|
+
executionMode?: ToolExecutionMode;
|
|
1189
|
+
execute(args: TArgs, context: ToolContext, signal?: AbortSignal): Promise<ToolResult>;
|
|
1190
|
+
};
|
|
1191
|
+
/** Context snapshot passed into the low-level agent loop. */
|
|
1192
|
+
type AgentContext = {
|
|
1193
|
+
/** System prompt included with the request. */
|
|
1194
|
+
systemPrompt: string;
|
|
1195
|
+
/** Transcript visible to the model. */
|
|
1196
|
+
messages: AgentMessage[];
|
|
1197
|
+
/** Tools available for this run. */
|
|
1198
|
+
tools: Tool[];
|
|
1199
|
+
/** Skills available for this run. */
|
|
1200
|
+
skills: Skill$1[];
|
|
1201
|
+
/** Custom phases for this run. Agent normalizes this with the built-in default phase. */
|
|
1202
|
+
phases?: PhaseRegistry;
|
|
1203
|
+
};
|
|
1204
|
+
type BeforeToolCall = (input: {
|
|
1205
|
+
tool: Tool;
|
|
1206
|
+
args: unknown;
|
|
1207
|
+
}) => Promise<{
|
|
1208
|
+
allow: true;
|
|
1209
|
+
} | {
|
|
1210
|
+
allow: false;
|
|
1211
|
+
reason: string;
|
|
1212
|
+
}>;
|
|
1213
|
+
type AfterToolCall = (input: {
|
|
1214
|
+
tool: Tool;
|
|
1215
|
+
result: ToolResult;
|
|
1216
|
+
}) => Promise<ToolResult>;
|
|
1217
|
+
type RunResult = {
|
|
1218
|
+
sessionId: string;
|
|
1219
|
+
messages: AgentMessage[];
|
|
1220
|
+
outcome: Outcome;
|
|
1221
|
+
metrics: LoopMetrics;
|
|
1222
|
+
};
|
|
1223
|
+
type Unsubscribe = () => void;
|
|
1224
|
+
declare function createMessage(role: AgentMessage["role"], content: AgentMessage["content"], metadata?: Record<string, unknown>): AgentMessage;
|
|
1225
|
+
declare function messageContentText(content: AgentMessage["content"]): string;
|
|
1226
|
+
|
|
1227
|
+
/** Unified phase output — model decides routing via route. */
|
|
1228
|
+
type PhaseOutput = {
|
|
1229
|
+
message: string;
|
|
1230
|
+
/** Route to next phase, or "continue" to re-execute current phase, or "stop" to end */
|
|
1231
|
+
route: string;
|
|
1232
|
+
/** Phase name that produced this output */
|
|
1233
|
+
phase?: string;
|
|
1234
|
+
/** Tool calls from the model invocation (used by framework for route extraction) */
|
|
1235
|
+
toolCalls?: Array<{
|
|
1236
|
+
id: string;
|
|
1237
|
+
name: string;
|
|
1238
|
+
args: unknown;
|
|
1239
|
+
}>;
|
|
1240
|
+
/** Route reason extracted from route tool call (for hooks to inspect) */
|
|
1241
|
+
routeReason?: string;
|
|
1242
|
+
/** Structured data from this phase, passed to the next phase */
|
|
1243
|
+
payload?: unknown;
|
|
1244
|
+
};
|
|
1245
|
+
/** Phase machine state — tracks position and inter-phase data */
|
|
1246
|
+
interface PhaseState {
|
|
1247
|
+
current: string;
|
|
1248
|
+
available: string[];
|
|
1249
|
+
iterations: number;
|
|
1250
|
+
payload?: unknown;
|
|
1251
|
+
}
|
|
1252
|
+
/** Everything a phase needs to execute */
|
|
1253
|
+
interface PhaseContext {
|
|
1254
|
+
systemPrompt: string;
|
|
1255
|
+
messages: AgentMessage[];
|
|
1256
|
+
/** Phase-filtered tools */
|
|
1257
|
+
tools: Tool[];
|
|
1258
|
+
/** Phase-filtered skills */
|
|
1259
|
+
skills: Skill$1[];
|
|
1260
|
+
/** Phase machine state */
|
|
1261
|
+
state: PhaseState;
|
|
1262
|
+
/** Additional guideline bullets appended to the system prompt */
|
|
1263
|
+
promptGuidelines?: string[];
|
|
1264
|
+
/** Text to append after the system prompt */
|
|
1265
|
+
appendSystemPrompt?: string;
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Loaded Phase object
|
|
1269
|
+
*/
|
|
1270
|
+
interface Phase {
|
|
1271
|
+
/** Unique identifier */
|
|
1272
|
+
id: string;
|
|
1273
|
+
/** Display name */
|
|
1274
|
+
name: string;
|
|
1275
|
+
/** Description */
|
|
1276
|
+
description: string;
|
|
1277
|
+
/** Restricted tools (undefined = all tools available) */
|
|
1278
|
+
tools?: string[];
|
|
1279
|
+
/** Restricted skills (undefined = all skills available) */
|
|
1280
|
+
skills?: string[];
|
|
1281
|
+
/** Forced next phase */
|
|
1282
|
+
target?: string;
|
|
1283
|
+
/** Expected input fields (key → description) */
|
|
1284
|
+
input?: Record<string, string>;
|
|
1285
|
+
/** If true, phase gets a fresh context when executed in parallel */
|
|
1286
|
+
isolated?: boolean;
|
|
1287
|
+
/** Path to PHASE.md file */
|
|
1288
|
+
filePath: string;
|
|
1289
|
+
/** Phase directory path */
|
|
1290
|
+
baseDir: string;
|
|
1291
|
+
/** PHASE.md body content */
|
|
1292
|
+
content: string;
|
|
1293
|
+
/** Model override for this phase (resolved from frontmatter) */
|
|
1294
|
+
model?: LlmModelRef;
|
|
1295
|
+
/** ExtensionAPI factory function (default export pattern) */
|
|
1296
|
+
factory?: (api: ExtensionAPI) => Promise<void>;
|
|
1297
|
+
/** Legacy run function */
|
|
1298
|
+
run?: (context: PhaseContext, execution: PhaseExecution) => Promise<PhaseOutput | void>;
|
|
1299
|
+
}
|
|
1300
|
+
/**
|
|
1301
|
+
* Phase registry containing all loaded phases
|
|
1302
|
+
*/
|
|
1303
|
+
interface PhaseRegistry {
|
|
1304
|
+
/** Map of phase id to Phase object */
|
|
1305
|
+
phases: Map<string, Phase>;
|
|
1306
|
+
/** Entry phase id (null until Agent applies its default phase) */
|
|
1307
|
+
entryPhaseId: string | null;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
type WorkspacePaths = {
|
|
1311
|
+
cwd: string;
|
|
1312
|
+
rowanDir: string;
|
|
1313
|
+
};
|
|
1314
|
+
type ResolveWorkspaceOptions = {
|
|
1315
|
+
cwd?: string;
|
|
1316
|
+
env?: NodeJS.ProcessEnv;
|
|
1317
|
+
homeDir?: string;
|
|
1318
|
+
rowanDir?: string;
|
|
1319
|
+
};
|
|
1320
|
+
declare function resolveWorkspacePaths(options?: ResolveWorkspaceOptions): WorkspacePaths;
|
|
1321
|
+
declare function resolveInWorkspace(path: string, rootOrPaths: string | Pick<WorkspacePaths, "cwd">): string;
|
|
1322
|
+
|
|
1323
|
+
type PhaseLoadTarget = string | Pick<WorkspacePaths, "rowanDir">;
|
|
1324
|
+
/**
|
|
1325
|
+
* Load a single phase from a PHASE.md file or phase directory.
|
|
1326
|
+
*
|
|
1327
|
+
* If a directory is provided, the loader reads its PHASE.md.
|
|
1328
|
+
*/
|
|
1329
|
+
declare function loadPhase(targetPath: string): Promise<Phase>;
|
|
1330
|
+
declare function loadPhases(targetPath: PhaseLoadTarget): Promise<PhaseRegistry>;
|
|
1331
|
+
/**
|
|
1332
|
+
* Re-read all file-based phases from disk and update the registry in place.
|
|
1333
|
+
* Extension-registered phases (with empty filePath) are preserved as-is.
|
|
1334
|
+
*/
|
|
1335
|
+
declare function reloadPhases(registry: PhaseRegistry): Promise<void>;
|
|
1336
|
+
|
|
1310
1337
|
type AgentOptions = {
|
|
1311
1338
|
context: AgentContext;
|
|
1312
1339
|
model: LlmModelRef;
|
|
1313
1340
|
stream: StreamFn;
|
|
1341
|
+
cwd?: string;
|
|
1314
1342
|
extensions?: LoadedExtension[];
|
|
1315
1343
|
sessionId?: string;
|
|
1316
1344
|
maxAttempts?: number;
|
|
@@ -1342,8 +1370,9 @@ declare class Agent {
|
|
|
1342
1370
|
private activeRun?;
|
|
1343
1371
|
private extensionRunner?;
|
|
1344
1372
|
private loadedExtensions?;
|
|
1373
|
+
private loadedExtensionsCwd?;
|
|
1345
1374
|
static loadSkills(targetPath: string): Promise<AgentContext["skills"]>;
|
|
1346
|
-
static loadPhases(targetPath:
|
|
1375
|
+
static loadPhases(targetPath: Parameters<typeof loadPhases>[0]): Promise<PhaseRegistry>;
|
|
1347
1376
|
static loadExtensions(targetPath: string): Promise<LoadExtensionsResult>;
|
|
1348
1377
|
constructor(options: AgentOptions);
|
|
1349
1378
|
subscribe(listener: AgentEventListener): Unsubscribe;
|
|
@@ -1614,19 +1643,6 @@ type CoreToolContext = {
|
|
|
1614
1643
|
};
|
|
1615
1644
|
declare function createCoreTools(input?: CoreToolContext): Tool[];
|
|
1616
1645
|
|
|
1617
|
-
type WorkspacePaths = {
|
|
1618
|
-
cwd: string;
|
|
1619
|
-
rowanDir: string;
|
|
1620
|
-
};
|
|
1621
|
-
type ResolveWorkspaceOptions = {
|
|
1622
|
-
cwd?: string;
|
|
1623
|
-
env?: NodeJS.ProcessEnv;
|
|
1624
|
-
homeDir?: string;
|
|
1625
|
-
rowanDir?: string;
|
|
1626
|
-
};
|
|
1627
|
-
declare function resolveWorkspacePaths(options?: ResolveWorkspaceOptions): WorkspacePaths;
|
|
1628
|
-
declare function resolveInWorkspace(path: string, rootOrPaths: string | Pick<WorkspacePaths, "cwd">): string;
|
|
1629
|
-
|
|
1630
1646
|
type ModelConfigFromFile = {
|
|
1631
1647
|
id: string;
|
|
1632
1648
|
name?: string;
|
|
@@ -1693,6 +1709,19 @@ declare class AgentEventStream extends EventStream<AgentEvent, AgentMessage[]> {
|
|
|
1693
1709
|
constructor();
|
|
1694
1710
|
}
|
|
1695
1711
|
|
|
1712
|
+
/** Error thrown when the model returns an empty response (no text, no tool calls). */
|
|
1713
|
+
declare class EmptyResponseError extends Error {
|
|
1714
|
+
readonly code = "empty_response";
|
|
1715
|
+
constructor(message?: string);
|
|
1716
|
+
}
|
|
1717
|
+
/** Error thrown when a routed phase needs a route tool call but the model did not emit one. */
|
|
1718
|
+
declare class MissingRouteToolCallError extends Error {
|
|
1719
|
+
readonly code = "missing_route_tool_call";
|
|
1720
|
+
readonly phase: string;
|
|
1721
|
+
readonly toolCallNames: string[];
|
|
1722
|
+
constructor(phase: string, toolCallNames: string[]);
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1696
1725
|
interface SystemPromptOptions {
|
|
1697
1726
|
/** Base system prompt. */
|
|
1698
1727
|
systemPrompt: string;
|
|
@@ -1746,4 +1775,4 @@ declare function buildModelRequest(input: ModelRequestInput, options?: {
|
|
|
1746
1775
|
model?: LlmModelRef;
|
|
1747
1776
|
}): LlmRequest;
|
|
1748
1777
|
|
|
1749
|
-
export { type AbortEvent, type AfterPhaseEvent, type AfterPhaseHookResult, type AfterPhaseResult, type AfterToolCallEvent, type AfterToolCallResult, Agent, type AgentConfigFile, type AgentContext, type AgentEndEvent, AgentEventStream, type AgentOptions, type AgentStartEvent, type AgentStatus, type BeforePhaseEvent, type BeforePhaseHookResult, type BeforePhaseResult, type BeforePromptEvent, type BeforePromptResult, type BeforeToolCallEvent, type BeforeToolCallResult, type EventBus, EventStream, type ExecOptions, type ExecResult, type ExecutionTurn, type Extension, type ExtensionAPI, type ExtensionContext, type ExtensionError, type ExtensionErrorListener, type ExtensionFactory, type ExtensionManifest, type ExtensionPackageManifest, ExtensionRunner, type ExtensionRunnerOptions, type ExtensionRuntime, type ExtensionUtils, HookError, type HookEvent, type HookEventType, type HookHandler, type HookResultMap, HooksManager, type LoadExtensionsResult, type LoadedExtension, LocalJsonlSessionManager, type LoopMetrics, type MessageEndEvent, type MessageStartEvent, type MessageUpdateEvent, type ModelConfigFromFile, type ModelTranscript, type Phase, type PhaseContext, type PhaseDefinition, type PhaseExecution, type PhaseOutput, type PhaseRegistration, type PhaseRegistry, type PhaseRun, type PhaseState, type ProviderConfigFromFile, type QueueUpdateEvent, type RegisteredPhase, type RegisteredTool, type RunOptions, type RunResult, type SavePointEvent, type Session, type SessionListItem, type SettledEvent, type SourceInfo, type Tool, type ToolDefinition, type ToolExecutionEndEvent, type ToolExecutionResult, type ToolExecutionStartEvent, type ToolExecutionUpdateEvent, type TurnEndEvent, type TurnStartEvent, type WorkspacePaths, appendUserTurn, buildModelRequest, buildSystemPrompt, conversationMessages, createCoreTools, createEventBus, createExtension, createExtensionAPI, createExtensionRunner, createExtensionRuntime, createId, createMessage, createSession, createSourceInfo, createTimestamp, getGlobalHooks, interpolateEnvVars, latestUserInput, loadConfigFile, messageContentText, parseModelRef, registerConfigModels, resetGlobalHooks, resolveDefaultModel, resolveInWorkspace, resolveWorkspacePaths, serializeSkills };
|
|
1778
|
+
export { type AbortEvent, type AfterPhaseEvent, type AfterPhaseHookResult, type AfterPhaseResult, type AfterToolCallEvent, type AfterToolCallResult, Agent, type AgentConfigFile, type AgentContext, type AgentEndEvent, AgentEventStream, type AgentOptions, type AgentStartEvent, type AgentStatus, type BeforePhaseEvent, type BeforePhaseHookResult, type BeforePhaseResult, type BeforePromptEvent, type BeforePromptResult, type BeforeToolCallEvent, type BeforeToolCallResult, EmptyResponseError, type EventBus, EventStream, type ExecOptions, type ExecResult, type ExecutionTurn, type Extension, type ExtensionAPI, type ExtensionContext, type ExtensionError, type ExtensionErrorListener, type ExtensionFactory, type ExtensionManifest, type ExtensionPackageManifest, ExtensionRunner, type ExtensionRunnerOptions, type ExtensionRuntime, type ExtensionUtils, HookError, type HookEvent, type HookEventType, type HookHandler, type HookResultMap, HooksManager, type LoadExtensionsResult, type LoadedExtension, LocalJsonlSessionManager, type LoopMetrics, type MessageEndEvent, type MessageStartEvent, type MessageUpdateEvent, MissingRouteToolCallError, type ModelConfigFromFile, type ModelTranscript, type Phase, type PhaseContext, type PhaseDefinition, type PhaseExecution, type PhaseOutput, type PhaseRegistration, type PhaseRegistry, type PhaseRun, type PhaseState, type ProviderConfigFromFile, type QueueUpdateEvent, type RegisteredPhase, type RegisteredTool, type RunOptions, type RunResult, type SavePointEvent, type Session, type SessionListItem, type SettledEvent, type SourceInfo, type Tool, type ToolDefinition, type ToolExecutionEndEvent, type ToolExecutionResult, type ToolExecutionStartEvent, type ToolExecutionUpdateEvent, type TurnEndEvent, type TurnStartEvent, type WorkspacePaths, appendUserTurn, buildModelRequest, buildSystemPrompt, conversationMessages, createCoreTools, createEventBus, createExtension, createExtensionAPI, createExtensionRunner, createExtensionRuntime, createId, createMessage, createSession, createSourceInfo, createTimestamp, getGlobalHooks, interpolateEnvVars, latestUserInput, loadConfigFile, loadPhase, loadPhases, messageContentText, parseModelRef, registerConfigModels, reloadPhases, resetGlobalHooks, resolveDefaultModel, resolveInWorkspace, resolveWorkspacePaths, serializeSkills };
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,19 @@ var EmptyResponseError = class extends Error {
|
|
|
21
21
|
this.name = "EmptyResponseError";
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
+
var MissingRouteToolCallError = class extends Error {
|
|
25
|
+
code = "missing_route_tool_call";
|
|
26
|
+
phase;
|
|
27
|
+
toolCallNames;
|
|
28
|
+
constructor(phase, toolCallNames) {
|
|
29
|
+
super(
|
|
30
|
+
`Phase "${phase}" requires a route tool call, but the model did not emit one.`
|
|
31
|
+
);
|
|
32
|
+
this.name = "MissingRouteToolCallError";
|
|
33
|
+
this.phase = phase;
|
|
34
|
+
this.toolCallNames = toolCallNames;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
24
37
|
var LoopGuard = {
|
|
25
38
|
/** Returns abort result if signal is aborted */
|
|
26
39
|
checkAbort(signal) {
|
|
@@ -81,6 +94,9 @@ var createOutcome = {
|
|
|
81
94
|
id: createId("out"),
|
|
82
95
|
message
|
|
83
96
|
};
|
|
97
|
+
if (output.payload !== void 0) {
|
|
98
|
+
outcome.payload = output.payload;
|
|
99
|
+
}
|
|
84
100
|
if (toolResults.length > 0) {
|
|
85
101
|
outcome.toolResults = toolResults;
|
|
86
102
|
}
|
|
@@ -747,9 +763,12 @@ function readPhaseContent(phase) {
|
|
|
747
763
|
baseDir: phase.baseDir
|
|
748
764
|
});
|
|
749
765
|
}
|
|
766
|
+
function resolvePhaseLoadTarget(targetPath) {
|
|
767
|
+
return typeof targetPath === "string" ? targetPath : join2(targetPath.rowanDir, "phases");
|
|
768
|
+
}
|
|
750
769
|
async function loadPhases(targetPath) {
|
|
751
770
|
const phases = /* @__PURE__ */ new Map();
|
|
752
|
-
const phasesDir = resolve(targetPath);
|
|
771
|
+
const phasesDir = resolve(resolvePhaseLoadTarget(targetPath));
|
|
753
772
|
if (existsSync2(phasesDir) && statSync(phasesDir).isFile()) {
|
|
754
773
|
const phase = await loadPhase(phasesDir);
|
|
755
774
|
phases.set(phase.id, phase);
|
|
@@ -799,6 +818,19 @@ async function loadPhaseCode(codePath) {
|
|
|
799
818
|
}
|
|
800
819
|
throw new Error(`Phase code at "${codePath}" must export a default function or a run() function.`);
|
|
801
820
|
}
|
|
821
|
+
async function reloadPhases(registry) {
|
|
822
|
+
for (const [id, phase] of registry.phases) {
|
|
823
|
+
if (!phase.filePath) {
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
try {
|
|
827
|
+
const fresh = await loadPhase(phase.filePath);
|
|
828
|
+
registry.phases.set(id, fresh);
|
|
829
|
+
} catch (error) {
|
|
830
|
+
console.warn(`Failed to reload phase "${id}":`, error);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
802
834
|
|
|
803
835
|
// src/harness/phases/default.ts
|
|
804
836
|
var DEFAULT_PHASE_ID = "default";
|
|
@@ -1956,6 +1988,14 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
1956
1988
|
output = extAfter.output;
|
|
1957
1989
|
}
|
|
1958
1990
|
}
|
|
1991
|
+
const routeToolAvailable = phaseContext.tools.some((tool) => tool.name === PhaseRouteTool);
|
|
1992
|
+
const routeRequired = !phase.target && !phase.run && !phase.factory && routeToolAvailable && registry.phases.size > 1;
|
|
1993
|
+
if (routeRequired && !routeDecision) {
|
|
1994
|
+
throw new MissingRouteToolCallError(
|
|
1995
|
+
currentPhaseId,
|
|
1996
|
+
output.toolCalls?.map((toolCall) => toolCall.name) ?? []
|
|
1997
|
+
);
|
|
1998
|
+
}
|
|
1959
1999
|
if (output.route === "continue") {
|
|
1960
2000
|
isContinuing = true;
|
|
1961
2001
|
continue;
|
|
@@ -3378,6 +3418,7 @@ var Agent = class {
|
|
|
3378
3418
|
activeRun;
|
|
3379
3419
|
extensionRunner;
|
|
3380
3420
|
loadedExtensions;
|
|
3421
|
+
loadedExtensionsCwd;
|
|
3381
3422
|
static loadSkills(targetPath) {
|
|
3382
3423
|
return loadSkills(targetPath);
|
|
3383
3424
|
}
|
|
@@ -3388,14 +3429,14 @@ var Agent = class {
|
|
|
3388
3429
|
return loadExtensionsFromPath(targetPath);
|
|
3389
3430
|
}
|
|
3390
3431
|
constructor(options) {
|
|
3391
|
-
const context =
|
|
3432
|
+
const context = prepareAgentContext(options.context);
|
|
3392
3433
|
this.options = {
|
|
3393
3434
|
...options,
|
|
3394
3435
|
context
|
|
3395
3436
|
};
|
|
3396
3437
|
this.state = {
|
|
3397
3438
|
...this.options.sessionId ? { sessionId: this.options.sessionId } : {},
|
|
3398
|
-
context:
|
|
3439
|
+
context: prepareAgentContext(context),
|
|
3399
3440
|
model: this.options.model,
|
|
3400
3441
|
tools: this.options.context.tools ?? [],
|
|
3401
3442
|
isRunning: false
|
|
@@ -3529,28 +3570,30 @@ var Agent = class {
|
|
|
3529
3570
|
this.state.isRunning = false;
|
|
3530
3571
|
this.activeRun = void 0;
|
|
3531
3572
|
}
|
|
3532
|
-
async loadExtensions(extensions) {
|
|
3573
|
+
async loadExtensions(extensions, cwd) {
|
|
3533
3574
|
if (extensions.length === 0) {
|
|
3534
3575
|
this.extensionRunner?.invalidate();
|
|
3535
3576
|
this.extensionRunner = void 0;
|
|
3536
3577
|
this.loadedExtensions = extensions;
|
|
3578
|
+
this.loadedExtensionsCwd = cwd;
|
|
3537
3579
|
return;
|
|
3538
3580
|
}
|
|
3539
|
-
if (this.extensionRunner && this.loadedExtensions === extensions) {
|
|
3581
|
+
if (this.extensionRunner && this.loadedExtensions === extensions && this.loadedExtensionsCwd === cwd) {
|
|
3540
3582
|
return;
|
|
3541
3583
|
}
|
|
3542
|
-
const runner = createExtensionRunner();
|
|
3584
|
+
const runner = createExtensionRunner({ cwd });
|
|
3543
3585
|
await runner.loadExtensions(extensions);
|
|
3544
3586
|
runner.bind();
|
|
3545
3587
|
this.extensionRunner?.invalidate();
|
|
3546
3588
|
this.extensionRunner = runner;
|
|
3547
3589
|
this.loadedExtensions = extensions;
|
|
3590
|
+
this.loadedExtensionsCwd = cwd;
|
|
3548
3591
|
}
|
|
3549
3592
|
async run(config) {
|
|
3550
|
-
const extensions = config?.extensions ?? this.options.extensions ?? [];
|
|
3551
|
-
await this.loadExtensions(extensions);
|
|
3552
3593
|
const resolved = this.resolveRunConfig(config);
|
|
3553
|
-
const
|
|
3594
|
+
const extensions = resolved.extensions ?? [];
|
|
3595
|
+
await this.loadExtensions(extensions, resolved.cwd);
|
|
3596
|
+
const runContext = prepareAgentContext(resolved.context, this.extensionRunner);
|
|
3554
3597
|
const sessionId = resolved.sessionId ?? this.state.sessionId;
|
|
3555
3598
|
this.options = resolved;
|
|
3556
3599
|
if (sessionId) {
|
|
@@ -3601,11 +3644,11 @@ var Agent = class {
|
|
|
3601
3644
|
onModelTranscript: resolved.onModelTranscript
|
|
3602
3645
|
});
|
|
3603
3646
|
const nextContext = {
|
|
3604
|
-
...
|
|
3647
|
+
...prepareAgentContext(resolved.context),
|
|
3605
3648
|
messages: snapshotMessages(result.messages)
|
|
3606
3649
|
};
|
|
3607
3650
|
this.state.sessionId = result.sessionId;
|
|
3608
|
-
this.state.context =
|
|
3651
|
+
this.state.context = prepareAgentContext(nextContext, this.extensionRunner);
|
|
3609
3652
|
this.state.currentResult = result;
|
|
3610
3653
|
this.options = {
|
|
3611
3654
|
...resolved,
|
|
@@ -3648,8 +3691,8 @@ ${additionalInstructions}` : content;
|
|
|
3648
3691
|
* @returns Formatted phase content string, or empty string if not found
|
|
3649
3692
|
*/
|
|
3650
3693
|
async phase(name) {
|
|
3651
|
-
await this.loadExtensions(this.options.extensions ?? []);
|
|
3652
|
-
const registry =
|
|
3694
|
+
await this.loadExtensions(this.options.extensions ?? [], this.options.cwd);
|
|
3695
|
+
const registry = prepareAgentContext(this.options.context, this.extensionRunner).phases?.phases;
|
|
3653
3696
|
const phase = registry?.get(name) ?? [...registry?.values() ?? []].find((candidate) => candidate.name === name);
|
|
3654
3697
|
return phase ? readPhaseContent(phase) : "";
|
|
3655
3698
|
}
|
|
@@ -3661,19 +3704,22 @@ ${additionalInstructions}` : content;
|
|
|
3661
3704
|
await this.flushEvents().catch(() => void 0);
|
|
3662
3705
|
}
|
|
3663
3706
|
resolveRunConfig(config) {
|
|
3664
|
-
const
|
|
3665
|
-
return {
|
|
3707
|
+
const merged = {
|
|
3666
3708
|
...this.options,
|
|
3667
|
-
...config
|
|
3709
|
+
...config
|
|
3710
|
+
};
|
|
3711
|
+
const context = prepareAgentContext(config?.context ?? this.createContextSnapshot());
|
|
3712
|
+
return {
|
|
3713
|
+
...merged,
|
|
3668
3714
|
context,
|
|
3669
3715
|
sessionId: config?.sessionId ?? this.state.sessionId ?? this.options.sessionId
|
|
3670
3716
|
};
|
|
3671
3717
|
}
|
|
3672
3718
|
createContextSnapshot() {
|
|
3673
|
-
return
|
|
3719
|
+
return prepareAgentContext(this.options.context);
|
|
3674
3720
|
}
|
|
3675
3721
|
};
|
|
3676
|
-
function
|
|
3722
|
+
function prepareAgentContext(context, extensionRunner) {
|
|
3677
3723
|
const phases = /* @__PURE__ */ new Map();
|
|
3678
3724
|
phases.set(DEFAULT_PHASE_ID, createDefaultPhase());
|
|
3679
3725
|
for (const [id, phase] of context.phases?.phases ?? []) {
|
|
@@ -4222,10 +4268,12 @@ import {
|
|
|
4222
4268
|
export {
|
|
4223
4269
|
Agent,
|
|
4224
4270
|
AgentEventStream,
|
|
4271
|
+
EmptyResponseError,
|
|
4225
4272
|
EventStream,
|
|
4226
4273
|
ExtensionRunner,
|
|
4227
4274
|
HooksManager,
|
|
4228
4275
|
LocalJsonlSessionManager,
|
|
4276
|
+
MissingRouteToolCallError,
|
|
4229
4277
|
appendUserTurn,
|
|
4230
4278
|
buildModelRequest,
|
|
4231
4279
|
buildSystemPrompt,
|
|
@@ -4246,10 +4294,13 @@ export {
|
|
|
4246
4294
|
interpolateEnvVars,
|
|
4247
4295
|
latestUserInput,
|
|
4248
4296
|
loadConfigFile,
|
|
4297
|
+
loadPhase,
|
|
4298
|
+
loadPhases,
|
|
4249
4299
|
messageContentText,
|
|
4250
4300
|
parseModelRef,
|
|
4251
4301
|
registerBuiltInApiProviders,
|
|
4252
4302
|
registerConfigModels,
|
|
4303
|
+
reloadPhases,
|
|
4253
4304
|
resetGlobalHooks,
|
|
4254
4305
|
resolveDefaultModel,
|
|
4255
4306
|
resolveInWorkspace,
|