@rowan-agent/agent 0.15.0 → 0.15.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.
Files changed (2) hide show
  1. package/dist/index.js +62 -31
  2. package/package.json +1 -1
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: error ? JSON.stringify({ ok: false, error }) : '{"ok": true}',
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
- collected.toolCalls.some((candidate) => candidate.name !== PhaseRouteTool) ? "Route must be called separately after ordinary tools finish; this route decision was ignored." : void 0
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) => ({ name: r.instanceId, output: r.payload }));
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);
@@ -3280,8 +3305,15 @@ async function executeParallelPhase(config, state, registry, phase, payload, ins
3280
3305
  const toolExecutionManager = createToolExecutionManager();
3281
3306
  const execution = createPhaseExecution(config, state, phase, messageManager, toolExecutionManager, registry);
3282
3307
  const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
3283
- const output = await executePhase(runtime);
3308
+ let output = await executePhase(runtime);
3284
3309
  if (phaseMsgId) removePhaseMessage(messages, phaseMsgId);
3310
+ if (config.afterPhase) {
3311
+ const extAfter = await config.afterPhase(phase.name, output);
3312
+ if (extAfter?.output) output = extAfter.output;
3313
+ }
3314
+ if (output.status) {
3315
+ await execution.reportStatus(output.status);
3316
+ }
3285
3317
  const decision = output.toolCalls ? extractRouteCall(output.toolCalls) : void 0;
3286
3318
  const resultPayload = decision?.decision[0]?.payload !== void 0 ? normalizePayload(decision.decision[0].payload) : output.payload;
3287
3319
  return { instanceId, phaseId: phase.name, payload: resultPayload, content: output.message ?? `${phase.name} completed.` };
@@ -6532,7 +6564,30 @@ var AgentRuntime = class _AgentRuntime {
6532
6564
  interactionAnswers: claim.run.interactionAnswers,
6533
6565
  signal: controller.signal,
6534
6566
  beforePhase: assembly.beforePhase,
6535
- afterPhase: assembly.afterPhase,
6567
+ afterPhase: async (phaseId, output) => {
6568
+ const extAfter = assembly.afterPhase ? await assembly.afterPhase(phaseId, output) : {};
6569
+ const effectiveOutput = extAfter.output ?? output;
6570
+ if (!extAfter.abort && (phaseId === COMPACT_PHASE_ID || isCompactionOutcome(effectiveOutput.payload))) {
6571
+ const active = this.executions.get(run.id);
6572
+ if (active?.executionId === claim.execution.executionId && !this.cancellationRequested.has(run.id) && !controller.signal.aborted) {
6573
+ const summary = compactSummary(effectiveOutput.payload);
6574
+ const instructions = compactInstructions2(run) ?? compactOutputInstructions(effectiveOutput.payload);
6575
+ if (summary) {
6576
+ const covered = claim.history.at(-1);
6577
+ const record = {
6578
+ id: createId("compact"),
6579
+ agentId: run.agentId,
6580
+ summary,
6581
+ ...covered ? { coveredThrough: { messageId: covered.id, sequence: covered.sequenceWithinRun } } : {},
6582
+ ...instructions ? { instructions } : {},
6583
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
6584
+ };
6585
+ await this.owned.commitContextCompaction(record);
6586
+ }
6587
+ }
6588
+ }
6589
+ return extAfter;
6590
+ },
6536
6591
  beforePrompt: assembly.beforePrompt,
6537
6592
  onPhaseEntered: async (phaseId) => {
6538
6593
  const active = this.executions.get(run.id);
@@ -6639,14 +6694,6 @@ var AgentRuntime = class _AgentRuntime {
6639
6694
  const compactResult = await executeModel(compactContext);
6640
6695
  const summary = compactResult.type === "completed" ? compactSummary(compactResult.outcome.payload) : void 0;
6641
6696
  if (summary) {
6642
- const covered = claim.history.at(-1);
6643
- await this.owned.commitContextCompaction({
6644
- id: createId("compact"),
6645
- agentId: run.agentId,
6646
- summary,
6647
- ...covered ? { coveredThrough: { messageId: covered.id, sequence: covered.sequenceWithinRun } } : {},
6648
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
6649
- });
6650
6697
  modelMessages = await this.owned.contextMessages(run.agentId);
6651
6698
  executionContext = buildExecutionContext(modelMessages);
6652
6699
  result = await executeModel(executionContext);
@@ -6695,22 +6742,6 @@ var AgentRuntime = class _AgentRuntime {
6695
6742
  }
6696
6743
  if (result.type === "completed") {
6697
6744
  const output = latestAssistant(run, result.messages, modelMessages.length);
6698
- if (controlKind === "compact" || isCompactionOutcome(result.outcome.payload)) {
6699
- const summary = compactSummary(result.outcome.payload);
6700
- const instructions = compactInstructions2(run) ?? compactOutputInstructions(result.outcome.payload);
6701
- if (summary) {
6702
- const covered = claim.history.at(-1);
6703
- const record = {
6704
- id: createId("compact"),
6705
- agentId: run.agentId,
6706
- summary,
6707
- ...covered ? { coveredThrough: { messageId: covered.id, sequence: covered.sequenceWithinRun } } : {},
6708
- ...instructions ? { instructions } : {},
6709
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
6710
- };
6711
- await this.owned.commitContextCompaction(record);
6712
- }
6713
- }
6714
6745
  await this.owned.commitOutcome({ runId: run.id, execution: claim.execution, expectedRevision: executionRevision, outcome: durableOutcome(result.outcome), ...output ? { output } : {} });
6715
6746
  this.transientEvents.clear(run.id, claim.execution.executionId, true);
6716
6747
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowan-agent/agent",
3
- "version": "0.15.0",
3
+ "version": "0.15.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",