@rowan-agent/agent 0.15.1 → 0.15.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +19 -0
- package/dist/index.js +113 -8
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1137,6 +1137,12 @@ interface OwnedStore {
|
|
|
1137
1137
|
phaseId: string;
|
|
1138
1138
|
visit: number;
|
|
1139
1139
|
}): Promise<RunRecord>;
|
|
1140
|
+
commitPhaseOutput(input: {
|
|
1141
|
+
runId: RunId;
|
|
1142
|
+
execution: ExecutionToken;
|
|
1143
|
+
expectedRevision: number;
|
|
1144
|
+
message: AssistantMessage;
|
|
1145
|
+
}): Promise<RunRecord>;
|
|
1140
1146
|
commitInputRequired(input: {
|
|
1141
1147
|
runId: RunId;
|
|
1142
1148
|
execution: ExecutionToken;
|
|
@@ -2368,6 +2374,13 @@ declare class InMemoryStore implements DurableStore {
|
|
|
2368
2374
|
phaseId: string;
|
|
2369
2375
|
visit: number;
|
|
2370
2376
|
}): RunRecord;
|
|
2377
|
+
/** Commit a parallel Phase's reply while its Run is still running. */
|
|
2378
|
+
commitPhaseOutput(lease: OwnerLease, input: {
|
|
2379
|
+
runId: RunId;
|
|
2380
|
+
execution: ExecutionToken;
|
|
2381
|
+
expectedRevision: number;
|
|
2382
|
+
message: AssistantMessage;
|
|
2383
|
+
}): RunRecord;
|
|
2371
2384
|
commitInputRequired(lease: OwnerLease, input: {
|
|
2372
2385
|
runId: RunId;
|
|
2373
2386
|
execution: ExecutionToken;
|
|
@@ -2571,6 +2584,12 @@ declare class SqliteStore implements DurableStore {
|
|
|
2571
2584
|
phaseId: string;
|
|
2572
2585
|
visit: number;
|
|
2573
2586
|
}): Promise<RunRecord>;
|
|
2587
|
+
commitPhaseOutput(lease: OwnerLease, input: {
|
|
2588
|
+
runId: RunId;
|
|
2589
|
+
execution: ExecutionToken;
|
|
2590
|
+
expectedRevision: number;
|
|
2591
|
+
message: AssistantMessage;
|
|
2592
|
+
}): Promise<RunRecord>;
|
|
2574
2593
|
commitInputRequired(lease: OwnerLease, input: {
|
|
2575
2594
|
runId: RunId;
|
|
2576
2595
|
execution: ExecutionToken;
|
package/dist/index.js
CHANGED
|
@@ -2512,12 +2512,22 @@ function createToolResultContent(result) {
|
|
|
2512
2512
|
}
|
|
2513
2513
|
];
|
|
2514
2514
|
}
|
|
2515
|
-
function createRouteToolResultContent(toolCall, error) {
|
|
2515
|
+
function createRouteToolResultContent(toolCall, error, executionContext) {
|
|
2516
|
+
const result = error ? { ok: false, error } : { ok: true };
|
|
2517
|
+
if (!error && executionContext) {
|
|
2518
|
+
const { completedPhases, phaseTransitions } = executionContext;
|
|
2519
|
+
if (completedPhases && completedPhases.length > 0) {
|
|
2520
|
+
result.completed_phases = completedPhases;
|
|
2521
|
+
}
|
|
2522
|
+
if (phaseTransitions && phaseTransitions.length > 0) {
|
|
2523
|
+
result.route_history = phaseTransitions.map(({ from, to }) => `${from} \u2192 ${to}`);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2516
2526
|
return [
|
|
2517
2527
|
{
|
|
2518
2528
|
type: "tool_result",
|
|
2519
2529
|
toolUseId: toolCall.id,
|
|
2520
|
-
content:
|
|
2530
|
+
content: JSON.stringify(result),
|
|
2521
2531
|
...error ? { isError: true } : {}
|
|
2522
2532
|
}
|
|
2523
2533
|
];
|
|
@@ -2561,11 +2571,13 @@ async function executePhaseWithModel(ctx) {
|
|
|
2561
2571
|
};
|
|
2562
2572
|
for (const toolCall of collected.toolCalls) {
|
|
2563
2573
|
if (toolCall.name !== PhaseRouteTool) continue;
|
|
2574
|
+
const hasOrdinaryTools = collected.toolCalls.some((candidate) => candidate.name !== PhaseRouteTool);
|
|
2564
2575
|
const messageId = ctx.messageManager.start(
|
|
2565
2576
|
"tool",
|
|
2566
2577
|
createRouteToolResultContent(
|
|
2567
2578
|
toolCall,
|
|
2568
|
-
|
|
2579
|
+
hasOrdinaryTools ? "Route must be called separately after ordinary tools finish; this route decision was ignored." : void 0,
|
|
2580
|
+
!hasOrdinaryTools ? { completedPhases: ctx.completedPhases, phaseTransitions: ctx.state.metrics.phaseTransitions } : void 0
|
|
2569
2581
|
),
|
|
2570
2582
|
{
|
|
2571
2583
|
phase: ctx.phase.name
|
|
@@ -2617,6 +2629,7 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2617
2629
|
let previousPhaseInputMsgId;
|
|
2618
2630
|
let previousResults = resumingSuspendedRun ? state.continuation?.previousResults?.map((result) => ({ ...result })) ?? [] : [];
|
|
2619
2631
|
let pendingInstruction = resumingSuspendedRun ? state.continuation?.pendingInstruction : void 0;
|
|
2632
|
+
const completedPhases = [];
|
|
2620
2633
|
const availablePhases = [];
|
|
2621
2634
|
for (const [, phase] of registry.phases) {
|
|
2622
2635
|
availablePhases.push({
|
|
@@ -2657,7 +2670,16 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2657
2670
|
parallelTasks.set(instanceId, { promise, phaseId: target.phase });
|
|
2658
2671
|
}
|
|
2659
2672
|
const successfulResults = await waitForBackgroundTasks(parallelTasks);
|
|
2660
|
-
previousResults = successfulResults.map((r) => ({
|
|
2673
|
+
previousResults = successfulResults.map((r) => ({
|
|
2674
|
+
name: r.instanceId,
|
|
2675
|
+
output: {
|
|
2676
|
+
message: r.content,
|
|
2677
|
+
...r.payload !== void 0 ? { payload: r.payload } : {}
|
|
2678
|
+
}
|
|
2679
|
+
}));
|
|
2680
|
+
for (const r of successfulResults) {
|
|
2681
|
+
completedPhases.push(r.phaseId);
|
|
2682
|
+
}
|
|
2661
2683
|
pendingInstruction = void 0;
|
|
2662
2684
|
};
|
|
2663
2685
|
if (!resumingSuspendedRun && state.entryPhases && state.entryPhases.length > 0) {
|
|
@@ -2842,7 +2864,7 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2842
2864
|
previousResults = [];
|
|
2843
2865
|
pendingInstruction = void 0;
|
|
2844
2866
|
}
|
|
2845
|
-
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
|
|
2867
|
+
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext, completedPhases };
|
|
2846
2868
|
let output = await executePhase(runtime);
|
|
2847
2869
|
delete state.initialPhasePayload;
|
|
2848
2870
|
delete state.entryPhases;
|
|
@@ -2882,6 +2904,9 @@ async function runPhaseLoop(config, state, registry) {
|
|
|
2882
2904
|
if (output.status) {
|
|
2883
2905
|
await execution.reportStatus(output.status);
|
|
2884
2906
|
}
|
|
2907
|
+
if (output.route !== "continue") {
|
|
2908
|
+
completedPhases.push(currentPhaseId);
|
|
2909
|
+
}
|
|
2885
2910
|
if (phase.name === STOP_PHASE_ID) {
|
|
2886
2911
|
removePhaseMessage(config.context.messages, previousPhaseMsgId);
|
|
2887
2912
|
removePhaseMessage(config.context.messages, previousPhaseInputMsgId);
|
|
@@ -3239,6 +3264,13 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3239
3264
|
}
|
|
3240
3265
|
};
|
|
3241
3266
|
}
|
|
3267
|
+
function parallelPhaseReply(produced) {
|
|
3268
|
+
const last = [...produced].reverse().find((message) => message.role === "assistant");
|
|
3269
|
+
if (!last) return void 0;
|
|
3270
|
+
if (typeof last.content === "string") return last.content.trim() ? last : void 0;
|
|
3271
|
+
if (last.content.some((part) => part.type === "tool_use")) return void 0;
|
|
3272
|
+
return last.content.some((part) => part.type === "text" && part.text.trim()) ? last : void 0;
|
|
3273
|
+
}
|
|
3242
3274
|
async function executeParallelPhase(config, state, registry, phase, payload, instruction, context, availablePhases, instanceId, groupId, index, count, sourcePhaseId) {
|
|
3243
3275
|
const messages = [...context];
|
|
3244
3276
|
const effectivePayload = preparePhasePayload(phase.input, payload);
|
|
@@ -3280,7 +3312,12 @@ async function executeParallelPhase(config, state, registry, phase, payload, ins
|
|
|
3280
3312
|
const toolExecutionManager = createToolExecutionManager();
|
|
3281
3313
|
const execution = createPhaseExecution(config, state, phase, messageManager, toolExecutionManager, registry);
|
|
3282
3314
|
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
|
|
3315
|
+
const phaseStart = messages.length;
|
|
3283
3316
|
let output = await executePhase(runtime);
|
|
3317
|
+
const reply = parallelPhaseReply(messages.slice(phaseStart));
|
|
3318
|
+
if (reply && config.onParallelPhaseOutput) {
|
|
3319
|
+
await config.onParallelPhaseOutput(reply, { mode: "parallel", instanceId, groupId, index, count, sourcePhaseId });
|
|
3320
|
+
}
|
|
3284
3321
|
if (phaseMsgId) removePhaseMessage(messages, phaseMsgId);
|
|
3285
3322
|
if (config.afterPhase) {
|
|
3286
3323
|
const extAfter = await config.afterPhase(phase.name, output);
|
|
@@ -3458,6 +3495,7 @@ async function executeOnce(input) {
|
|
|
3458
3495
|
afterPhase: input.afterPhase,
|
|
3459
3496
|
beforePrompt: input.beforePrompt,
|
|
3460
3497
|
onMessage: input.onMessage,
|
|
3498
|
+
onParallelPhaseOutput: input.onParallelPhaseOutput,
|
|
3461
3499
|
onMessageDelta: input.onMessageDelta,
|
|
3462
3500
|
onThinkingDelta: input.onThinkingDelta,
|
|
3463
3501
|
onOutcome: input.onOutcome,
|
|
@@ -4282,6 +4320,10 @@ function renderInteractionText(record) {
|
|
|
4282
4320
|
const replyStr = record.reply ?? "";
|
|
4283
4321
|
return template.replaceAll("{{prompt}}", record.prompt).replaceAll("{{answer}}", answerStr).replaceAll("{{reply}}", replyStr);
|
|
4284
4322
|
}
|
|
4323
|
+
var PARALLEL_PHASE_METADATA_KEY = "parallelPhase";
|
|
4324
|
+
function isParallelPhaseOutput(message) {
|
|
4325
|
+
return message.role === "assistant" && message.metadata?.[PARALLEL_PHASE_METADATA_KEY] !== void 0;
|
|
4326
|
+
}
|
|
4285
4327
|
function projectModelContext(input) {
|
|
4286
4328
|
const toolInteractionTexts = /* @__PURE__ */ new Map();
|
|
4287
4329
|
for (const message of input.messages) {
|
|
@@ -4297,6 +4339,7 @@ function projectModelContext(input) {
|
|
|
4297
4339
|
}
|
|
4298
4340
|
const projectedMessages = [];
|
|
4299
4341
|
for (const message of input.messages) {
|
|
4342
|
+
if (isParallelPhaseOutput(message)) continue;
|
|
4300
4343
|
if (message.role === "interaction") {
|
|
4301
4344
|
if (message.toolCallId !== void 0) {
|
|
4302
4345
|
continue;
|
|
@@ -6588,6 +6631,33 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6588
6631
|
status
|
|
6589
6632
|
});
|
|
6590
6633
|
},
|
|
6634
|
+
onParallelPhaseOutput: (message, invocation) => {
|
|
6635
|
+
const task = toolQueue.then(async () => {
|
|
6636
|
+
const active = this.executions.get(run.id);
|
|
6637
|
+
if (this.closed || controller.signal.aborted || active?.executionId !== claim.execution.executionId) return;
|
|
6638
|
+
const projected = projectAssistantMessage(message, run.agentId, run.id, 0);
|
|
6639
|
+
const committed = await this.owned.commitPhaseOutput({
|
|
6640
|
+
runId: run.id,
|
|
6641
|
+
execution: claim.execution,
|
|
6642
|
+
expectedRevision: executionRevision,
|
|
6643
|
+
message: {
|
|
6644
|
+
...projected,
|
|
6645
|
+
metadata: {
|
|
6646
|
+
...projected.metadata,
|
|
6647
|
+
[PARALLEL_PHASE_METADATA_KEY]: {
|
|
6648
|
+
groupId: invocation.groupId,
|
|
6649
|
+
instanceId: invocation.instanceId,
|
|
6650
|
+
index: invocation.index,
|
|
6651
|
+
count: invocation.count
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
}
|
|
6655
|
+
});
|
|
6656
|
+
executionRevision = committed.revision;
|
|
6657
|
+
});
|
|
6658
|
+
toolQueue = task.then(() => void 0, () => void 0);
|
|
6659
|
+
return task;
|
|
6660
|
+
},
|
|
6591
6661
|
onMessageDelta: (event) => {
|
|
6592
6662
|
const active = this.executions.get(run.id);
|
|
6593
6663
|
if (this.closed || controller.signal.aborted || active?.executionId !== claim.execution.executionId) return;
|
|
@@ -6675,7 +6745,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6675
6745
|
}
|
|
6676
6746
|
}
|
|
6677
6747
|
if (this.cancellationRequested.has(run.id) || controller.signal.aborted) {
|
|
6678
|
-
const output = latestAssistant(run, result.messages,
|
|
6748
|
+
const output = latestAssistant(run, result.messages, executionContext.messages.length, true);
|
|
6679
6749
|
const reason = this.cancellationReasons.get(run.id) ?? "Agent run stopped.";
|
|
6680
6750
|
await this.owned.cancelRun({
|
|
6681
6751
|
runId: run.id,
|
|
@@ -6698,7 +6768,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6698
6768
|
const output = isToolCallInteraction ? void 0 : latestAssistant(
|
|
6699
6769
|
run,
|
|
6700
6770
|
result.messages,
|
|
6701
|
-
|
|
6771
|
+
executionContext.messages.length
|
|
6702
6772
|
);
|
|
6703
6773
|
const prompt = isToolCallInteraction ? void 0 : output ?? (result.interactions[0]?.prompt ? promptMessage(run, result.interactions[0].prompt, result.messages.length) : void 0);
|
|
6704
6774
|
await this.owned.commitInputRequired({
|
|
@@ -6716,7 +6786,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6716
6786
|
return;
|
|
6717
6787
|
}
|
|
6718
6788
|
if (result.type === "completed") {
|
|
6719
|
-
const output = latestAssistant(run, result.messages,
|
|
6789
|
+
const output = latestAssistant(run, result.messages, executionContext.messages.length);
|
|
6720
6790
|
await this.owned.commitOutcome({ runId: run.id, execution: claim.execution, expectedRevision: executionRevision, outcome: durableOutcome(result.outcome), ...output ? { output } : {} });
|
|
6721
6791
|
this.transientEvents.clear(run.id, claim.execution.executionId, true);
|
|
6722
6792
|
return;
|
|
@@ -8100,6 +8170,32 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8100
8170
|
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8101
8171
|
return result;
|
|
8102
8172
|
}
|
|
8173
|
+
/** Commit a parallel Phase's reply while its Run is still running. */
|
|
8174
|
+
commitPhaseOutput(lease, input) {
|
|
8175
|
+
this.assertOwner(lease);
|
|
8176
|
+
const operationKey = `phase_output:${input.message.id}`;
|
|
8177
|
+
const operationPayload = canonicalJson([input.runId, input.execution.executionId, input.expectedRevision, input.message]);
|
|
8178
|
+
const replay = this.replayOperation(operationKey, operationPayload);
|
|
8179
|
+
if (replay) return clone(replay);
|
|
8180
|
+
const run = this.requireRun(input.runId);
|
|
8181
|
+
this.assertExecution(run, input.execution, input.expectedRevision);
|
|
8182
|
+
this.assertState(run, ["running"]);
|
|
8183
|
+
if (this.messages.has(input.message.id)) throw new RuntimeError("run_state_conflict", { runId: run.id, expected: ["running"], actual: run.state });
|
|
8184
|
+
const message = {
|
|
8185
|
+
...clone(input.message),
|
|
8186
|
+
agentId: run.agentId,
|
|
8187
|
+
runId: run.id,
|
|
8188
|
+
role: "assistant",
|
|
8189
|
+
sequenceWithinRun: this.nextMessageSequence(run.id)
|
|
8190
|
+
};
|
|
8191
|
+
this.messages.set(message.id, message);
|
|
8192
|
+
run.revision += 1;
|
|
8193
|
+
run.updatedAt = createTimestamp();
|
|
8194
|
+
this.appendMessage(run, message);
|
|
8195
|
+
const result = clone(run);
|
|
8196
|
+
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8197
|
+
return result;
|
|
8198
|
+
}
|
|
8103
8199
|
commitInputRequired(lease, input) {
|
|
8104
8200
|
this.assertOwner(lease);
|
|
8105
8201
|
if (typeof input.phase !== "string" || input.phase.length === 0) throw new TypeError("phase must be non-empty");
|
|
@@ -8919,6 +9015,9 @@ var MemoryOwnedStore = class {
|
|
|
8919
9015
|
async commitPhaseEntered(input) {
|
|
8920
9016
|
return this.store.commitPhaseEntered(this.lease, input);
|
|
8921
9017
|
}
|
|
9018
|
+
async commitPhaseOutput(input) {
|
|
9019
|
+
return this.store.commitPhaseOutput(this.lease, input);
|
|
9020
|
+
}
|
|
8922
9021
|
async commitInputRequired(input) {
|
|
8923
9022
|
return this.store.commitInputRequired(this.lease, input);
|
|
8924
9023
|
}
|
|
@@ -9322,6 +9421,9 @@ var SqliteStore = class {
|
|
|
9322
9421
|
async commitPhaseEntered(lease, input) {
|
|
9323
9422
|
return this.invoke(lease, (store, current) => store.commitPhaseEntered(current, input));
|
|
9324
9423
|
}
|
|
9424
|
+
async commitPhaseOutput(lease, input) {
|
|
9425
|
+
return this.invoke(lease, (store, current) => store.commitPhaseOutput(current, input));
|
|
9426
|
+
}
|
|
9325
9427
|
async commitInputRequired(lease, input) {
|
|
9326
9428
|
return this.invoke(lease, (store, current) => store.commitInputRequired(current, input));
|
|
9327
9429
|
}
|
|
@@ -9715,6 +9817,9 @@ var SqliteOwnedStore = class {
|
|
|
9715
9817
|
commitPhaseEntered(input) {
|
|
9716
9818
|
return this.store.commitPhaseEntered(this.lease, input);
|
|
9717
9819
|
}
|
|
9820
|
+
commitPhaseOutput(input) {
|
|
9821
|
+
return this.store.commitPhaseOutput(this.lease, input);
|
|
9822
|
+
}
|
|
9718
9823
|
commitInputRequired(input) {
|
|
9719
9824
|
return this.store.commitInputRequired(this.lease, input);
|
|
9720
9825
|
}
|