@rowan-agent/agent 0.14.0 → 0.14.2

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 CHANGED
@@ -110,6 +110,8 @@ type RunInteraction = Readonly<{
110
110
  status: RunInteractionStatus;
111
111
  answer?: JsonValue;
112
112
  reply?: string;
113
+ /** The Run is only waiting for the next user message, not asking a question. */
114
+ turnBoundary?: true;
113
115
  toolCallId?: string;
114
116
  result?: Readonly<{
115
117
  answered?: string;
@@ -543,7 +545,7 @@ type PhaseExecution = {
543
545
  }): Promise<ModelInvokeOutput>;
544
546
  reportStatus(status: PhaseStatus): Promise<void>;
545
547
  executeTool(context: AgentContext, toolCall: ToolCall): Promise<ToolResult>;
546
- executeTools(context: AgentContext, toolCalls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
548
+ executeTools(context: AgentContext, toolCalls: readonly ToolCall[], contentBlocks?: readonly ContentBlock[]): Promise<readonly ToolResult[]>;
547
549
  interaction: RunInteractionDriver;
548
550
  /** Message lifecycle manager for streaming updates from programmatic phases */
549
551
  messages: PhaseMessageManager;
@@ -1440,6 +1442,8 @@ interface OwnedStore {
1440
1442
  expectedRevision: number;
1441
1443
  requestMessageId: MessageId;
1442
1444
  calls: readonly ToolCallReservation[];
1445
+ /** The model response's blocks, so the request message keeps what preceded the Tool Calls. */
1446
+ contentBlocks?: readonly ContentBlock[];
1443
1447
  }): Promise<ToolBatchCommit>;
1444
1448
  startToolCall(input: {
1445
1449
  runId: RunId;
@@ -2386,12 +2390,9 @@ declare class InMemoryStore implements DurableStore {
2386
2390
  execution: ExecutionToken;
2387
2391
  expectedRevision: number;
2388
2392
  requestMessageId: MessageId;
2389
- calls: readonly Readonly<{
2390
- providerToolCallId: string;
2391
- name: string;
2392
- args: JsonValue;
2393
- toolCallId?: ToolCallId;
2394
- }>[];
2393
+ calls: readonly ToolCallReservation[];
2394
+ /** The model response's blocks, so the request message keeps what preceded the Tool Calls. */
2395
+ contentBlocks?: readonly ContentBlock[];
2395
2396
  }): ToolBatchCommit;
2396
2397
  startToolCall(lease: OwnerLease, input: {
2397
2398
  runId: RunId;
@@ -2605,6 +2606,7 @@ declare class SqliteStore implements DurableStore {
2605
2606
  args: JsonValue;
2606
2607
  toolCallId?: ToolCallId;
2607
2608
  }>[];
2609
+ contentBlocks?: readonly ContentBlock[];
2608
2610
  }): Promise<ToolBatchCommit>;
2609
2611
  startToolCall(lease: OwnerLease, input: {
2610
2612
  runId: RunId;
package/dist/index.js CHANGED
@@ -2537,6 +2537,7 @@ async function executePhaseWithModel(ctx) {
2537
2537
  messages: ctx.messageManager.visible()
2538
2538
  };
2539
2539
  let executableToolCalls;
2540
+ let roundContentBlocks;
2540
2541
  const checkpoint = ctx.execution.interaction.checkpoint();
2541
2542
  if (checkpoint && typeof checkpoint === "object" && checkpoint.kind === "tool_call_suspension") {
2542
2543
  const toolSuspension = checkpoint;
@@ -2575,11 +2576,12 @@ async function executePhaseWithModel(ctx) {
2575
2576
  executableToolCalls = collected.toolCalls.filter(
2576
2577
  (toolCall) => executableToolNames.has(toolCall.name)
2577
2578
  );
2579
+ roundContentBlocks = collected.contentBlocks;
2578
2580
  if (executableToolCalls.length === 0) {
2579
2581
  return output;
2580
2582
  }
2581
2583
  }
2582
- const results = await ctx.execution.executeTools(roundContext, executableToolCalls);
2584
+ const results = await ctx.execution.executeTools(roundContext, executableToolCalls, roundContentBlocks);
2583
2585
  for (const result of results) {
2584
2586
  const messageId = ctx.messageManager.start("tool", createToolResultContent(result), {
2585
2587
  phase: ctx.phase.name
@@ -3055,6 +3057,7 @@ async function executeToolCall(input) {
3055
3057
  result = await input.config.runtime.tools({
3056
3058
  config: input.config,
3057
3059
  toolCall: input.toolCall,
3060
+ contentBlocks: input.contentBlocks,
3058
3061
  driver: input.driver
3059
3062
  });
3060
3063
  } else {
@@ -3082,6 +3085,7 @@ async function executeToolCalls(input) {
3082
3085
  const results2 = await input.config.runtime.toolsBatch({
3083
3086
  config: input.config,
3084
3087
  toolCalls: input.toolCalls,
3088
+ contentBlocks: input.contentBlocks,
3085
3089
  driver: input.driver
3086
3090
  });
3087
3091
  if (results2.length !== input.toolCalls.length) throw new Error("Runtime returned an invalid Tool batch result");
@@ -3187,7 +3191,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
3187
3191
  return result;
3188
3192
  });
3189
3193
  },
3190
- async executeTools(phaseContext, toolCalls) {
3194
+ async executeTools(phaseContext, toolCalls, contentBlocks) {
3191
3195
  return runTurn(async () => {
3192
3196
  const tools = phaseContext.tools.filter((tool) => tool.name !== PhaseRouteTool);
3193
3197
  for (const toolCall of toolCalls) {
@@ -3204,6 +3208,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
3204
3208
  },
3205
3209
  tools,
3206
3210
  toolCalls,
3211
+ contentBlocks,
3207
3212
  driver: interaction
3208
3213
  });
3209
3214
  for (const result of results) {
@@ -3449,6 +3454,7 @@ async function executeOnce(input) {
3449
3454
  kind: "user_input",
3450
3455
  phase: error.request.phase,
3451
3456
  prompt: error.request.prompt,
3457
+ turnBoundary: true,
3452
3458
  status: "pending",
3453
3459
  createdAt: error.request.requestedAt
3454
3460
  };
@@ -6530,7 +6536,7 @@ var AgentRuntime = class _AgentRuntime {
6530
6536
  },
6531
6537
  onContext: assembly.setContext,
6532
6538
  runtime: {
6533
- tools: ({ toolCall, driver }) => {
6539
+ tools: ({ toolCall, contentBlocks, driver }) => {
6534
6540
  const task = toolQueue.then(async () => {
6535
6541
  const execution = await this.executeToolBatch({
6536
6542
  run,
@@ -6539,6 +6545,7 @@ var AgentRuntime = class _AgentRuntime {
6539
6545
  expectedRevision: executionRevision,
6540
6546
  toolConfig: executionTools,
6541
6547
  toolCalls: [toolCall],
6548
+ contentBlocks,
6542
6549
  signal: controller.signal,
6543
6550
  driver,
6544
6551
  onRevision: (rev) => {
@@ -6551,7 +6558,7 @@ var AgentRuntime = class _AgentRuntime {
6551
6558
  toolQueue = task.then(() => void 0, () => void 0);
6552
6559
  return task;
6553
6560
  },
6554
- toolsBatch: ({ toolCalls, driver }) => {
6561
+ toolsBatch: ({ toolCalls, contentBlocks, driver }) => {
6555
6562
  const task = toolQueue.then(async () => {
6556
6563
  const execution = await this.executeToolBatch({
6557
6564
  run,
@@ -6560,6 +6567,7 @@ var AgentRuntime = class _AgentRuntime {
6560
6567
  expectedRevision: executionRevision,
6561
6568
  toolConfig: executionTools,
6562
6569
  toolCalls,
6570
+ contentBlocks,
6563
6571
  signal: controller.signal,
6564
6572
  driver,
6565
6573
  onRevision: (rev) => {
@@ -6675,7 +6683,12 @@ var AgentRuntime = class _AgentRuntime {
6675
6683
  execution: claim.execution,
6676
6684
  expectedRevision: executionRevision,
6677
6685
  failure: { code: "execution_failed", message: error instanceof Error ? error.message : "Execution failed." }
6678
- }).catch(() => void 0);
6686
+ }).catch(async (commitError) => {
6687
+ await this.owned.cancelRun({
6688
+ runId: run.id,
6689
+ reason: commitError instanceof Error ? commitError.message : "Run failure could not be committed."
6690
+ }).catch(() => void 0);
6691
+ });
6679
6692
  return;
6680
6693
  }
6681
6694
  throw error;
@@ -6755,6 +6768,7 @@ var AgentRuntime = class _AgentRuntime {
6755
6768
  execution: input.execution,
6756
6769
  expectedRevision: revision,
6757
6770
  requestMessageId: createId("msg"),
6771
+ contentBlocks: input.contentBlocks,
6758
6772
  calls: input.toolCalls.map((tc, i) => ({
6759
6773
  toolCallId: toolCallIds[i],
6760
6774
  providerToolCallId: tc.id,
@@ -6929,6 +6943,7 @@ var AgentRuntime = class _AgentRuntime {
6929
6943
  execution: input.execution,
6930
6944
  expectedRevision: revision,
6931
6945
  requestMessageId: createId("msg"),
6946
+ contentBlocks: input.contentBlocks,
6932
6947
  calls: [{
6933
6948
  toolCallId,
6934
6949
  providerToolCallId,
@@ -7011,6 +7026,7 @@ var AgentRuntime = class _AgentRuntime {
7011
7026
  execution: input.execution,
7012
7027
  expectedRevision: revision,
7013
7028
  requestMessageId: createId("msg"),
7029
+ contentBlocks: input.contentBlocks,
7014
7030
  calls: [{ toolCallId, providerToolCallId, name: toolCall.name, args: toJsonValue(toolCall.args) }]
7015
7031
  });
7016
7032
  setRevision(reserved2.run.revision);
@@ -7024,6 +7040,7 @@ var AgentRuntime = class _AgentRuntime {
7024
7040
  execution: input.execution,
7025
7041
  expectedRevision: revision,
7026
7042
  requestMessageId: createId("msg"),
7043
+ contentBlocks: input.contentBlocks,
7027
7044
  calls: [{ toolCallId, providerToolCallId, name: toolCall.name, args: toJsonValue(toolCall.args) }]
7028
7045
  });
7029
7046
  setRevision(reserved2.run.revision);
@@ -7052,6 +7069,7 @@ var AgentRuntime = class _AgentRuntime {
7052
7069
  execution: input.execution,
7053
7070
  expectedRevision: revision,
7054
7071
  requestMessageId: createId("msg"),
7072
+ contentBlocks: input.contentBlocks,
7055
7073
  calls: [{ toolCallId, providerToolCallId, name: toolCall.name, args: toJsonValue(toolCall.args) }]
7056
7074
  });
7057
7075
  setRevision(reserved2.run.revision);
@@ -7074,6 +7092,7 @@ var AgentRuntime = class _AgentRuntime {
7074
7092
  execution: input.execution,
7075
7093
  expectedRevision: revision,
7076
7094
  requestMessageId: createId("msg"),
7095
+ contentBlocks: input.contentBlocks,
7077
7096
  calls: [{ toolCallId, providerToolCallId, name: toolCall.name, args: toJsonValue(toolCall.args) }]
7078
7097
  });
7079
7098
  setRevision(committed.run.revision);
@@ -7872,7 +7891,10 @@ var InMemoryStore = class _InMemoryStore {
7872
7891
  this.commitInteractionRecord(waitingRun, interaction, "replied", void 0, replyText);
7873
7892
  }
7874
7893
  delete waitingRun.openInteractions;
7875
- delete waitingRun.interactionAnswers;
7894
+ waitingRun.interactionAnswers = {
7895
+ ...waitingRun.interactionAnswers ?? {},
7896
+ ...Object.fromEntries(openInteractions.map(({ id }) => [id, { status: "replied", reply: replyText }]))
7897
+ };
7876
7898
  if (waitingRun.checkpoint?.data && typeof waitingRun.checkpoint.data === "object") {
7877
7899
  const stored = waitingRun.checkpoint.data.runInteractions ?? waitingRun.checkpoint.data.phaseInteractions;
7878
7900
  if (stored?.requests && Array.isArray(stored.requests)) {
@@ -8144,7 +8166,8 @@ var InMemoryStore = class _InMemoryStore {
8144
8166
  input.expectedRevision,
8145
8167
  input.execution.executionId,
8146
8168
  input.requestMessageId,
8147
- input.calls
8169
+ input.calls,
8170
+ input.contentBlocks ?? null
8148
8171
  ]);
8149
8172
  const replay = this.replayOperation(operationKey, operationPayload);
8150
8173
  if (replay) return clone(replay);
@@ -8173,13 +8196,7 @@ var InMemoryStore = class _InMemoryStore {
8173
8196
  agentId: run.agentId,
8174
8197
  runId: run.id,
8175
8198
  role: "assistant",
8176
- content: toolCalls.map((toolCall) => ({
8177
- type: "tool_use",
8178
- toolCallId: toolCall.id,
8179
- providerToolCallId: toolCall.providerToolCallId,
8180
- name: toolCall.name,
8181
- input: clone(toolCall.args)
8182
- })),
8199
+ content: requestMessageContent(toolCalls, input.contentBlocks),
8183
8200
  sequenceWithinRun: this.nextMessageSequence(run.id),
8184
8201
  createdAt: timestamp
8185
8202
  };
@@ -9003,6 +9020,32 @@ function digestToolEffects(toolCalls) {
9003
9020
  function assertToolValue(value, argument) {
9004
9021
  assertUtf8ByteLimit(canonicalJson(value), TOOL_VALUE_JSON_BYTES, argument);
9005
9022
  }
9023
+ function requestMessageContent(toolCalls, contentBlocks) {
9024
+ const toolUse = (toolCall) => ({
9025
+ type: "tool_use",
9026
+ toolCallId: toolCall.id,
9027
+ providerToolCallId: toolCall.providerToolCallId,
9028
+ name: toolCall.name,
9029
+ input: clone(toolCall.args)
9030
+ });
9031
+ if (!contentBlocks) return toolCalls.map(toolUse);
9032
+ const reserved = new Map(toolCalls.map((toolCall) => [toolCall.providerToolCallId, toolCall]));
9033
+ const parts = [];
9034
+ for (const block of contentBlocks) {
9035
+ if (block.type === "text") {
9036
+ parts.push({ type: "text", text: block.text });
9037
+ } else if (block.type === "thinking") {
9038
+ parts.push({ type: "thinking", thinking: block.thinking, ...block.signature ? { signature: block.signature } : {} });
9039
+ } else {
9040
+ const toolCall = reserved.get(block.id);
9041
+ if (!toolCall) continue;
9042
+ reserved.delete(block.id);
9043
+ parts.push(toolUse(toolCall));
9044
+ }
9045
+ }
9046
+ for (const toolCall of reserved.values()) parts.push(toolUse(toolCall));
9047
+ return parts;
9048
+ }
9006
9049
 
9007
9050
  // src/runtime/sqlite-durable-store.ts
9008
9051
  import { Database } from "bun:sqlite";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowan-agent/agent",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,7 +23,7 @@
23
23
  "build": "tsup && bun scripts/check-public-interface.ts"
24
24
  },
25
25
  "dependencies": {
26
- "@rowan-agent/models": "0.7.0",
26
+ "@rowan-agent/models": "0.7.1",
27
27
  "jiti": "2.7.0",
28
28
  "typebox": "^1.0.0",
29
29
  "yaml": "^2.7.0"