@rowan-agent/agent 0.5.0 → 0.5.1
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 +57 -9
- 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) {
|
|
@@ -747,9 +760,12 @@ function readPhaseContent(phase) {
|
|
|
747
760
|
baseDir: phase.baseDir
|
|
748
761
|
});
|
|
749
762
|
}
|
|
763
|
+
function resolvePhaseLoadTarget(targetPath) {
|
|
764
|
+
return typeof targetPath === "string" ? targetPath : join2(targetPath.rowanDir, "phases");
|
|
765
|
+
}
|
|
750
766
|
async function loadPhases(targetPath) {
|
|
751
767
|
const phases = /* @__PURE__ */ new Map();
|
|
752
|
-
const phasesDir = resolve(targetPath);
|
|
768
|
+
const phasesDir = resolve(resolvePhaseLoadTarget(targetPath));
|
|
753
769
|
if (existsSync2(phasesDir) && statSync(phasesDir).isFile()) {
|
|
754
770
|
const phase = await loadPhase(phasesDir);
|
|
755
771
|
phases.set(phase.id, phase);
|
|
@@ -799,6 +815,19 @@ async function loadPhaseCode(codePath) {
|
|
|
799
815
|
}
|
|
800
816
|
throw new Error(`Phase code at "${codePath}" must export a default function or a run() function.`);
|
|
801
817
|
}
|
|
818
|
+
async function reloadPhases(registry) {
|
|
819
|
+
for (const [id, phase] of registry.phases) {
|
|
820
|
+
if (!phase.filePath) {
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
823
|
+
try {
|
|
824
|
+
const fresh = await loadPhase(phase.filePath);
|
|
825
|
+
registry.phases.set(id, fresh);
|
|
826
|
+
} catch (error) {
|
|
827
|
+
console.warn(`Failed to reload phase "${id}":`, error);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
802
831
|
|
|
803
832
|
// src/harness/phases/default.ts
|
|
804
833
|
var DEFAULT_PHASE_ID = "default";
|
|
@@ -1956,6 +1985,14 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
1956
1985
|
output = extAfter.output;
|
|
1957
1986
|
}
|
|
1958
1987
|
}
|
|
1988
|
+
const routeToolAvailable = phaseContext.tools.some((tool) => tool.name === PhaseRouteTool);
|
|
1989
|
+
const routeRequired = !phase.target && !phase.run && !phase.factory && routeToolAvailable && registry.phases.size > 1;
|
|
1990
|
+
if (routeRequired && !routeDecision) {
|
|
1991
|
+
throw new MissingRouteToolCallError(
|
|
1992
|
+
currentPhaseId,
|
|
1993
|
+
output.toolCalls?.map((toolCall) => toolCall.name) ?? []
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1959
1996
|
if (output.route === "continue") {
|
|
1960
1997
|
isContinuing = true;
|
|
1961
1998
|
continue;
|
|
@@ -3378,6 +3415,7 @@ var Agent = class {
|
|
|
3378
3415
|
activeRun;
|
|
3379
3416
|
extensionRunner;
|
|
3380
3417
|
loadedExtensions;
|
|
3418
|
+
loadedExtensionsCwd;
|
|
3381
3419
|
static loadSkills(targetPath) {
|
|
3382
3420
|
return loadSkills(targetPath);
|
|
3383
3421
|
}
|
|
@@ -3529,27 +3567,29 @@ var Agent = class {
|
|
|
3529
3567
|
this.state.isRunning = false;
|
|
3530
3568
|
this.activeRun = void 0;
|
|
3531
3569
|
}
|
|
3532
|
-
async loadExtensions(extensions) {
|
|
3570
|
+
async loadExtensions(extensions, cwd) {
|
|
3533
3571
|
if (extensions.length === 0) {
|
|
3534
3572
|
this.extensionRunner?.invalidate();
|
|
3535
3573
|
this.extensionRunner = void 0;
|
|
3536
3574
|
this.loadedExtensions = extensions;
|
|
3575
|
+
this.loadedExtensionsCwd = cwd;
|
|
3537
3576
|
return;
|
|
3538
3577
|
}
|
|
3539
|
-
if (this.extensionRunner && this.loadedExtensions === extensions) {
|
|
3578
|
+
if (this.extensionRunner && this.loadedExtensions === extensions && this.loadedExtensionsCwd === cwd) {
|
|
3540
3579
|
return;
|
|
3541
3580
|
}
|
|
3542
|
-
const runner = createExtensionRunner();
|
|
3581
|
+
const runner = createExtensionRunner({ cwd });
|
|
3543
3582
|
await runner.loadExtensions(extensions);
|
|
3544
3583
|
runner.bind();
|
|
3545
3584
|
this.extensionRunner?.invalidate();
|
|
3546
3585
|
this.extensionRunner = runner;
|
|
3547
3586
|
this.loadedExtensions = extensions;
|
|
3587
|
+
this.loadedExtensionsCwd = cwd;
|
|
3548
3588
|
}
|
|
3549
3589
|
async run(config) {
|
|
3550
|
-
const extensions = config?.extensions ?? this.options.extensions ?? [];
|
|
3551
|
-
await this.loadExtensions(extensions);
|
|
3552
3590
|
const resolved = this.resolveRunConfig(config);
|
|
3591
|
+
const extensions = resolved.extensions ?? [];
|
|
3592
|
+
await this.loadExtensions(extensions, resolved.cwd);
|
|
3553
3593
|
const runContext = cloneAgentContext(resolved.context, this.extensionRunner);
|
|
3554
3594
|
const sessionId = resolved.sessionId ?? this.state.sessionId;
|
|
3555
3595
|
this.options = resolved;
|
|
@@ -3648,7 +3688,7 @@ ${additionalInstructions}` : content;
|
|
|
3648
3688
|
* @returns Formatted phase content string, or empty string if not found
|
|
3649
3689
|
*/
|
|
3650
3690
|
async phase(name) {
|
|
3651
|
-
await this.loadExtensions(this.options.extensions ?? []);
|
|
3691
|
+
await this.loadExtensions(this.options.extensions ?? [], this.options.cwd);
|
|
3652
3692
|
const registry = cloneAgentContext(this.options.context, this.extensionRunner).phases?.phases;
|
|
3653
3693
|
const phase = registry?.get(name) ?? [...registry?.values() ?? []].find((candidate) => candidate.name === name);
|
|
3654
3694
|
return phase ? readPhaseContent(phase) : "";
|
|
@@ -3661,10 +3701,13 @@ ${additionalInstructions}` : content;
|
|
|
3661
3701
|
await this.flushEvents().catch(() => void 0);
|
|
3662
3702
|
}
|
|
3663
3703
|
resolveRunConfig(config) {
|
|
3704
|
+
const merged = {
|
|
3705
|
+
...this.options,
|
|
3706
|
+
...config
|
|
3707
|
+
};
|
|
3664
3708
|
const context = cloneAgentContext(config?.context ?? this.createContextSnapshot());
|
|
3665
3709
|
return {
|
|
3666
|
-
...
|
|
3667
|
-
...config,
|
|
3710
|
+
...merged,
|
|
3668
3711
|
context,
|
|
3669
3712
|
sessionId: config?.sessionId ?? this.state.sessionId ?? this.options.sessionId
|
|
3670
3713
|
};
|
|
@@ -4222,10 +4265,12 @@ import {
|
|
|
4222
4265
|
export {
|
|
4223
4266
|
Agent,
|
|
4224
4267
|
AgentEventStream,
|
|
4268
|
+
EmptyResponseError,
|
|
4225
4269
|
EventStream,
|
|
4226
4270
|
ExtensionRunner,
|
|
4227
4271
|
HooksManager,
|
|
4228
4272
|
LocalJsonlSessionManager,
|
|
4273
|
+
MissingRouteToolCallError,
|
|
4229
4274
|
appendUserTurn,
|
|
4230
4275
|
buildModelRequest,
|
|
4231
4276
|
buildSystemPrompt,
|
|
@@ -4246,10 +4291,13 @@ export {
|
|
|
4246
4291
|
interpolateEnvVars,
|
|
4247
4292
|
latestUserInput,
|
|
4248
4293
|
loadConfigFile,
|
|
4294
|
+
loadPhase,
|
|
4295
|
+
loadPhases,
|
|
4249
4296
|
messageContentText,
|
|
4250
4297
|
parseModelRef,
|
|
4251
4298
|
registerBuiltInApiProviders,
|
|
4252
4299
|
registerConfigModels,
|
|
4300
|
+
reloadPhases,
|
|
4253
4301
|
resetGlobalHooks,
|
|
4254
4302
|
resolveDefaultModel,
|
|
4255
4303
|
resolveInWorkspace,
|