@rowan-agent/agent 0.4.7 → 0.4.9
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 +14 -7
- package/dist/{chunk-S7DI7HIF.js → chunk-2FIII4GP.js} +11 -14
- package/dist/{chunk-AFRSS3C5.js → chunk-FTIS43EE.js} +34 -24
- package/dist/index.cjs +94 -64
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +51 -32
- package/dist/{loader-UKBWDLDZ.js → loader-HCYCHPGT.js} +2 -2
- package/dist/{path-TJ2G5L4N.js → path-XORRK2EC.js} +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,6 +60,8 @@ type AgentOptions = {
|
|
|
60
60
|
context: AgentContext;
|
|
61
61
|
model: LlmModelRef;
|
|
62
62
|
stream: StreamFn;
|
|
63
|
+
cwd?: string;
|
|
64
|
+
rowanDir?: string; // project-local Rowan directory, default: ".rowan"
|
|
63
65
|
sessionId?: string;
|
|
64
66
|
phases?: PhaseRegistry;
|
|
65
67
|
extensions?: ExtensionRunnerRef;
|
|
@@ -212,7 +214,7 @@ agent.subscribe((event: AgentEvent) => {
|
|
|
212
214
|
|
|
213
215
|
### Parallel Phase Events
|
|
214
216
|
|
|
215
|
-
When multiple phases run concurrently (via multi-target `route`), each branch emits its own `turn_*`, `message_*`, and `tool_execution_*` events into the shared event stream — they are interleaved, not sequenced. Individual parallel phases do **not** emit `phase_start`/`phase_end`; those only fire for serial phases. After all branches complete,
|
|
217
|
+
When multiple phases run concurrently (via multi-target `route`), each branch emits its own `turn_*`, `message_*`, and `tool_execution_*` events into the shared event stream — they are interleaved, not sequenced. Individual parallel phases do **not** emit `phase_start`/`phase_end`; those only fire for serial phases. After all branches complete, their outputs are stashed and surfaced in the next iteration's phase entry message (under `<prev_phase_outputs>`); the `message_start`/`message_end` you observe for that entry message carry the merged results.
|
|
216
218
|
|
|
217
219
|
## Session
|
|
218
220
|
|
|
@@ -294,11 +296,11 @@ Per iteration:
|
|
|
294
296
|
┌──────────┐ ┌──────────┐
|
|
295
297
|
│ lint │ │typecheck │
|
|
296
298
|
└────┬─────┘ └────┬─────┘
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
└─────────┬─────────┘
|
|
300
|
+
▼
|
|
301
|
+
merged into <prev_phase_outputs>
|
|
302
|
+
│
|
|
303
|
+
route("stop")
|
|
302
304
|
│
|
|
303
305
|
▼
|
|
304
306
|
┌──────────┐
|
|
@@ -460,6 +462,8 @@ export default function myPlugin(rowan: ExtensionAPI) {
|
|
|
460
462
|
|
|
461
463
|
Multi-provider model configuration via `.rowan/config.yaml`. Supports multiple API providers, per-model settings, environment variable interpolation, and per-phase model overrides.
|
|
462
464
|
|
|
465
|
+
Config is loaded from the runtime Rowan directory, which defaults to `.rowan` and can be set when constructing `Agent` via `rowanDir`.
|
|
466
|
+
|
|
463
467
|
### Config File
|
|
464
468
|
|
|
465
469
|
Place `config.yaml` in your `.rowan/` directory (alongside `phases/`, `skills/`, etc.):
|
|
@@ -632,13 +636,16 @@ const request = buildModelRequest({ systemPrompt, messages, tools });
|
|
|
632
636
|
|
|
633
637
|
## Workspace
|
|
634
638
|
|
|
635
|
-
Workspace resolution
|
|
639
|
+
Workspace resolution uses the current project for both source and binary runs. The project Rowan directory defaults to `<cwd>/.rowan`; pass `rowanDir` to resolve another project-local directory.
|
|
636
640
|
|
|
637
641
|
```ts
|
|
638
642
|
import { resolveWorkspacePaths, resolveInWorkspace } from "@rowan-agent/agent";
|
|
639
643
|
|
|
640
644
|
const workspace = resolveWorkspacePaths();
|
|
641
645
|
// → { mode: "source" | "binary", cwd: string, rowanDir: string }
|
|
646
|
+
|
|
647
|
+
const custom = resolveWorkspacePaths({ rowanDir: ".rowan-project" });
|
|
648
|
+
// → custom.rowanDir is <cwd>/.rowan-project
|
|
642
649
|
```
|
|
643
650
|
|
|
644
651
|
## Loop Metrics
|
|
@@ -59,17 +59,10 @@ function detectRuntimeMode(input = {}) {
|
|
|
59
59
|
const executable = basename(input.execPath ?? process.execPath).toLowerCase().replace(/\.exe$/, "");
|
|
60
60
|
return executable === "bun" ? "source" : "binary";
|
|
61
61
|
}
|
|
62
|
-
function
|
|
62
|
+
function defaultWorkspaceStartDir(options) {
|
|
63
63
|
if (options.cwd) {
|
|
64
64
|
return options.cwd;
|
|
65
65
|
}
|
|
66
|
-
const entrypoint = options.entrypoint ?? process.argv[1];
|
|
67
|
-
if (entrypoint) {
|
|
68
|
-
const entrypointPath = resolve(process.cwd(), entrypoint);
|
|
69
|
-
if (existsSync(entrypointPath)) {
|
|
70
|
-
return dirname(entrypointPath);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
66
|
return process.cwd();
|
|
74
67
|
}
|
|
75
68
|
function resolveWorkspaceRoot(options = {}) {
|
|
@@ -79,11 +72,7 @@ function resolveWorkspaceRoot(options = {}) {
|
|
|
79
72
|
if (override) {
|
|
80
73
|
return resolveUserPath(override, homeDir);
|
|
81
74
|
}
|
|
82
|
-
|
|
83
|
-
if (mode === "binary") {
|
|
84
|
-
return homeDir;
|
|
85
|
-
}
|
|
86
|
-
return findSourceWorkspaceRoot(defaultSourceStartDir(options));
|
|
75
|
+
return findSourceWorkspaceRoot(defaultWorkspaceStartDir(options));
|
|
87
76
|
}
|
|
88
77
|
function resolveWorkspacePaths(options = {}) {
|
|
89
78
|
const mode = options.mode ?? detectRuntimeMode(options);
|
|
@@ -91,9 +80,16 @@ function resolveWorkspacePaths(options = {}) {
|
|
|
91
80
|
return {
|
|
92
81
|
mode,
|
|
93
82
|
cwd,
|
|
94
|
-
rowanDir:
|
|
83
|
+
rowanDir: resolveProjectRowanDir(cwd, options.rowanDir)
|
|
95
84
|
};
|
|
96
85
|
}
|
|
86
|
+
function resolveProjectRowanDir(cwd, rowanDir = BINARY_WORKSPACE_DIR) {
|
|
87
|
+
const inputPath = rowanDir.trim() || BINARY_WORKSPACE_DIR;
|
|
88
|
+
if (isAbsolute(inputPath)) {
|
|
89
|
+
throw new Error(`Project Rowan dir must be a relative path: ${rowanDir}`);
|
|
90
|
+
}
|
|
91
|
+
return resolveWorkspacePath({ root: cwd }, inputPath).absolutePath;
|
|
92
|
+
}
|
|
97
93
|
function resolveInWorkspace(path, rootOrPaths) {
|
|
98
94
|
if (path === "~" || path.startsWith("~/") || path.startsWith("~\\")) {
|
|
99
95
|
return resolveUserPath(path, homedir());
|
|
@@ -139,6 +135,7 @@ export {
|
|
|
139
135
|
detectRuntimeMode,
|
|
140
136
|
resolveWorkspaceRoot,
|
|
141
137
|
resolveWorkspacePaths,
|
|
138
|
+
resolveProjectRowanDir,
|
|
142
139
|
resolveInWorkspace,
|
|
143
140
|
normalizeRelativePath,
|
|
144
141
|
resolveWorkspacePath
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveInWorkspace,
|
|
3
3
|
resolveWorkspacePaths
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2FIII4GP.js";
|
|
5
5
|
|
|
6
6
|
// src/harness/phases/loader.ts
|
|
7
7
|
import { existsSync as existsSync3 } from "fs";
|
|
@@ -336,26 +336,25 @@ ${indent}</${tag}>`;
|
|
|
336
336
|
return `${indent}<${tag}>${escapeXml(String(val))}</${tag}>`;
|
|
337
337
|
}).join("\n");
|
|
338
338
|
}
|
|
339
|
-
function
|
|
339
|
+
function buildPhaseDirectiveMessage(phase, output, toolUseId) {
|
|
340
340
|
const parts = [];
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (p.content) {
|
|
348
|
-
parts.push(` <content>${p.content}</content>`);
|
|
341
|
+
parts.push(`<phase name="${escapeXml(phase.name)}">`);
|
|
342
|
+
parts.push(` <content>${phase.content}</content>`);
|
|
343
|
+
if (output.results && output.results.length > 0) {
|
|
344
|
+
parts.push(` <prev_phase_outputs>`);
|
|
345
|
+
if (output.instruction) {
|
|
346
|
+
parts.push(` <instruction>${escapeXml(output.instruction)}</instruction>`);
|
|
349
347
|
}
|
|
350
|
-
|
|
351
|
-
parts.push(` <
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
348
|
+
for (const r of output.results) {
|
|
349
|
+
parts.push(` <phase name="${escapeXml(r.name)}">`);
|
|
350
|
+
if (r.output !== void 0) {
|
|
351
|
+
parts.push(jsonToXml(r.output, 3));
|
|
352
|
+
}
|
|
353
|
+
parts.push(` </phase>`);
|
|
355
354
|
}
|
|
356
|
-
parts.push(` </
|
|
355
|
+
parts.push(` </prev_phase_outputs>`);
|
|
357
356
|
}
|
|
358
|
-
parts.push(`</
|
|
357
|
+
parts.push(`</phase>`);
|
|
359
358
|
return [{
|
|
360
359
|
type: "tool_result",
|
|
361
360
|
toolUseId,
|
|
@@ -370,11 +369,18 @@ var PHASE_DIR = "phases";
|
|
|
370
369
|
async function loadPhase(input, workspace) {
|
|
371
370
|
const resolved = resolveResourcePath(input, PHASE_DIR, PHASE_MARKER, workspace);
|
|
372
371
|
const { frontmatter, body } = await loadMarkdown(resolved);
|
|
372
|
+
const id = inferResourceName(resolved, PHASE_MARKER);
|
|
373
|
+
if (!frontmatter.name) {
|
|
374
|
+
throw new Error(`Phase "${id}" at "${resolved}" is missing required field "name" in PHASE.md frontmatter.`);
|
|
375
|
+
}
|
|
376
|
+
if (!frontmatter.description) {
|
|
377
|
+
throw new Error(`Phase "${id}" at "${resolved}" is missing required field "description" in PHASE.md frontmatter.`);
|
|
378
|
+
}
|
|
373
379
|
const baseDir = dirname2(resolved);
|
|
374
380
|
const phase = {
|
|
375
|
-
id
|
|
376
|
-
name: frontmatter.name
|
|
377
|
-
description: frontmatter.description
|
|
381
|
+
id,
|
|
382
|
+
name: frontmatter.name,
|
|
383
|
+
description: frontmatter.description,
|
|
378
384
|
tools: frontmatter.tools,
|
|
379
385
|
skills: frontmatter.skills,
|
|
380
386
|
target: frontmatter.target,
|
|
@@ -409,12 +415,16 @@ async function loadPhases(workspace, paths) {
|
|
|
409
415
|
const phases = /* @__PURE__ */ new Map();
|
|
410
416
|
if (paths && paths.length > 0) {
|
|
411
417
|
for (const path of paths) {
|
|
412
|
-
|
|
413
|
-
|
|
418
|
+
try {
|
|
419
|
+
const phase = await loadPhase(path, workspace);
|
|
420
|
+
phases.set(phase.id, phase);
|
|
421
|
+
} catch (error) {
|
|
422
|
+
console.warn(`Failed to load phase "${path}":`, error);
|
|
423
|
+
}
|
|
414
424
|
}
|
|
415
425
|
return { phases, entryPhaseId: null };
|
|
416
426
|
}
|
|
417
|
-
const ws = workspace ?? (await import("./path-
|
|
427
|
+
const ws = workspace ?? (await import("./path-XORRK2EC.js")).resolveWorkspacePaths();
|
|
418
428
|
const phasesDir = join3(ws.rowanDir, PHASE_DIR);
|
|
419
429
|
if (!existsSync3(phasesDir)) {
|
|
420
430
|
return { phases, entryPhaseId: null };
|
|
@@ -486,7 +496,7 @@ export {
|
|
|
486
496
|
buildSkillsDescription,
|
|
487
497
|
formatResourceOutput,
|
|
488
498
|
detectResourceType,
|
|
489
|
-
|
|
499
|
+
buildPhaseDirectiveMessage,
|
|
490
500
|
loadPhase,
|
|
491
501
|
readPhaseContent,
|
|
492
502
|
loadPhases,
|
package/dist/index.cjs
CHANGED
|
@@ -41,6 +41,7 @@ __export(path_exports, {
|
|
|
41
41
|
findSourceWorkspaceRoot: () => findSourceWorkspaceRoot,
|
|
42
42
|
normalizeRelativePath: () => normalizeRelativePath,
|
|
43
43
|
resolveInWorkspace: () => resolveInWorkspace,
|
|
44
|
+
resolveProjectRowanDir: () => resolveProjectRowanDir,
|
|
44
45
|
resolveWorkspacePath: () => resolveWorkspacePath,
|
|
45
46
|
resolveWorkspacePaths: () => resolveWorkspacePaths,
|
|
46
47
|
resolveWorkspaceRoot: () => resolveWorkspaceRoot
|
|
@@ -98,17 +99,10 @@ function detectRuntimeMode(input = {}) {
|
|
|
98
99
|
const executable = (0, import_node_path.basename)(input.execPath ?? process.execPath).toLowerCase().replace(/\.exe$/, "");
|
|
99
100
|
return executable === "bun" ? "source" : "binary";
|
|
100
101
|
}
|
|
101
|
-
function
|
|
102
|
+
function defaultWorkspaceStartDir(options) {
|
|
102
103
|
if (options.cwd) {
|
|
103
104
|
return options.cwd;
|
|
104
105
|
}
|
|
105
|
-
const entrypoint = options.entrypoint ?? process.argv[1];
|
|
106
|
-
if (entrypoint) {
|
|
107
|
-
const entrypointPath = (0, import_node_path.resolve)(process.cwd(), entrypoint);
|
|
108
|
-
if ((0, import_node_fs.existsSync)(entrypointPath)) {
|
|
109
|
-
return (0, import_node_path.dirname)(entrypointPath);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
106
|
return process.cwd();
|
|
113
107
|
}
|
|
114
108
|
function resolveWorkspaceRoot(options = {}) {
|
|
@@ -118,11 +112,7 @@ function resolveWorkspaceRoot(options = {}) {
|
|
|
118
112
|
if (override) {
|
|
119
113
|
return resolveUserPath(override, homeDir);
|
|
120
114
|
}
|
|
121
|
-
|
|
122
|
-
if (mode === "binary") {
|
|
123
|
-
return homeDir;
|
|
124
|
-
}
|
|
125
|
-
return findSourceWorkspaceRoot(defaultSourceStartDir(options));
|
|
115
|
+
return findSourceWorkspaceRoot(defaultWorkspaceStartDir(options));
|
|
126
116
|
}
|
|
127
117
|
function resolveWorkspacePaths(options = {}) {
|
|
128
118
|
const mode = options.mode ?? detectRuntimeMode(options);
|
|
@@ -130,9 +120,16 @@ function resolveWorkspacePaths(options = {}) {
|
|
|
130
120
|
return {
|
|
131
121
|
mode,
|
|
132
122
|
cwd,
|
|
133
|
-
rowanDir: (
|
|
123
|
+
rowanDir: resolveProjectRowanDir(cwd, options.rowanDir)
|
|
134
124
|
};
|
|
135
125
|
}
|
|
126
|
+
function resolveProjectRowanDir(cwd, rowanDir = BINARY_WORKSPACE_DIR) {
|
|
127
|
+
const inputPath = rowanDir.trim() || BINARY_WORKSPACE_DIR;
|
|
128
|
+
if ((0, import_node_path.isAbsolute)(inputPath)) {
|
|
129
|
+
throw new Error(`Project Rowan dir must be a relative path: ${rowanDir}`);
|
|
130
|
+
}
|
|
131
|
+
return resolveWorkspacePath({ root: cwd }, inputPath).absolutePath;
|
|
132
|
+
}
|
|
136
133
|
function resolveInWorkspace(path, rootOrPaths) {
|
|
137
134
|
if (path === "~" || path.startsWith("~/") || path.startsWith("~\\")) {
|
|
138
135
|
return resolveUserPath(path, (0, import_node_os.homedir)());
|
|
@@ -523,26 +520,25 @@ ${indent}</${tag}>`;
|
|
|
523
520
|
return `${indent}<${tag}>${escapeXml(String(val))}</${tag}>`;
|
|
524
521
|
}).join("\n");
|
|
525
522
|
}
|
|
526
|
-
function
|
|
523
|
+
function buildPhaseDirectiveMessage(phase, output, toolUseId) {
|
|
527
524
|
const parts = [];
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
parts.push(` <content>Phase "${p.name}" completed with no output.</content>`);
|
|
525
|
+
parts.push(`<phase name="${escapeXml(phase.name)}">`);
|
|
526
|
+
parts.push(` <content>${phase.content}</content>`);
|
|
527
|
+
if (output.results && output.results.length > 0) {
|
|
528
|
+
parts.push(` <prev_phase_outputs>`);
|
|
529
|
+
if (output.instruction) {
|
|
530
|
+
parts.push(` <instruction>${escapeXml(output.instruction)}</instruction>`);
|
|
531
|
+
}
|
|
532
|
+
for (const r of output.results) {
|
|
533
|
+
parts.push(` <phase name="${escapeXml(r.name)}">`);
|
|
534
|
+
if (r.output !== void 0) {
|
|
535
|
+
parts.push(jsonToXml(r.output, 3));
|
|
536
|
+
}
|
|
537
|
+
parts.push(` </phase>`);
|
|
542
538
|
}
|
|
543
|
-
parts.push(` </
|
|
539
|
+
parts.push(` </prev_phase_outputs>`);
|
|
544
540
|
}
|
|
545
|
-
parts.push(`</
|
|
541
|
+
parts.push(`</phase>`);
|
|
546
542
|
return [{
|
|
547
543
|
type: "tool_result",
|
|
548
544
|
toolUseId,
|
|
@@ -567,11 +563,18 @@ __export(loader_exports, {
|
|
|
567
563
|
async function loadPhase(input, workspace) {
|
|
568
564
|
const resolved = resolveResourcePath(input, PHASE_DIR, PHASE_MARKER, workspace);
|
|
569
565
|
const { frontmatter, body } = await loadMarkdown(resolved);
|
|
566
|
+
const id = inferResourceName(resolved, PHASE_MARKER);
|
|
567
|
+
if (!frontmatter.name) {
|
|
568
|
+
throw new Error(`Phase "${id}" at "${resolved}" is missing required field "name" in PHASE.md frontmatter.`);
|
|
569
|
+
}
|
|
570
|
+
if (!frontmatter.description) {
|
|
571
|
+
throw new Error(`Phase "${id}" at "${resolved}" is missing required field "description" in PHASE.md frontmatter.`);
|
|
572
|
+
}
|
|
570
573
|
const baseDir = (0, import_node_path4.dirname)(resolved);
|
|
571
574
|
const phase = {
|
|
572
|
-
id
|
|
573
|
-
name: frontmatter.name
|
|
574
|
-
description: frontmatter.description
|
|
575
|
+
id,
|
|
576
|
+
name: frontmatter.name,
|
|
577
|
+
description: frontmatter.description,
|
|
575
578
|
tools: frontmatter.tools,
|
|
576
579
|
skills: frontmatter.skills,
|
|
577
580
|
target: frontmatter.target,
|
|
@@ -606,8 +609,12 @@ async function loadPhases(workspace, paths) {
|
|
|
606
609
|
const phases = /* @__PURE__ */ new Map();
|
|
607
610
|
if (paths && paths.length > 0) {
|
|
608
611
|
for (const path of paths) {
|
|
609
|
-
|
|
610
|
-
|
|
612
|
+
try {
|
|
613
|
+
const phase = await loadPhase(path, workspace);
|
|
614
|
+
phases.set(phase.id, phase);
|
|
615
|
+
} catch (error) {
|
|
616
|
+
console.warn(`Failed to load phase "${path}":`, error);
|
|
617
|
+
}
|
|
611
618
|
}
|
|
612
619
|
return { phases, entryPhaseId: null };
|
|
613
620
|
}
|
|
@@ -715,6 +722,7 @@ __export(index_exports, {
|
|
|
715
722
|
loadConfigFile: () => loadConfigFile,
|
|
716
723
|
loadExtensionFromFactory: () => loadExtensionFromFactory,
|
|
717
724
|
loadExtensions: () => loadExtensions,
|
|
725
|
+
loadPhases: () => loadPhases,
|
|
718
726
|
loadSkill: () => loadSkill,
|
|
719
727
|
loadSkills: () => loadSkills,
|
|
720
728
|
messageContentText: () => messageContentText,
|
|
@@ -1847,10 +1855,14 @@ function applyFirstDecision(route, output) {
|
|
|
1847
1855
|
if (first.reason) output.routeReason = first.reason;
|
|
1848
1856
|
if (first.payload !== void 0) output.payload = normalizePayload(first.payload);
|
|
1849
1857
|
}
|
|
1850
|
-
function injectPhaseContent(phase,
|
|
1858
|
+
function injectPhaseContent(phase, output, messageManager) {
|
|
1851
1859
|
try {
|
|
1852
1860
|
const phaseContent = phase.filePath ? readPhaseContent(phase) : phase.content ?? phase.description ?? "";
|
|
1853
|
-
const content =
|
|
1861
|
+
const content = buildPhaseDirectiveMessage(
|
|
1862
|
+
{ name: phase.id, content: phaseContent },
|
|
1863
|
+
output,
|
|
1864
|
+
`phase_${phase.id}`
|
|
1865
|
+
);
|
|
1854
1866
|
const msgId = messageManager.start("tool", content, { phase: phase.id });
|
|
1855
1867
|
messageManager.end(msgId);
|
|
1856
1868
|
return msgId;
|
|
@@ -2024,6 +2036,8 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2024
2036
|
let isContinuing = false;
|
|
2025
2037
|
let previousPayload = void 0;
|
|
2026
2038
|
let previousPhaseMsgId = void 0;
|
|
2039
|
+
let previousResults = [];
|
|
2040
|
+
let pendingInstruction = void 0;
|
|
2027
2041
|
while (currentPhaseId) {
|
|
2028
2042
|
await reloadPhases(registry);
|
|
2029
2043
|
if (config.phases) {
|
|
@@ -2108,7 +2122,9 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2108
2122
|
removePhaseMessage(config.context.messages, previousPhaseMsgId);
|
|
2109
2123
|
previousPhaseMsgId = void 0;
|
|
2110
2124
|
if (enteringNewPhase) {
|
|
2111
|
-
previousPhaseMsgId = injectPhaseContent(phase,
|
|
2125
|
+
previousPhaseMsgId = injectPhaseContent(phase, { results: previousResults, instruction: pendingInstruction }, messageManager);
|
|
2126
|
+
previousResults = [];
|
|
2127
|
+
pendingInstruction = void 0;
|
|
2112
2128
|
}
|
|
2113
2129
|
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
|
|
2114
2130
|
let output = await executePhase(runtime);
|
|
@@ -2151,21 +2167,15 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2151
2167
|
if (!pt) continue;
|
|
2152
2168
|
const instanceId = instanceIds[i];
|
|
2153
2169
|
const context = pt.isolated ? [] : contextSnapshot;
|
|
2154
|
-
const payload = target.payload !== void 0 ? normalizePayload(target.payload) :
|
|
2155
|
-
const promise = executeParallelPhase(config, state, registry, pt, payload, context, availablePhases);
|
|
2170
|
+
const payload = target.payload !== void 0 ? normalizePayload(target.payload) : void 0;
|
|
2171
|
+
const promise = executeParallelPhase(config, state, registry, pt, payload, context, availablePhases, currentPhaseId);
|
|
2156
2172
|
parallelTasks.set(instanceId, { promise, phaseId: target.phase });
|
|
2157
2173
|
}
|
|
2158
2174
|
const successfulResults = await waitForBackgroundTasks(parallelTasks);
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
const content = buildPhaseResultMessage(phaseResults, `phase_results`, routeDecision.instruction);
|
|
2162
|
-
const msgId = messageManager.start("tool", content, { phase: "parallel_group" });
|
|
2163
|
-
await messageManager.end(msgId);
|
|
2164
|
-
previousPhaseMsgId = msgId;
|
|
2165
|
-
}
|
|
2175
|
+
previousResults = successfulResults.map((r) => ({ name: r.instanceId, output: r.payload }));
|
|
2176
|
+
pendingInstruction = routeDecision.instruction;
|
|
2166
2177
|
const entryPhaseId = phase.target ?? registry.entryPhaseId ?? "default";
|
|
2167
2178
|
if (entryPhaseId === "stop") {
|
|
2168
|
-
removePhaseMessage(config.context.messages, previousPhaseMsgId);
|
|
2169
2179
|
return completeRun(config, state, createOutcome.default(output, config.context.messages));
|
|
2170
2180
|
}
|
|
2171
2181
|
currentPhaseId = entryPhaseId;
|
|
@@ -2195,6 +2205,7 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2195
2205
|
ts: createTimestamp()
|
|
2196
2206
|
});
|
|
2197
2207
|
previousPayload = output.payload;
|
|
2208
|
+
previousResults = output.payload !== void 0 ? [{ name: phase.id, output: output.payload }] : [];
|
|
2198
2209
|
currentPhaseId = targetPhaseId;
|
|
2199
2210
|
}
|
|
2200
2211
|
throw new Error("Phase machine exited without a stop or abort transition.");
|
|
@@ -2402,7 +2413,7 @@ function createPhaseExecution(config, state, allTools, phase, messageManager, to
|
|
|
2402
2413
|
}
|
|
2403
2414
|
};
|
|
2404
2415
|
}
|
|
2405
|
-
async function executeParallelPhase(config, state, registry, phase,
|
|
2416
|
+
async function executeParallelPhase(config, state, registry, phase, payload, context, availablePhases, currentPhaseId) {
|
|
2406
2417
|
const messages = [...context];
|
|
2407
2418
|
const allTools = buildToolsWithRouting(config, availablePhases);
|
|
2408
2419
|
const phaseTools = phase.tools ? allTools.filter((t) => t.name === PhaseRouteTool || phase.tools.includes(t.name)) : allTools;
|
|
@@ -2417,19 +2428,23 @@ async function executeParallelPhase(config, state, registry, phase, parentPayloa
|
|
|
2417
2428
|
current: phase.id,
|
|
2418
2429
|
available: Array.from(registry.phases.keys()),
|
|
2419
2430
|
iterations: 0,
|
|
2420
|
-
payload
|
|
2431
|
+
payload
|
|
2421
2432
|
}
|
|
2422
2433
|
};
|
|
2423
2434
|
const messageManager = createMessageManager({ messages }, config.emit, config.onMessage);
|
|
2424
|
-
const phaseMsgId = phase.isolated ? void 0 : injectPhaseContent(
|
|
2435
|
+
const phaseMsgId = phase.isolated ? void 0 : injectPhaseContent(
|
|
2436
|
+
phase,
|
|
2437
|
+
{ results: payload !== void 0 ? [{ name: currentPhaseId, output: payload }] : [] },
|
|
2438
|
+
messageManager
|
|
2439
|
+
);
|
|
2425
2440
|
const toolExecutionManager = createToolExecutionManager(config.emit);
|
|
2426
2441
|
const execution = createPhaseExecution(config, state, phaseTools, phase, messageManager, toolExecutionManager, registry);
|
|
2427
2442
|
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
|
|
2428
2443
|
const output = await executePhase(runtime);
|
|
2429
2444
|
if (phaseMsgId) removePhaseMessage(messages, phaseMsgId);
|
|
2430
2445
|
const decision = output.toolCalls ? extractRouteCall(output.toolCalls) : void 0;
|
|
2431
|
-
const
|
|
2432
|
-
return { phaseId: phase.id, payload, content: output.message };
|
|
2446
|
+
const resultPayload = decision?.decision[0]?.payload !== void 0 ? normalizePayload(decision.decision[0].payload) : output.payload;
|
|
2447
|
+
return { instanceId: "", phaseId: phase.id, payload: resultPayload, content: output.message };
|
|
2433
2448
|
}
|
|
2434
2449
|
async function waitForBackgroundTasks(backgroundTasks) {
|
|
2435
2450
|
const entries = Array.from(backgroundTasks.entries());
|
|
@@ -2438,7 +2453,7 @@ async function waitForBackgroundTasks(backgroundTasks) {
|
|
|
2438
2453
|
for (let i = 0; i < results.length; i++) {
|
|
2439
2454
|
const r = results[i];
|
|
2440
2455
|
if (r.status === "fulfilled") {
|
|
2441
|
-
successful.push(r.value);
|
|
2456
|
+
successful.push({ ...r.value, instanceId: entries[i][0] });
|
|
2442
2457
|
}
|
|
2443
2458
|
}
|
|
2444
2459
|
backgroundTasks.clear();
|
|
@@ -2688,7 +2703,7 @@ var Agent = class {
|
|
|
2688
2703
|
* - Merges with CLI-provided phases and skills
|
|
2689
2704
|
*/
|
|
2690
2705
|
async discoverResources(context) {
|
|
2691
|
-
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd });
|
|
2706
|
+
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd, rowanDir: this.options.rowanDir });
|
|
2692
2707
|
const filePhases = await loadPhases(workspace);
|
|
2693
2708
|
let phases;
|
|
2694
2709
|
const providedPhases = this.options.phases;
|
|
@@ -2848,7 +2863,7 @@ ${additionalInstructions}` : content;
|
|
|
2848
2863
|
* @returns Formatted phase content string, or empty string if not found
|
|
2849
2864
|
*/
|
|
2850
2865
|
async phase(name) {
|
|
2851
|
-
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd });
|
|
2866
|
+
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd, rowanDir: this.options.rowanDir });
|
|
2852
2867
|
const { loadPhase: loadPhase2, readPhaseContent: readPhaseContent2 } = await Promise.resolve().then(() => (init_loader2(), loader_exports));
|
|
2853
2868
|
try {
|
|
2854
2869
|
const phase = await loadPhase2(name, workspace);
|
|
@@ -4198,13 +4213,19 @@ var ExtensionRunner = class {
|
|
|
4198
4213
|
if (!registration.id) {
|
|
4199
4214
|
throw new Error(`Phase registration requires an "id" field.`);
|
|
4200
4215
|
}
|
|
4216
|
+
if (!registration.name) {
|
|
4217
|
+
throw new Error(`Phase registration "${registration.id}" requires a "name" field.`);
|
|
4218
|
+
}
|
|
4219
|
+
if (!registration.description) {
|
|
4220
|
+
throw new Error(`Phase registration "${registration.id}" requires a "description" field.`);
|
|
4221
|
+
}
|
|
4201
4222
|
if (this.phases.has(registration.id)) {
|
|
4202
4223
|
throw new Error(`Duplicate phase id: ${registration.id}`);
|
|
4203
4224
|
}
|
|
4204
4225
|
const definition = {
|
|
4205
4226
|
id: registration.id,
|
|
4206
|
-
name: registration.name
|
|
4207
|
-
description: registration.description
|
|
4227
|
+
name: registration.name,
|
|
4228
|
+
description: registration.description,
|
|
4208
4229
|
run: registration.run,
|
|
4209
4230
|
...registration.model ? { model: registration.model } : {}
|
|
4210
4231
|
};
|
|
@@ -4288,14 +4309,19 @@ function readManifestSync(dir) {
|
|
|
4288
4309
|
}
|
|
4289
4310
|
}
|
|
4290
4311
|
function jitiAliases() {
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
}
|
|
4312
|
+
const moduleUrl = import_meta2.url;
|
|
4313
|
+
if (!moduleUrl) {
|
|
4314
|
+
return {};
|
|
4315
|
+
}
|
|
4316
|
+
const agentSourcePath = (0, import_node_url.fileURLToPath)(new URL("../index.ts", moduleUrl));
|
|
4317
|
+
if (!(0, import_node_fs6.existsSync)(agentSourcePath)) {
|
|
4318
|
+
return {};
|
|
4319
|
+
}
|
|
4320
|
+
return { "@rowan-agent/agent": agentSourcePath };
|
|
4295
4321
|
}
|
|
4296
4322
|
var sharedJiti;
|
|
4297
4323
|
function getJiti() {
|
|
4298
|
-
sharedJiti ??= (0, import_jiti.createJiti)(import_meta2.url, {
|
|
4324
|
+
sharedJiti ??= (0, import_jiti.createJiti)(import_meta2.url || process.cwd(), {
|
|
4299
4325
|
moduleCache: false,
|
|
4300
4326
|
alias: jitiAliases()
|
|
4301
4327
|
});
|
|
@@ -4398,6 +4424,9 @@ async function discoverAndLoadExtensions(cwd) {
|
|
|
4398
4424
|
return loadExtensions(paths, cwd);
|
|
4399
4425
|
}
|
|
4400
4426
|
|
|
4427
|
+
// src/index.ts
|
|
4428
|
+
init_loader2();
|
|
4429
|
+
|
|
4401
4430
|
// src/harness/context/index.ts
|
|
4402
4431
|
init_resource_formatter();
|
|
4403
4432
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -4430,6 +4459,7 @@ init_resource_formatter();
|
|
|
4430
4459
|
loadConfigFile,
|
|
4431
4460
|
loadExtensionFromFactory,
|
|
4432
4461
|
loadExtensions,
|
|
4462
|
+
loadPhases,
|
|
4433
4463
|
loadSkill,
|
|
4434
4464
|
loadSkills,
|
|
4435
4465
|
messageContentText,
|
package/dist/index.d.cts
CHANGED
|
@@ -1381,6 +1381,7 @@ type AgentOptions = {
|
|
|
1381
1381
|
model: LlmModelRef;
|
|
1382
1382
|
stream: StreamFn;
|
|
1383
1383
|
cwd?: string;
|
|
1384
|
+
rowanDir?: string;
|
|
1384
1385
|
phases?: PhaseRegistry;
|
|
1385
1386
|
extensionRunnerRef?: ExtensionRunnerRef;
|
|
1386
1387
|
sessionId?: string;
|
|
@@ -1700,6 +1701,7 @@ type ResolveWorkspaceOptions = {
|
|
|
1700
1701
|
entrypoint?: string;
|
|
1701
1702
|
homeDir?: string;
|
|
1702
1703
|
mode?: RuntimeMode;
|
|
1704
|
+
rowanDir?: string;
|
|
1703
1705
|
};
|
|
1704
1706
|
declare function resolveWorkspacePaths(options?: ResolveWorkspaceOptions): WorkspacePaths;
|
|
1705
1707
|
declare function resolveInWorkspace(path: string, rootOrPaths: string | Pick<WorkspacePaths, "cwd">): string;
|
|
@@ -1774,6 +1776,18 @@ declare class AgentEventStream extends EventStream<AgentEvent, AgentMessage[]> {
|
|
|
1774
1776
|
constructor();
|
|
1775
1777
|
}
|
|
1776
1778
|
|
|
1779
|
+
/**
|
|
1780
|
+
* Load all phases from .rowan/phases directory.
|
|
1781
|
+
*
|
|
1782
|
+
* Scans for subdirectories containing PHASE.md files.
|
|
1783
|
+
* Returns PhaseRegistry with entryPhaseId:
|
|
1784
|
+
* - null by default (caller must explicitly set to start from a specific phase)
|
|
1785
|
+
* - Set to a specific phase id to start from that phase
|
|
1786
|
+
*
|
|
1787
|
+
* When entryPhaseId is null, AgentLoop starts from "none" phase.
|
|
1788
|
+
*/
|
|
1789
|
+
declare function loadPhases(workspace?: WorkspacePaths, paths?: string[]): Promise<PhaseRegistry>;
|
|
1790
|
+
|
|
1777
1791
|
interface SystemPromptOptions {
|
|
1778
1792
|
/** Base system prompt. */
|
|
1779
1793
|
systemPrompt: string;
|
|
@@ -1827,4 +1841,4 @@ declare function buildModelRequest(input: ModelRequestInput, options?: {
|
|
|
1827
1841
|
model?: LlmModelRef;
|
|
1828
1842
|
}): LlmRequest;
|
|
1829
1843
|
|
|
1830
|
-
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 ExtensionRunnerRef, 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, discoverAndLoadExtensions, getGlobalHooks, interpolateEnvVars, latestUserInput, loadConfigFile, loadExtensionFromFactory, loadExtensions, loadSkill, loadSkills, messageContentText, parseModelRef, registerConfigModels, resetGlobalHooks, resolveDefaultModel, resolveInWorkspace, resolveSkillPath, resolveWorkspacePaths, serializeSkills };
|
|
1844
|
+
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 ExtensionRunnerRef, 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, discoverAndLoadExtensions, getGlobalHooks, interpolateEnvVars, latestUserInput, loadConfigFile, loadExtensionFromFactory, loadExtensions, loadPhases, loadSkill, loadSkills, messageContentText, parseModelRef, registerConfigModels, resetGlobalHooks, resolveDefaultModel, resolveInWorkspace, resolveSkillPath, resolveWorkspacePaths, serializeSkills };
|
package/dist/index.d.ts
CHANGED
|
@@ -1381,6 +1381,7 @@ type AgentOptions = {
|
|
|
1381
1381
|
model: LlmModelRef;
|
|
1382
1382
|
stream: StreamFn;
|
|
1383
1383
|
cwd?: string;
|
|
1384
|
+
rowanDir?: string;
|
|
1384
1385
|
phases?: PhaseRegistry;
|
|
1385
1386
|
extensionRunnerRef?: ExtensionRunnerRef;
|
|
1386
1387
|
sessionId?: string;
|
|
@@ -1700,6 +1701,7 @@ type ResolveWorkspaceOptions = {
|
|
|
1700
1701
|
entrypoint?: string;
|
|
1701
1702
|
homeDir?: string;
|
|
1702
1703
|
mode?: RuntimeMode;
|
|
1704
|
+
rowanDir?: string;
|
|
1703
1705
|
};
|
|
1704
1706
|
declare function resolveWorkspacePaths(options?: ResolveWorkspaceOptions): WorkspacePaths;
|
|
1705
1707
|
declare function resolveInWorkspace(path: string, rootOrPaths: string | Pick<WorkspacePaths, "cwd">): string;
|
|
@@ -1774,6 +1776,18 @@ declare class AgentEventStream extends EventStream<AgentEvent, AgentMessage[]> {
|
|
|
1774
1776
|
constructor();
|
|
1775
1777
|
}
|
|
1776
1778
|
|
|
1779
|
+
/**
|
|
1780
|
+
* Load all phases from .rowan/phases directory.
|
|
1781
|
+
*
|
|
1782
|
+
* Scans for subdirectories containing PHASE.md files.
|
|
1783
|
+
* Returns PhaseRegistry with entryPhaseId:
|
|
1784
|
+
* - null by default (caller must explicitly set to start from a specific phase)
|
|
1785
|
+
* - Set to a specific phase id to start from that phase
|
|
1786
|
+
*
|
|
1787
|
+
* When entryPhaseId is null, AgentLoop starts from "none" phase.
|
|
1788
|
+
*/
|
|
1789
|
+
declare function loadPhases(workspace?: WorkspacePaths, paths?: string[]): Promise<PhaseRegistry>;
|
|
1790
|
+
|
|
1777
1791
|
interface SystemPromptOptions {
|
|
1778
1792
|
/** Base system prompt. */
|
|
1779
1793
|
systemPrompt: string;
|
|
@@ -1827,4 +1841,4 @@ declare function buildModelRequest(input: ModelRequestInput, options?: {
|
|
|
1827
1841
|
model?: LlmModelRef;
|
|
1828
1842
|
}): LlmRequest;
|
|
1829
1843
|
|
|
1830
|
-
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 ExtensionRunnerRef, 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, discoverAndLoadExtensions, getGlobalHooks, interpolateEnvVars, latestUserInput, loadConfigFile, loadExtensionFromFactory, loadExtensions, loadSkill, loadSkills, messageContentText, parseModelRef, registerConfigModels, resetGlobalHooks, resolveDefaultModel, resolveInWorkspace, resolveSkillPath, resolveWorkspacePaths, serializeSkills };
|
|
1844
|
+
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 ExtensionRunnerRef, 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, discoverAndLoadExtensions, getGlobalHooks, interpolateEnvVars, latestUserInput, loadConfigFile, loadExtensionFromFactory, loadExtensions, loadPhases, loadSkill, loadSkills, messageContentText, parseModelRef, registerConfigModels, resetGlobalHooks, resolveDefaultModel, resolveInWorkspace, resolveSkillPath, resolveWorkspacePaths, serializeSkills };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
buildPhaseDirectiveMessage,
|
|
3
3
|
buildSkillsDescription,
|
|
4
4
|
buildStructuredSection,
|
|
5
5
|
detectResourceType,
|
|
@@ -16,12 +16,12 @@ import {
|
|
|
16
16
|
reloadPhases,
|
|
17
17
|
resolveDefaultModel,
|
|
18
18
|
resolveResourcePath
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-FTIS43EE.js";
|
|
20
20
|
import {
|
|
21
21
|
normalizeRelativePath,
|
|
22
22
|
resolveInWorkspace,
|
|
23
23
|
resolveWorkspacePaths
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-2FIII4GP.js";
|
|
25
25
|
|
|
26
26
|
// src/utils.ts
|
|
27
27
|
function createId(prefix) {
|
|
@@ -1132,10 +1132,14 @@ function applyFirstDecision(route, output) {
|
|
|
1132
1132
|
if (first.reason) output.routeReason = first.reason;
|
|
1133
1133
|
if (first.payload !== void 0) output.payload = normalizePayload(first.payload);
|
|
1134
1134
|
}
|
|
1135
|
-
function injectPhaseContent(phase,
|
|
1135
|
+
function injectPhaseContent(phase, output, messageManager) {
|
|
1136
1136
|
try {
|
|
1137
1137
|
const phaseContent = phase.filePath ? readPhaseContent(phase) : phase.content ?? phase.description ?? "";
|
|
1138
|
-
const content =
|
|
1138
|
+
const content = buildPhaseDirectiveMessage(
|
|
1139
|
+
{ name: phase.id, content: phaseContent },
|
|
1140
|
+
output,
|
|
1141
|
+
`phase_${phase.id}`
|
|
1142
|
+
);
|
|
1139
1143
|
const msgId = messageManager.start("tool", content, { phase: phase.id });
|
|
1140
1144
|
messageManager.end(msgId);
|
|
1141
1145
|
return msgId;
|
|
@@ -1309,6 +1313,8 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
1309
1313
|
let isContinuing = false;
|
|
1310
1314
|
let previousPayload = void 0;
|
|
1311
1315
|
let previousPhaseMsgId = void 0;
|
|
1316
|
+
let previousResults = [];
|
|
1317
|
+
let pendingInstruction = void 0;
|
|
1312
1318
|
while (currentPhaseId) {
|
|
1313
1319
|
await reloadPhases(registry);
|
|
1314
1320
|
if (config.phases) {
|
|
@@ -1393,7 +1399,9 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
1393
1399
|
removePhaseMessage(config.context.messages, previousPhaseMsgId);
|
|
1394
1400
|
previousPhaseMsgId = void 0;
|
|
1395
1401
|
if (enteringNewPhase) {
|
|
1396
|
-
previousPhaseMsgId = injectPhaseContent(phase,
|
|
1402
|
+
previousPhaseMsgId = injectPhaseContent(phase, { results: previousResults, instruction: pendingInstruction }, messageManager);
|
|
1403
|
+
previousResults = [];
|
|
1404
|
+
pendingInstruction = void 0;
|
|
1397
1405
|
}
|
|
1398
1406
|
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
|
|
1399
1407
|
let output = await executePhase(runtime);
|
|
@@ -1436,21 +1444,15 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
1436
1444
|
if (!pt) continue;
|
|
1437
1445
|
const instanceId = instanceIds[i];
|
|
1438
1446
|
const context = pt.isolated ? [] : contextSnapshot;
|
|
1439
|
-
const payload = target.payload !== void 0 ? normalizePayload(target.payload) :
|
|
1440
|
-
const promise = executeParallelPhase(config, state, registry, pt, payload, context, availablePhases);
|
|
1447
|
+
const payload = target.payload !== void 0 ? normalizePayload(target.payload) : void 0;
|
|
1448
|
+
const promise = executeParallelPhase(config, state, registry, pt, payload, context, availablePhases, currentPhaseId);
|
|
1441
1449
|
parallelTasks.set(instanceId, { promise, phaseId: target.phase });
|
|
1442
1450
|
}
|
|
1443
1451
|
const successfulResults = await waitForBackgroundTasks(parallelTasks);
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
const content = buildPhaseResultMessage(phaseResults, `phase_results`, routeDecision.instruction);
|
|
1447
|
-
const msgId = messageManager.start("tool", content, { phase: "parallel_group" });
|
|
1448
|
-
await messageManager.end(msgId);
|
|
1449
|
-
previousPhaseMsgId = msgId;
|
|
1450
|
-
}
|
|
1452
|
+
previousResults = successfulResults.map((r) => ({ name: r.instanceId, output: r.payload }));
|
|
1453
|
+
pendingInstruction = routeDecision.instruction;
|
|
1451
1454
|
const entryPhaseId = phase.target ?? registry.entryPhaseId ?? "default";
|
|
1452
1455
|
if (entryPhaseId === "stop") {
|
|
1453
|
-
removePhaseMessage(config.context.messages, previousPhaseMsgId);
|
|
1454
1456
|
return completeRun(config, state, createOutcome.default(output, config.context.messages));
|
|
1455
1457
|
}
|
|
1456
1458
|
currentPhaseId = entryPhaseId;
|
|
@@ -1480,6 +1482,7 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
1480
1482
|
ts: createTimestamp()
|
|
1481
1483
|
});
|
|
1482
1484
|
previousPayload = output.payload;
|
|
1485
|
+
previousResults = output.payload !== void 0 ? [{ name: phase.id, output: output.payload }] : [];
|
|
1483
1486
|
currentPhaseId = targetPhaseId;
|
|
1484
1487
|
}
|
|
1485
1488
|
throw new Error("Phase machine exited without a stop or abort transition.");
|
|
@@ -1687,7 +1690,7 @@ function createPhaseExecution(config, state, allTools, phase, messageManager, to
|
|
|
1687
1690
|
}
|
|
1688
1691
|
};
|
|
1689
1692
|
}
|
|
1690
|
-
async function executeParallelPhase(config, state, registry, phase,
|
|
1693
|
+
async function executeParallelPhase(config, state, registry, phase, payload, context, availablePhases, currentPhaseId) {
|
|
1691
1694
|
const messages = [...context];
|
|
1692
1695
|
const allTools = buildToolsWithRouting(config, availablePhases);
|
|
1693
1696
|
const phaseTools = phase.tools ? allTools.filter((t) => t.name === PhaseRouteTool || phase.tools.includes(t.name)) : allTools;
|
|
@@ -1702,19 +1705,23 @@ async function executeParallelPhase(config, state, registry, phase, parentPayloa
|
|
|
1702
1705
|
current: phase.id,
|
|
1703
1706
|
available: Array.from(registry.phases.keys()),
|
|
1704
1707
|
iterations: 0,
|
|
1705
|
-
payload
|
|
1708
|
+
payload
|
|
1706
1709
|
}
|
|
1707
1710
|
};
|
|
1708
1711
|
const messageManager = createMessageManager({ messages }, config.emit, config.onMessage);
|
|
1709
|
-
const phaseMsgId = phase.isolated ? void 0 : injectPhaseContent(
|
|
1712
|
+
const phaseMsgId = phase.isolated ? void 0 : injectPhaseContent(
|
|
1713
|
+
phase,
|
|
1714
|
+
{ results: payload !== void 0 ? [{ name: currentPhaseId, output: payload }] : [] },
|
|
1715
|
+
messageManager
|
|
1716
|
+
);
|
|
1710
1717
|
const toolExecutionManager = createToolExecutionManager(config.emit);
|
|
1711
1718
|
const execution = createPhaseExecution(config, state, phaseTools, phase, messageManager, toolExecutionManager, registry);
|
|
1712
1719
|
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
|
|
1713
1720
|
const output = await executePhase(runtime);
|
|
1714
1721
|
if (phaseMsgId) removePhaseMessage(messages, phaseMsgId);
|
|
1715
1722
|
const decision = output.toolCalls ? extractRouteCall(output.toolCalls) : void 0;
|
|
1716
|
-
const
|
|
1717
|
-
return { phaseId: phase.id, payload, content: output.message };
|
|
1723
|
+
const resultPayload = decision?.decision[0]?.payload !== void 0 ? normalizePayload(decision.decision[0].payload) : output.payload;
|
|
1724
|
+
return { instanceId: "", phaseId: phase.id, payload: resultPayload, content: output.message };
|
|
1718
1725
|
}
|
|
1719
1726
|
async function waitForBackgroundTasks(backgroundTasks) {
|
|
1720
1727
|
const entries = Array.from(backgroundTasks.entries());
|
|
@@ -1723,7 +1730,7 @@ async function waitForBackgroundTasks(backgroundTasks) {
|
|
|
1723
1730
|
for (let i = 0; i < results.length; i++) {
|
|
1724
1731
|
const r = results[i];
|
|
1725
1732
|
if (r.status === "fulfilled") {
|
|
1726
|
-
successful.push(r.value);
|
|
1733
|
+
successful.push({ ...r.value, instanceId: entries[i][0] });
|
|
1727
1734
|
}
|
|
1728
1735
|
}
|
|
1729
1736
|
backgroundTasks.clear();
|
|
@@ -1966,7 +1973,7 @@ var Agent = class {
|
|
|
1966
1973
|
* - Merges with CLI-provided phases and skills
|
|
1967
1974
|
*/
|
|
1968
1975
|
async discoverResources(context) {
|
|
1969
|
-
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd });
|
|
1976
|
+
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd, rowanDir: this.options.rowanDir });
|
|
1970
1977
|
const filePhases = await loadPhases(workspace);
|
|
1971
1978
|
let phases;
|
|
1972
1979
|
const providedPhases = this.options.phases;
|
|
@@ -2126,8 +2133,8 @@ ${additionalInstructions}` : content;
|
|
|
2126
2133
|
* @returns Formatted phase content string, or empty string if not found
|
|
2127
2134
|
*/
|
|
2128
2135
|
async phase(name) {
|
|
2129
|
-
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd });
|
|
2130
|
-
const { loadPhase: loadPhase2, readPhaseContent: readPhaseContent2 } = await import("./loader-
|
|
2136
|
+
const workspace = resolveWorkspacePaths({ cwd: this.options.cwd, rowanDir: this.options.rowanDir });
|
|
2137
|
+
const { loadPhase: loadPhase2, readPhaseContent: readPhaseContent2 } = await import("./loader-HCYCHPGT.js");
|
|
2131
2138
|
try {
|
|
2132
2139
|
const phase = await loadPhase2(name, workspace);
|
|
2133
2140
|
return readPhaseContent2(phase);
|
|
@@ -3471,13 +3478,19 @@ var ExtensionRunner = class {
|
|
|
3471
3478
|
if (!registration.id) {
|
|
3472
3479
|
throw new Error(`Phase registration requires an "id" field.`);
|
|
3473
3480
|
}
|
|
3481
|
+
if (!registration.name) {
|
|
3482
|
+
throw new Error(`Phase registration "${registration.id}" requires a "name" field.`);
|
|
3483
|
+
}
|
|
3484
|
+
if (!registration.description) {
|
|
3485
|
+
throw new Error(`Phase registration "${registration.id}" requires a "description" field.`);
|
|
3486
|
+
}
|
|
3474
3487
|
if (this.phases.has(registration.id)) {
|
|
3475
3488
|
throw new Error(`Duplicate phase id: ${registration.id}`);
|
|
3476
3489
|
}
|
|
3477
3490
|
const definition = {
|
|
3478
3491
|
id: registration.id,
|
|
3479
|
-
name: registration.name
|
|
3480
|
-
description: registration.description
|
|
3492
|
+
name: registration.name,
|
|
3493
|
+
description: registration.description,
|
|
3481
3494
|
run: registration.run,
|
|
3482
3495
|
...registration.model ? { model: registration.model } : {}
|
|
3483
3496
|
};
|
|
@@ -3560,14 +3573,19 @@ function readManifestSync(dir) {
|
|
|
3560
3573
|
}
|
|
3561
3574
|
}
|
|
3562
3575
|
function jitiAliases() {
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
}
|
|
3576
|
+
const moduleUrl = import.meta.url;
|
|
3577
|
+
if (!moduleUrl) {
|
|
3578
|
+
return {};
|
|
3579
|
+
}
|
|
3580
|
+
const agentSourcePath = fileURLToPath(new URL("../index.ts", moduleUrl));
|
|
3581
|
+
if (!existsSync2(agentSourcePath)) {
|
|
3582
|
+
return {};
|
|
3583
|
+
}
|
|
3584
|
+
return { "@rowan-agent/agent": agentSourcePath };
|
|
3567
3585
|
}
|
|
3568
3586
|
var sharedJiti;
|
|
3569
3587
|
function getJiti() {
|
|
3570
|
-
sharedJiti ??= createJiti(import.meta.url, {
|
|
3588
|
+
sharedJiti ??= createJiti(import.meta.url || process.cwd(), {
|
|
3571
3589
|
moduleCache: false,
|
|
3572
3590
|
alias: jitiAliases()
|
|
3573
3591
|
});
|
|
@@ -3698,6 +3716,7 @@ export {
|
|
|
3698
3716
|
loadConfigFile,
|
|
3699
3717
|
loadExtensionFromFactory,
|
|
3700
3718
|
loadExtensions,
|
|
3719
|
+
loadPhases,
|
|
3701
3720
|
loadSkill,
|
|
3702
3721
|
loadSkills,
|
|
3703
3722
|
messageContentText,
|
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
findSourceWorkspaceRoot,
|
|
8
8
|
normalizeRelativePath,
|
|
9
9
|
resolveInWorkspace,
|
|
10
|
+
resolveProjectRowanDir,
|
|
10
11
|
resolveWorkspacePath,
|
|
11
12
|
resolveWorkspacePaths,
|
|
12
13
|
resolveWorkspaceRoot
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2FIII4GP.js";
|
|
14
15
|
export {
|
|
15
16
|
BINARY_WORKSPACE_DIR,
|
|
16
17
|
PACKAGED_ENV,
|
|
@@ -20,6 +21,7 @@ export {
|
|
|
20
21
|
findSourceWorkspaceRoot,
|
|
21
22
|
normalizeRelativePath,
|
|
22
23
|
resolveInWorkspace,
|
|
24
|
+
resolveProjectRowanDir,
|
|
23
25
|
resolveWorkspacePath,
|
|
24
26
|
resolveWorkspacePaths,
|
|
25
27
|
resolveWorkspaceRoot
|