@rowan-agent/agent 0.5.1 → 0.5.3
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 +86 -9
- package/dist/index.d.ts +31 -0
- package/dist/index.js +161 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,14 +42,51 @@ The `Agent` class is the public facade. It drives the entire execution loop —
|
|
|
42
42
|
```ts
|
|
43
43
|
class Agent {
|
|
44
44
|
constructor(options: AgentOptions);
|
|
45
|
-
run(options?: RunOptions): Promise<
|
|
45
|
+
run(options?: RunOptions): Promise<RunResult>;
|
|
46
|
+
|
|
47
|
+
// User input / conversation continuation
|
|
48
|
+
appendUserMessage(input: string): void;
|
|
49
|
+
appendMessage(message: AgentMessage): void;
|
|
50
|
+
appendMessages(messages: AgentMessage[]): void;
|
|
51
|
+
runWithUserInput(input: string, options?: RunOptions): Promise<RunResult>;
|
|
52
|
+
runWithMessage(message: AgentMessage, options?: RunOptions): Promise<RunResult>;
|
|
53
|
+
|
|
54
|
+
// Context and transcript
|
|
55
|
+
getContext(): AgentContext;
|
|
56
|
+
setContext(context: AgentContext): void;
|
|
57
|
+
updateContext(updater: (context: AgentContext) => AgentContext): void;
|
|
58
|
+
forkContext(overrides?: Partial<AgentContext>): AgentContext;
|
|
59
|
+
getMessages(): AgentMessage[];
|
|
60
|
+
setMessages(messages: AgentMessage[]): void;
|
|
61
|
+
clearMessages(): void;
|
|
62
|
+
getTranscript(): AgentMessage[];
|
|
63
|
+
replaceTranscript(messages: AgentMessage[]): void;
|
|
64
|
+
|
|
65
|
+
// Config access and shortcuts
|
|
66
|
+
getConfig(): AgentOptions;
|
|
67
|
+
setConfig(config: AgentOptions): void;
|
|
68
|
+
updateConfig(updater: (config: AgentOptions) => AgentOptions): void;
|
|
69
|
+
setSessionId(sessionId: string): void;
|
|
70
|
+
getSessionId(): string | undefined;
|
|
71
|
+
setModel(model: LlmModelRef): void;
|
|
72
|
+
setTools(tools: Tool[]): void;
|
|
73
|
+
setSkills(skills: Skill[]): void;
|
|
74
|
+
setPhases(phases: PhaseRegistry): void;
|
|
75
|
+
setCwd(cwd: string): void;
|
|
76
|
+
setStream(stream: StreamFn): void;
|
|
77
|
+
getModel(): LlmModelRef;
|
|
78
|
+
getTools(): Tool[];
|
|
79
|
+
getSkills(): Skill[];
|
|
80
|
+
getPhases(): PhaseRegistry | undefined;
|
|
81
|
+
getCwd(): string | undefined;
|
|
82
|
+
|
|
46
83
|
abort(): void;
|
|
47
84
|
subscribe(listener: AgentEventListener): () => void;
|
|
48
|
-
skill(name: string):
|
|
85
|
+
skill(name: string, additionalInstructions?: string): string;
|
|
49
86
|
phase(name: string): Promise<string>;
|
|
50
87
|
waitForIdle(): Promise<void>;
|
|
51
88
|
flushEvents(): Promise<void>;
|
|
52
|
-
readonly
|
|
89
|
+
readonly state: AgentStatus;
|
|
53
90
|
|
|
54
91
|
// Resource loading — replaces standalone loadSkills/loadPhases/loadExtensions
|
|
55
92
|
static loadSkills(targetPath: string): Promise<Skill[]>;
|
|
@@ -65,6 +102,7 @@ type AgentOptions = {
|
|
|
65
102
|
context: AgentContext;
|
|
66
103
|
model: LlmModelRef;
|
|
67
104
|
stream: StreamFn;
|
|
105
|
+
cwd?: string;
|
|
68
106
|
extensions?: LoadedExtension[];
|
|
69
107
|
sessionId?: string;
|
|
70
108
|
maxAttempts?: number;
|
|
@@ -78,18 +116,57 @@ type AgentOptions = {
|
|
|
78
116
|
};
|
|
79
117
|
```
|
|
80
118
|
|
|
81
|
-
###
|
|
119
|
+
### RunResult
|
|
82
120
|
|
|
83
121
|
```ts
|
|
84
|
-
type
|
|
85
|
-
status: AgentStatus;
|
|
86
|
-
outcome?: Outcome;
|
|
87
|
-
metrics?: LoopMetrics;
|
|
88
|
-
messages: AgentMessage[];
|
|
122
|
+
type RunResult = {
|
|
89
123
|
sessionId: string;
|
|
124
|
+
messages: AgentMessage[];
|
|
125
|
+
outcome: Outcome;
|
|
126
|
+
metrics: LoopMetrics;
|
|
90
127
|
};
|
|
91
128
|
```
|
|
92
129
|
|
|
130
|
+
### Conversation Continuation
|
|
131
|
+
|
|
132
|
+
For multi-turn use, append input to the agent's current transcript and run with the updated context. `runWithUserInput()` is the main convenience API; the lower-level append methods are useful when a UI or session layer controls message creation.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const first = await agent.runWithUserInput("summarize this repository");
|
|
136
|
+
|
|
137
|
+
agent.appendUserMessage("now focus on the CLI package");
|
|
138
|
+
const second = await agent.run();
|
|
139
|
+
|
|
140
|
+
await agent.runWithMessage(createMessage("user", "what changed since last turn?"));
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Transcript helpers return snapshots, so callers can inspect or edit history without accidentally mutating the agent until they call a setter.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
const messages = agent.getMessages();
|
|
147
|
+
agent.replaceTranscript(messages.slice(-6));
|
|
148
|
+
agent.clearMessages();
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Updating Config
|
|
152
|
+
|
|
153
|
+
`AgentOptions` can be replaced wholesale with `setConfig()`, or updated through focused shortcuts for common orchestration flows.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
agent.setSessionId("ses_known");
|
|
157
|
+
agent.setModel({ provider: "openai", id: "gpt-4.1" });
|
|
158
|
+
agent.setTools(createCoreTools({ root: process.cwd() }));
|
|
159
|
+
agent.setSkills(await Agent.loadSkills("./.rowan/skills"));
|
|
160
|
+
agent.setPhases(await Agent.loadPhases("./.rowan/phases"));
|
|
161
|
+
agent.setCwd(process.cwd());
|
|
162
|
+
agent.setStream(createDispatchStream());
|
|
163
|
+
|
|
164
|
+
agent.updateContext((context) => ({
|
|
165
|
+
...context,
|
|
166
|
+
systemPrompt: `${context.systemPrompt}\n\nPrefer concise answers.`,
|
|
167
|
+
}));
|
|
168
|
+
```
|
|
169
|
+
|
|
93
170
|
## AgentContext
|
|
94
171
|
|
|
95
172
|
The context snapshot that defines what the agent can see and do — the system prompt sets the role, messages form the conversation history, and tools/skills define the capability boundary.
|
package/dist/index.d.ts
CHANGED
|
@@ -1376,6 +1376,36 @@ declare class Agent {
|
|
|
1376
1376
|
static loadExtensions(targetPath: string): Promise<LoadExtensionsResult>;
|
|
1377
1377
|
constructor(options: AgentOptions);
|
|
1378
1378
|
subscribe(listener: AgentEventListener): Unsubscribe;
|
|
1379
|
+
appendUserMessage(input: string): void;
|
|
1380
|
+
appendMessage(message: AgentMessage): void;
|
|
1381
|
+
appendMessages(messages: AgentMessage[]): void;
|
|
1382
|
+
runWithUserInput(input: string, options?: RunOptions): Promise<RunResult>;
|
|
1383
|
+
runWithMessage(message: AgentMessage, options?: RunOptions): Promise<RunResult>;
|
|
1384
|
+
getContext(): AgentContext;
|
|
1385
|
+
setContext(context: AgentContext): void;
|
|
1386
|
+
updateContext(updater: (context: AgentContext) => AgentContext): void;
|
|
1387
|
+
forkContext(overrides?: Partial<AgentContext>): AgentContext;
|
|
1388
|
+
getMessages(): AgentMessage[];
|
|
1389
|
+
setMessages(messages: AgentMessage[]): void;
|
|
1390
|
+
clearMessages(): void;
|
|
1391
|
+
getTranscript(): AgentMessage[];
|
|
1392
|
+
replaceTranscript(messages: AgentMessage[]): void;
|
|
1393
|
+
getConfig(): AgentOptions;
|
|
1394
|
+
setConfig(config: AgentOptions): void;
|
|
1395
|
+
updateConfig(updater: (config: AgentOptions) => AgentOptions): void;
|
|
1396
|
+
setSessionId(sessionId: string): void;
|
|
1397
|
+
getSessionId(): string | undefined;
|
|
1398
|
+
setModel(model: LlmModelRef): void;
|
|
1399
|
+
setTools(tools: Tool[]): void;
|
|
1400
|
+
setSkills(skills: Skill$1[]): void;
|
|
1401
|
+
setPhases(phases: PhaseRegistry): void;
|
|
1402
|
+
setCwd(cwd: string): void;
|
|
1403
|
+
setStream(stream: StreamFn): void;
|
|
1404
|
+
getModel(): LlmModelRef;
|
|
1405
|
+
getTools(): Tool[];
|
|
1406
|
+
getSkills(): Skill$1[];
|
|
1407
|
+
getPhases(): PhaseRegistry | undefined;
|
|
1408
|
+
getCwd(): string | undefined;
|
|
1379
1409
|
private emitToListeners;
|
|
1380
1410
|
flushEvents(): Promise<void>;
|
|
1381
1411
|
private processEvents;
|
|
@@ -1434,6 +1464,7 @@ declare class Agent {
|
|
|
1434
1464
|
waitForIdle(): Promise<void>;
|
|
1435
1465
|
private resolveRunConfig;
|
|
1436
1466
|
private createContextSnapshot;
|
|
1467
|
+
private cloneOptions;
|
|
1437
1468
|
}
|
|
1438
1469
|
|
|
1439
1470
|
declare function createId(prefix: string): string;
|
package/dist/index.js
CHANGED
|
@@ -94,6 +94,9 @@ var createOutcome = {
|
|
|
94
94
|
id: createId("out"),
|
|
95
95
|
message
|
|
96
96
|
};
|
|
97
|
+
if (output.payload !== void 0) {
|
|
98
|
+
outcome.payload = output.payload;
|
|
99
|
+
}
|
|
97
100
|
if (toolResults.length > 0) {
|
|
98
101
|
outcome.toolResults = toolResults;
|
|
99
102
|
}
|
|
@@ -3426,14 +3429,14 @@ var Agent = class {
|
|
|
3426
3429
|
return loadExtensionsFromPath(targetPath);
|
|
3427
3430
|
}
|
|
3428
3431
|
constructor(options) {
|
|
3429
|
-
const context =
|
|
3432
|
+
const context = prepareAgentContext(options.context);
|
|
3430
3433
|
this.options = {
|
|
3431
3434
|
...options,
|
|
3432
3435
|
context
|
|
3433
3436
|
};
|
|
3434
3437
|
this.state = {
|
|
3435
3438
|
...this.options.sessionId ? { sessionId: this.options.sessionId } : {},
|
|
3436
|
-
context:
|
|
3439
|
+
context: prepareAgentContext(context),
|
|
3437
3440
|
model: this.options.model,
|
|
3438
3441
|
tools: this.options.context.tools ?? [],
|
|
3439
3442
|
isRunning: false
|
|
@@ -3445,6 +3448,142 @@ var Agent = class {
|
|
|
3445
3448
|
this.listeners.delete(listener);
|
|
3446
3449
|
};
|
|
3447
3450
|
}
|
|
3451
|
+
appendUserMessage(input) {
|
|
3452
|
+
this.appendMessage(createMessage("user", input));
|
|
3453
|
+
}
|
|
3454
|
+
appendMessage(message) {
|
|
3455
|
+
this.appendMessages([message]);
|
|
3456
|
+
}
|
|
3457
|
+
appendMessages(messages) {
|
|
3458
|
+
this.setMessages([...this.options.context.messages, ...snapshotMessages(messages)]);
|
|
3459
|
+
}
|
|
3460
|
+
runWithUserInput(input, options) {
|
|
3461
|
+
this.appendUserMessage(input);
|
|
3462
|
+
return this.run(options);
|
|
3463
|
+
}
|
|
3464
|
+
runWithMessage(message, options) {
|
|
3465
|
+
this.appendMessage(message);
|
|
3466
|
+
return this.run(options);
|
|
3467
|
+
}
|
|
3468
|
+
getContext() {
|
|
3469
|
+
return prepareAgentContext(this.options.context);
|
|
3470
|
+
}
|
|
3471
|
+
setContext(context) {
|
|
3472
|
+
const nextContext = prepareAgentContext(context);
|
|
3473
|
+
this.options = {
|
|
3474
|
+
...this.options,
|
|
3475
|
+
context: nextContext
|
|
3476
|
+
};
|
|
3477
|
+
this.state.context = prepareAgentContext(nextContext, this.extensionRunner);
|
|
3478
|
+
this.state.tools = this.state.context.tools ?? [];
|
|
3479
|
+
}
|
|
3480
|
+
updateContext(updater) {
|
|
3481
|
+
this.setContext(updater(this.getContext()));
|
|
3482
|
+
}
|
|
3483
|
+
forkContext(overrides = {}) {
|
|
3484
|
+
return prepareAgentContext({
|
|
3485
|
+
...this.getContext(),
|
|
3486
|
+
...overrides
|
|
3487
|
+
});
|
|
3488
|
+
}
|
|
3489
|
+
getMessages() {
|
|
3490
|
+
return snapshotMessages(this.options.context.messages);
|
|
3491
|
+
}
|
|
3492
|
+
setMessages(messages) {
|
|
3493
|
+
this.setContext({
|
|
3494
|
+
...this.options.context,
|
|
3495
|
+
messages: snapshotMessages(messages)
|
|
3496
|
+
});
|
|
3497
|
+
}
|
|
3498
|
+
clearMessages() {
|
|
3499
|
+
this.setMessages([]);
|
|
3500
|
+
}
|
|
3501
|
+
getTranscript() {
|
|
3502
|
+
return this.getMessages();
|
|
3503
|
+
}
|
|
3504
|
+
replaceTranscript(messages) {
|
|
3505
|
+
this.setMessages(messages);
|
|
3506
|
+
}
|
|
3507
|
+
getConfig() {
|
|
3508
|
+
return this.cloneOptions(this.options);
|
|
3509
|
+
}
|
|
3510
|
+
setConfig(config) {
|
|
3511
|
+
const context = prepareAgentContext(config.context);
|
|
3512
|
+
this.options = {
|
|
3513
|
+
...config,
|
|
3514
|
+
context,
|
|
3515
|
+
...config.extensions ? { extensions: config.extensions.slice() } : {}
|
|
3516
|
+
};
|
|
3517
|
+
this.state.sessionId = config.sessionId;
|
|
3518
|
+
this.state.context = prepareAgentContext(context, this.extensionRunner);
|
|
3519
|
+
this.state.model = config.model;
|
|
3520
|
+
this.state.tools = this.state.context.tools ?? [];
|
|
3521
|
+
}
|
|
3522
|
+
updateConfig(updater) {
|
|
3523
|
+
this.setConfig(updater(this.getConfig()));
|
|
3524
|
+
}
|
|
3525
|
+
setSessionId(sessionId) {
|
|
3526
|
+
this.options = {
|
|
3527
|
+
...this.options,
|
|
3528
|
+
sessionId
|
|
3529
|
+
};
|
|
3530
|
+
this.state.sessionId = sessionId;
|
|
3531
|
+
}
|
|
3532
|
+
getSessionId() {
|
|
3533
|
+
return this.state.sessionId;
|
|
3534
|
+
}
|
|
3535
|
+
setModel(model) {
|
|
3536
|
+
this.options = {
|
|
3537
|
+
...this.options,
|
|
3538
|
+
model
|
|
3539
|
+
};
|
|
3540
|
+
this.state.model = model;
|
|
3541
|
+
}
|
|
3542
|
+
setTools(tools) {
|
|
3543
|
+
this.setContext({
|
|
3544
|
+
...this.options.context,
|
|
3545
|
+
tools: tools.slice()
|
|
3546
|
+
});
|
|
3547
|
+
}
|
|
3548
|
+
setSkills(skills) {
|
|
3549
|
+
this.setContext({
|
|
3550
|
+
...this.options.context,
|
|
3551
|
+
skills: skills.slice()
|
|
3552
|
+
});
|
|
3553
|
+
}
|
|
3554
|
+
setPhases(phases) {
|
|
3555
|
+
this.setContext({
|
|
3556
|
+
...this.options.context,
|
|
3557
|
+
phases: clonePhaseRegistry(phases)
|
|
3558
|
+
});
|
|
3559
|
+
}
|
|
3560
|
+
setCwd(cwd) {
|
|
3561
|
+
this.options = {
|
|
3562
|
+
...this.options,
|
|
3563
|
+
cwd
|
|
3564
|
+
};
|
|
3565
|
+
}
|
|
3566
|
+
setStream(stream) {
|
|
3567
|
+
this.options = {
|
|
3568
|
+
...this.options,
|
|
3569
|
+
stream
|
|
3570
|
+
};
|
|
3571
|
+
}
|
|
3572
|
+
getModel() {
|
|
3573
|
+
return this.state.model;
|
|
3574
|
+
}
|
|
3575
|
+
getTools() {
|
|
3576
|
+
return this.state.context.tools.slice();
|
|
3577
|
+
}
|
|
3578
|
+
getSkills() {
|
|
3579
|
+
return this.state.context.skills.slice();
|
|
3580
|
+
}
|
|
3581
|
+
getPhases() {
|
|
3582
|
+
return this.state.context.phases ? clonePhaseRegistry(this.state.context.phases) : void 0;
|
|
3583
|
+
}
|
|
3584
|
+
getCwd() {
|
|
3585
|
+
return this.options.cwd;
|
|
3586
|
+
}
|
|
3448
3587
|
emitToListeners(event) {
|
|
3449
3588
|
for (const listener of this.listeners) {
|
|
3450
3589
|
try {
|
|
@@ -3590,7 +3729,7 @@ var Agent = class {
|
|
|
3590
3729
|
const resolved = this.resolveRunConfig(config);
|
|
3591
3730
|
const extensions = resolved.extensions ?? [];
|
|
3592
3731
|
await this.loadExtensions(extensions, resolved.cwd);
|
|
3593
|
-
const runContext =
|
|
3732
|
+
const runContext = prepareAgentContext(resolved.context, this.extensionRunner);
|
|
3594
3733
|
const sessionId = resolved.sessionId ?? this.state.sessionId;
|
|
3595
3734
|
this.options = resolved;
|
|
3596
3735
|
if (sessionId) {
|
|
@@ -3641,11 +3780,11 @@ var Agent = class {
|
|
|
3641
3780
|
onModelTranscript: resolved.onModelTranscript
|
|
3642
3781
|
});
|
|
3643
3782
|
const nextContext = {
|
|
3644
|
-
...
|
|
3783
|
+
...prepareAgentContext(resolved.context),
|
|
3645
3784
|
messages: snapshotMessages(result.messages)
|
|
3646
3785
|
};
|
|
3647
3786
|
this.state.sessionId = result.sessionId;
|
|
3648
|
-
this.state.context =
|
|
3787
|
+
this.state.context = prepareAgentContext(nextContext, this.extensionRunner);
|
|
3649
3788
|
this.state.currentResult = result;
|
|
3650
3789
|
this.options = {
|
|
3651
3790
|
...resolved,
|
|
@@ -3689,7 +3828,7 @@ ${additionalInstructions}` : content;
|
|
|
3689
3828
|
*/
|
|
3690
3829
|
async phase(name) {
|
|
3691
3830
|
await this.loadExtensions(this.options.extensions ?? [], this.options.cwd);
|
|
3692
|
-
const registry =
|
|
3831
|
+
const registry = prepareAgentContext(this.options.context, this.extensionRunner).phases?.phases;
|
|
3693
3832
|
const phase = registry?.get(name) ?? [...registry?.values() ?? []].find((candidate) => candidate.name === name);
|
|
3694
3833
|
return phase ? readPhaseContent(phase) : "";
|
|
3695
3834
|
}
|
|
@@ -3705,7 +3844,7 @@ ${additionalInstructions}` : content;
|
|
|
3705
3844
|
...this.options,
|
|
3706
3845
|
...config
|
|
3707
3846
|
};
|
|
3708
|
-
const context =
|
|
3847
|
+
const context = prepareAgentContext(config?.context ?? this.createContextSnapshot());
|
|
3709
3848
|
return {
|
|
3710
3849
|
...merged,
|
|
3711
3850
|
context,
|
|
@@ -3713,10 +3852,23 @@ ${additionalInstructions}` : content;
|
|
|
3713
3852
|
};
|
|
3714
3853
|
}
|
|
3715
3854
|
createContextSnapshot() {
|
|
3716
|
-
return
|
|
3855
|
+
return prepareAgentContext(this.options.context);
|
|
3856
|
+
}
|
|
3857
|
+
cloneOptions(options) {
|
|
3858
|
+
return {
|
|
3859
|
+
...options,
|
|
3860
|
+
context: prepareAgentContext(options.context),
|
|
3861
|
+
...options.extensions ? { extensions: options.extensions.slice() } : {}
|
|
3862
|
+
};
|
|
3717
3863
|
}
|
|
3718
3864
|
};
|
|
3719
|
-
function
|
|
3865
|
+
function clonePhaseRegistry(registry) {
|
|
3866
|
+
return {
|
|
3867
|
+
phases: new Map(registry.phases),
|
|
3868
|
+
entryPhaseId: registry.entryPhaseId
|
|
3869
|
+
};
|
|
3870
|
+
}
|
|
3871
|
+
function prepareAgentContext(context, extensionRunner) {
|
|
3720
3872
|
const phases = /* @__PURE__ */ new Map();
|
|
3721
3873
|
phases.set(DEFAULT_PHASE_ID, createDefaultPhase());
|
|
3722
3874
|
for (const [id, phase] of context.phases?.phases ?? []) {
|