@rowan-agent/agent 0.19.0 → 0.19.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
@@ -1689,6 +1689,8 @@ type RunInteractionDriver = Readonly<{
1689
1689
  answers(): ReadonlyMap<string, JsonValue>;
1690
1690
  checkpoint(): JsonValue | undefined;
1691
1691
  clearCheckpoint(): void;
1692
+ answer?(id: string, value: JsonValue): void;
1693
+ clearAnswer?(id: string): void;
1692
1694
  suspend(input?: Readonly<{
1693
1695
  checkpoint?: JsonValue;
1694
1696
  }>): never;
@@ -2029,7 +2031,14 @@ type ModelRetry = Readonly<{
2029
2031
  delayMs: number;
2030
2032
  error: string;
2031
2033
  }>;
2032
- type RunEvent = DurableRunEvent | MessageDelta | ThinkingDelta | ToolCallDelta | PhaseStatusEvent | ModelRetry | Extract<ToolStateChanged, {
2034
+ type LiveInteractionEvent = Readonly<{
2035
+ kind: "live_interaction";
2036
+ durability: "transient";
2037
+ runId: RunId;
2038
+ executionId?: ExecutionId;
2039
+ interaction: RunInteraction;
2040
+ }>;
2041
+ type RunEvent = DurableRunEvent | MessageDelta | ThinkingDelta | ToolCallDelta | PhaseStatusEvent | ModelRetry | LiveInteractionEvent | Extract<ToolStateChanged, {
2033
2042
  durability: "transient";
2034
2043
  }>;
2035
2044
 
@@ -2408,6 +2417,8 @@ declare class AgentRuntime implements AgentRuntime$1 {
2408
2417
  private readonly retryDelayMs?;
2409
2418
  private constructor();
2410
2419
  static init(options: AgentRuntimeOptions): Promise<AgentRuntime>;
2420
+ private publishLiveInteraction;
2421
+ private cancelLiveInteractions;
2411
2422
  private handleRunEnd;
2412
2423
  loadAgents(input: LoadInput<AgentDefinition>): Promise<LoadResult>;
2413
2424
  loadSkills(input: LoadInput<Skill>): Promise<LoadResult>;
@@ -3292,4 +3303,4 @@ declare function parseFrontmatter<T = Record<string, unknown>>(raw: string): Fro
3292
3303
 
3293
3304
  declare function createCoreTools(input?: CoreToolContext): Tool$1[];
3294
3305
 
3295
- export { type AfterToolCall, type AgentConfiguration, type AgentDefinition, type AgentId, type AgentListCursor, type AgentRecord, type AgentRun, AgentRuntime, type AgentRuntimeOptions, type AgentSummary, type AnyRuntimeError, type AssistantContent, type AssistantMessage, type BeforeToolCall, COMPACT_PHASE_ID, type ConfigProvider, type ConfigPutResult, type ConfigResolution, type ConfigToken, type ConfigurationSnapshot, type ContextCandidate, type ContextCompactionRecord, type ContextStatus, type CoreToolContext, DEFAULT_PHASE_ID, type DefinitionLayer, type DurableConsumer, type DurableRunEvent, type DurableStore, type DurableToolResult, type EntryPhaseSpec, type EventCursor, type EventId, type ExecutionCheckpoint, type ExecutionId, type ExecutionToken, type ExtensionAPI, type ExtensionActivationError, type ExtensionActivationResult, type ExtensionCapability, type ExtensionCapabilityContribution, type ExtensionContribution, type ExtensionDisposer, type ExtensionFactory, type ExtensionFactoryResult, type ExtensionHost, ExtensionLifetimeError, type ExtensionLifetimeErrorCode, type ExtensionLoadInput, type ExtensionStateStore, type ExtensionToolContribution, type FrontmatterResult, type HistorySeed, type HookEvent, type HookEventType, type HookHandler, type HostContribution, InMemoryConfigProvider, InMemoryExtensionHost, InMemoryStore, type InteractionRecord, type InvocationCatalogEntry, type InvocationSource, type JsonObject, type JsonPrimitive, type JsonValue, type LoadExtensionsResult, type LoadInput, type LoadResult, type LoadedExtension, type Message, type MessageBase, type MessageCommitted, type MessageContent, type MessageDelta, type MessageId, type MessageRevised, type MessageRevisionResult, type Metadata, type ModelRetry, type OpaqueId, type Outcome, type OwnerLease, type OwnerToken, type Page, type Phase, type PhaseContext, type PhaseContribution, type PhaseExecution, type PhaseExecutionIdentity, type PhaseInput, type PhaseInvocation, type PhaseMessageManager, type PhaseOutput, type PhaseRegistry, type PhaseRegistrySelection, type PhaseState, type PhaseStatus, type PhaseStatusState, type ResolvedResourceView, type ResourceDiagnostic, type ResourceKind, type ResourceRef, ResourceRegistry, ResourceRegistryError, type ResourceRegistryErrorCode, type ResourceSourceId, type ResourceView, type RetentionResult, type RunBoundary, type RunClaim, type RunEndEvent, type RunEvent, type RunFailure, type RunId, type RunInteraction, RunInteractionBoundary, RunInteractionCancelledError, type RunInteractionDriver, type RunInteractionKind, type RunInteractionRequest, type RunInteractionState, type RunInteractionStatus, type RunListCursor, type RunRecord, type RunSnapshot, type RunStartEvent, type RunState, type RunStateChanged, type RunSummary, RuntimeBootstrapRegistry, RuntimeError, type RuntimeErrorCode, type RuntimeErrorDetails, RuntimeExtensionLifetime, STOP_PHASE_ID, type SettingsBadge, type SettingsControl, type SettingsDefinition, type SettingsItem, type SettingsOption, type SettingsSection, type Skill, SqliteStore, type TextContent, type ThinkingContent, type ThinkingDelta, type Tool$1 as Tool, type ToolCallContext, type ToolCallDelta, type ToolCallId, type ToolCallPresentationInput, type ToolCallPresentationOutput, type ToolCallSnapshot, type ToolCallState, type ToolContribution, type ToolDefinition, type ToolExecutionResult, type ToolInvocationContext, type ToolMessage, type ToolMessageContent, type ToolResultContent, type ToolStateChanged, type ToolUseContent, type UserContent, type UserInput, type UserMessage, type WithdrawnUserInput, brandConfigToken, createCompactPhase, createCorePhases, createCoreTools, createDefaultPhase, createStopPhase, isConfigurationSnapshot, isRuntimeError, loadExtensionsFromPath as loadExtensions, loadPhase, loadPhases, loadSkill, loadSkills, mergeToolCall, parseAgentDefinition, parseFrontmatter, resolveConfigurationSnapshot };
3306
+ export { type AfterToolCall, type AgentConfiguration, type AgentDefinition, type AgentId, type AgentListCursor, type AgentRecord, type AgentRun, AgentRuntime, type AgentRuntimeOptions, type AgentSummary, type AnyRuntimeError, type AssistantContent, type AssistantMessage, type BeforeToolCall, COMPACT_PHASE_ID, type ConfigProvider, type ConfigPutResult, type ConfigResolution, type ConfigToken, type ConfigurationSnapshot, type ContextCandidate, type ContextCompactionRecord, type ContextStatus, type CoreToolContext, DEFAULT_PHASE_ID, type DefinitionLayer, type DurableConsumer, type DurableRunEvent, type DurableStore, type DurableToolResult, type EntryPhaseSpec, type EventCursor, type EventId, type ExecutionCheckpoint, type ExecutionId, type ExecutionToken, type ExtensionAPI, type ExtensionActivationError, type ExtensionActivationResult, type ExtensionCapability, type ExtensionCapabilityContribution, type ExtensionContribution, type ExtensionDisposer, type ExtensionFactory, type ExtensionFactoryResult, type ExtensionHost, ExtensionLifetimeError, type ExtensionLifetimeErrorCode, type ExtensionLoadInput, type ExtensionStateStore, type ExtensionToolContribution, type FrontmatterResult, type HistorySeed, type HookEvent, type HookEventType, type HookHandler, type HostContribution, InMemoryConfigProvider, InMemoryExtensionHost, InMemoryStore, type InteractionRecord, type InvocationCatalogEntry, type InvocationSource, type JsonObject, type JsonPrimitive, type JsonValue, type LiveInteractionEvent, type LoadExtensionsResult, type LoadInput, type LoadResult, type LoadedExtension, type Message, type MessageBase, type MessageCommitted, type MessageContent, type MessageDelta, type MessageId, type MessageRevised, type MessageRevisionResult, type Metadata, type ModelRetry, type OpaqueId, type Outcome, type OwnerLease, type OwnerToken, type Page, type Phase, type PhaseContext, type PhaseContribution, type PhaseExecution, type PhaseExecutionIdentity, type PhaseInput, type PhaseInvocation, type PhaseMessageManager, type PhaseOutput, type PhaseRegistry, type PhaseRegistrySelection, type PhaseState, type PhaseStatus, type PhaseStatusState, type ResolvedResourceView, type ResourceDiagnostic, type ResourceKind, type ResourceRef, ResourceRegistry, ResourceRegistryError, type ResourceRegistryErrorCode, type ResourceSourceId, type ResourceView, type RetentionResult, type RunBoundary, type RunClaim, type RunEndEvent, type RunEvent, type RunFailure, type RunId, type RunInteraction, RunInteractionBoundary, RunInteractionCancelledError, type RunInteractionDriver, type RunInteractionKind, type RunInteractionRequest, type RunInteractionState, type RunInteractionStatus, type RunListCursor, type RunRecord, type RunSnapshot, type RunStartEvent, type RunState, type RunStateChanged, type RunSummary, RuntimeBootstrapRegistry, RuntimeError, type RuntimeErrorCode, type RuntimeErrorDetails, RuntimeExtensionLifetime, STOP_PHASE_ID, type SettingsBadge, type SettingsControl, type SettingsDefinition, type SettingsItem, type SettingsOption, type SettingsSection, type Skill, SqliteStore, type TextContent, type ThinkingContent, type ThinkingDelta, type Tool$1 as Tool, type ToolCallContext, type ToolCallDelta, type ToolCallId, type ToolCallPresentationInput, type ToolCallPresentationOutput, type ToolCallSnapshot, type ToolCallState, type ToolContribution, type ToolDefinition, type ToolExecutionResult, type ToolInvocationContext, type ToolMessage, type ToolMessageContent, type ToolResultContent, type ToolStateChanged, type ToolUseContent, type UserContent, type UserInput, type UserMessage, type WithdrawnUserInput, brandConfigToken, createCompactPhase, createCorePhases, createCoreTools, createDefaultPhase, createStopPhase, isConfigurationSnapshot, isRuntimeError, loadExtensionsFromPath as loadExtensions, loadPhase, loadPhases, loadSkill, loadSkills, mergeToolCall, parseAgentDefinition, parseFrontmatter, resolveConfigurationSnapshot };
package/dist/index.js CHANGED
@@ -1922,6 +1922,19 @@ function createRunInteractionDriver(state, phase, signal) {
1922
1922
  checkpoint = void 0;
1923
1923
  sync();
1924
1924
  },
1925
+ answer(id, value) {
1926
+ answers.set(id, value);
1927
+ const req = requests.get(id);
1928
+ if (req) {
1929
+ requests.set(id, { ...req, status: "answered", answer: value });
1930
+ }
1931
+ sync();
1932
+ },
1933
+ clearAnswer(id) {
1934
+ answers.delete(id);
1935
+ requests.delete(id);
1936
+ sync();
1937
+ },
1925
1938
  suspend(input = {}) {
1926
1939
  assertActive();
1927
1940
  const pending = this.pending();
@@ -3607,7 +3620,8 @@ async function executeToolCall(input) {
3607
3620
  toolCall: input.toolCall,
3608
3621
  contentBlocks: input.contentBlocks,
3609
3622
  driver: input.driver,
3610
- options: input.options
3623
+ options: input.options,
3624
+ ...input.providerInitiated ? { providerInitiated: true } : {}
3611
3625
  });
3612
3626
  } else {
3613
3627
  const toolContext = {
@@ -3652,7 +3666,7 @@ async function executeToolCalls(input) {
3652
3666
  }
3653
3667
  function createPhaseExecution(config, state, phase, messageManager, toolExecutionManager, registry) {
3654
3668
  const interaction = createRunInteractionDriver(state, phase.name, config.signal);
3655
- const executePhaseTool = async (phaseContext, toolCall, options) => {
3669
+ const executePhaseTool = async (phaseContext, toolCall, options, providerInitiated = false) => {
3656
3670
  return runTurn(async () => {
3657
3671
  await toolExecutionManager.start(toolCall.id, toolCall.name, toolCall.args);
3658
3672
  const tools = phaseContext.tools.filter((tool) => tool.name !== PhaseRouteTool);
@@ -3668,7 +3682,8 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
3668
3682
  tools,
3669
3683
  toolCall,
3670
3684
  driver: interaction,
3671
- options
3685
+ options,
3686
+ providerInitiated
3672
3687
  });
3673
3688
  await toolExecutionManager.end(result.toolCallId, result.toolName, result, !result.ok);
3674
3689
  return result;
@@ -3751,7 +3766,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
3751
3766
  name,
3752
3767
  args
3753
3768
  };
3754
- const res = await executePhaseTool(phaseContext, toolCall, options2);
3769
+ const res = await executePhaseTool(phaseContext, toolCall, options2, true);
3755
3770
  return res.ok ? { ok: true, content: res.content } : { ok: false, error: res.error ?? "Tool execution failed", ...res.content !== void 0 ? { content: res.content } : {} };
3756
3771
  },
3757
3772
  report: (update) => {
@@ -5340,7 +5355,6 @@ var TransientRunEventSubscription = class {
5340
5355
  stop() {
5341
5356
  if (this.stopped) return;
5342
5357
  this.stopped = true;
5343
- this.queue.length = 0;
5344
5358
  this.notify();
5345
5359
  }
5346
5360
  notify() {
@@ -7217,6 +7231,8 @@ function createToolInteractionDriver(driver, input) {
7217
7231
  answers: () => driver.answers(),
7218
7232
  checkpoint: () => resumed ? resumed.toolCheckpoint : stored,
7219
7233
  clearCheckpoint: () => driver.clearCheckpoint(),
7234
+ answer: (id, val) => driver.answer?.(id, val),
7235
+ clearAnswer: (id) => driver.clearAnswer?.(id),
7220
7236
  suspend(options = {}) {
7221
7237
  const interactionIds = [.../* @__PURE__ */ new Set([
7222
7238
  ...requestedIds,
@@ -7357,14 +7373,26 @@ var AgentRuntime = class _AgentRuntime {
7357
7373
  throw error;
7358
7374
  }
7359
7375
  }
7360
- async handleRunEnd(runId, agentId, outcome) {
7376
+ publishLiveInteraction(runId, interaction) {
7377
+ this.transientEvents.publish({
7378
+ kind: "live_interaction",
7379
+ durability: "transient",
7380
+ runId,
7381
+ executionId: this.executions.get(runId)?.executionId,
7382
+ interaction
7383
+ });
7384
+ }
7385
+ cancelLiveInteractions(runId, reason) {
7361
7386
  const runLive = this.liveInteractions.get(runId);
7362
- if (runLive) {
7363
- for (const live of runLive.values()) {
7364
- live.reject(new RunInteractionCancelledError("Run ended."));
7365
- }
7366
- this.liveInteractions.delete(runId);
7387
+ if (!runLive) return;
7388
+ this.liveInteractions.delete(runId);
7389
+ for (const live of runLive.values()) {
7390
+ this.publishLiveInteraction(runId, { ...live.interaction, status: "cancelled" });
7391
+ live.reject(new RunInteractionCancelledError(reason));
7367
7392
  }
7393
+ }
7394
+ async handleRunEnd(runId, agentId, outcome) {
7395
+ this.cancelLiveInteractions(runId, "Run ended.");
7368
7396
  if (this.startedRuns.has(runId)) {
7369
7397
  this.startedRuns.delete(runId);
7370
7398
  try {
@@ -7631,11 +7659,13 @@ var AgentRuntime = class _AgentRuntime {
7631
7659
  runLive = /* @__PURE__ */ new Map();
7632
7660
  this.liveInteractions.set(runId, runLive);
7633
7661
  }
7662
+ this.publishLiveInteraction(runId, interaction);
7634
7663
  return new Promise((resolve9, reject) => {
7635
7664
  const onAbort = () => {
7636
7665
  runLive?.delete(interactionId);
7637
7666
  if (runLive && runLive.size === 0) this.liveInteractions.delete(runId);
7638
7667
  signal.removeEventListener("abort", onAbort);
7668
+ this.publishLiveInteraction(runId, { ...interaction, status: "cancelled" });
7639
7669
  reject(signal.reason ?? new Error("Run aborted"));
7640
7670
  };
7641
7671
  signal.addEventListener("abort", onAbort, { once: true });
@@ -7658,12 +7688,9 @@ var AgentRuntime = class _AgentRuntime {
7658
7688
  if (this.heartbeat) clearInterval(this.heartbeat);
7659
7689
  for (const execution of this.executions.values()) execution.controller.abort();
7660
7690
  this.executions.clear();
7661
- for (const runLive of this.liveInteractions.values()) {
7662
- for (const live of runLive.values()) {
7663
- live.reject(new RunInteractionCancelledError("Runtime closed."));
7664
- }
7691
+ for (const runId of [...this.liveInteractions.keys()]) {
7692
+ this.cancelLiveInteractions(runId, "Runtime closed.");
7665
7693
  }
7666
- this.liveInteractions.clear();
7667
7694
  this.transientEvents.close();
7668
7695
  for (const subscription of this.consumers.values()) subscription.controller.abort();
7669
7696
  await this.resources.closeExtensions();
@@ -7693,8 +7720,10 @@ var AgentRuntime = class _AgentRuntime {
7693
7720
  runLive.delete(input.interactionId);
7694
7721
  if (runLive.size === 0) this.liveInteractions.delete(runId);
7695
7722
  if (input.cancel) {
7723
+ this.publishLiveInteraction(runId, { ...live.interaction, status: "cancelled" });
7696
7724
  live.reject(new RunInteractionCancelledError("Run interaction cancelled."));
7697
7725
  } else if (input.input !== void 0) {
7726
+ this.publishLiveInteraction(runId, { ...live.interaction, status: "answered", answer: input.input });
7698
7727
  live.resolve(input.input);
7699
7728
  } else {
7700
7729
  live.reject(new TypeError("respondInteraction requires input or cancel: true"));
@@ -7710,13 +7739,7 @@ var AgentRuntime = class _AgentRuntime {
7710
7739
  }
7711
7740
  async cancel(runId, reason) {
7712
7741
  this.assertOpen();
7713
- const runLive = this.liveInteractions.get(runId);
7714
- if (runLive) {
7715
- for (const live of runLive.values()) {
7716
- live.reject(new RunInteractionCancelledError(reason ?? "Agent run stopped."));
7717
- }
7718
- this.liveInteractions.delete(runId);
7719
- }
7742
+ this.cancelLiveInteractions(runId, reason ?? "Agent run stopped.");
7720
7743
  const done = this.executionDone.get(runId);
7721
7744
  if (done) {
7722
7745
  this.cancellationRequested.add(runId);
@@ -7845,7 +7868,13 @@ var AgentRuntime = class _AgentRuntime {
7845
7868
  });
7846
7869
  executionRevision = claim.run.revision;
7847
7870
  const controller = new AbortController();
7848
- this.executions.set(run.id, { controller, executionId });
7871
+ this.executions.set(run.id, {
7872
+ controller,
7873
+ executionId,
7874
+ reservedToolCalls: /* @__PURE__ */ new Set(),
7875
+ startedToolCalls: /* @__PURE__ */ new Set(),
7876
+ providerToolCalls: /* @__PURE__ */ new Map()
7877
+ });
7849
7878
  if (this.cancellationRequested.has(run.id)) controller.abort();
7850
7879
  if (!this.startedRuns.has(run.id)) {
7851
7880
  this.startedRuns.add(run.id);
@@ -8077,25 +8106,130 @@ var AgentRuntime = class _AgentRuntime {
8077
8106
  onContext: assembly.setContext,
8078
8107
  runtime: {
8079
8108
  interact: (request) => this.liveInteract(run.id, request, controller.signal),
8080
- tools: ({ toolCall, contentBlocks, driver, options }) => {
8109
+ tools: ({ toolCall, contentBlocks, driver, options, providerInitiated }) => {
8081
8110
  const task = toolQueue.then(async () => {
8082
- const execution = await this.executeToolBatch({
8083
- run,
8084
- agentMetadata: agent.metadata,
8085
- execution: claim.execution,
8086
- expectedRevision: executionRevision,
8087
- toolConfig: executionTools,
8088
- toolCalls: [toolCall],
8089
- contentBlocks,
8090
- signal: controller.signal,
8091
- driver,
8092
- options,
8093
- onRevision: (rev) => {
8094
- executionRevision = rev;
8111
+ if (!providerInitiated) {
8112
+ const execution = await this.executeToolBatch({
8113
+ run,
8114
+ agentMetadata: agent.metadata,
8115
+ execution: claim.execution,
8116
+ expectedRevision: executionRevision,
8117
+ toolConfig: executionTools,
8118
+ toolCalls: [toolCall],
8119
+ contentBlocks,
8120
+ signal: controller.signal,
8121
+ driver,
8122
+ options,
8123
+ onRevision: (rev) => {
8124
+ executionRevision = rev;
8125
+ }
8126
+ });
8127
+ executionRevision = execution.revision;
8128
+ return execution.results[0];
8129
+ }
8130
+ const interactionIds = [];
8131
+ try {
8132
+ while (true) {
8133
+ try {
8134
+ const execution = await this.executeToolBatch({
8135
+ run,
8136
+ agentMetadata: agent.metadata,
8137
+ execution: claim.execution,
8138
+ expectedRevision: executionRevision,
8139
+ toolConfig: executionTools,
8140
+ toolCalls: [toolCall],
8141
+ contentBlocks,
8142
+ signal: controller.signal,
8143
+ driver,
8144
+ options,
8145
+ providerInitiated: true,
8146
+ interactionIds,
8147
+ onRevision: (rev) => {
8148
+ executionRevision = rev;
8149
+ }
8150
+ });
8151
+ executionRevision = execution.revision;
8152
+ return execution.results[0];
8153
+ } catch (error) {
8154
+ if (error instanceof RunInteractionBoundary) {
8155
+ try {
8156
+ for (const interaction of error.interactions) {
8157
+ interactionIds.push(interaction.id);
8158
+ const answer = await this.liveInteract(run.id, interaction, controller.signal);
8159
+ driver?.answer?.(interaction.id, answer);
8160
+ }
8161
+ driver?.clearCheckpoint();
8162
+ continue;
8163
+ } catch (waitError) {
8164
+ const active2 = this.executions.get(run.id);
8165
+ const toolCallId2 = active2?.providerToolCalls.get(toolCall.id) ?? error.interactions[0]?.toolCallId;
8166
+ const isCancel = waitError instanceof RunInteractionCancelledError;
8167
+ const reason = isCancel ? waitError.message : "Tool execution aborted.";
8168
+ if (toolCallId2) {
8169
+ const committed2 = await this.owned.commitToolResult({
8170
+ runId: run.id,
8171
+ execution: claim.execution,
8172
+ expectedRevision: executionRevision,
8173
+ toolCallId: toolCallId2,
8174
+ state: "failed",
8175
+ result: { ok: false, content: null, error: reason },
8176
+ title: toolCall.name,
8177
+ kind: "other"
8178
+ });
8179
+ executionRevision = committed2.run.revision;
8180
+ if (options?.onUpdate) {
8181
+ try {
8182
+ options.onUpdate(createMergedToolCall(
8183
+ toolCallId2,
8184
+ "failed",
8185
+ { rawInput: toJsonValue(toolCall.args) },
8186
+ toolCall.name,
8187
+ "other"
8188
+ ));
8189
+ } catch (err) {
8190
+ console.warn("Error in tool call onUpdate callback:", err);
8191
+ }
8192
+ }
8193
+ }
8194
+ if (!controller.signal.aborted && isCancel) {
8195
+ return {
8196
+ toolCallId: toolCall.id,
8197
+ toolName: toolCall.name,
8198
+ ok: false,
8199
+ content: null,
8200
+ error: reason
8201
+ };
8202
+ }
8203
+ throw waitError;
8204
+ }
8205
+ }
8206
+ const active = this.executions.get(run.id);
8207
+ const toolCallId = active?.providerToolCalls.get(toolCall.id);
8208
+ if (toolCallId && (active?.reservedToolCalls.has(toolCallId) || active?.startedToolCalls.has(toolCallId))) {
8209
+ try {
8210
+ const committed2 = await this.owned.commitToolResult({
8211
+ runId: run.id,
8212
+ execution: claim.execution,
8213
+ expectedRevision: executionRevision,
8214
+ toolCallId,
8215
+ state: "failed",
8216
+ result: { ok: false, content: null, error: error instanceof Error ? error.message : "Tool execution failed." },
8217
+ title: toolCall.name,
8218
+ kind: "other"
8219
+ });
8220
+ executionRevision = committed2.run.revision;
8221
+ } catch {
8222
+ }
8223
+ }
8224
+ throw error;
8225
+ }
8095
8226
  }
8096
- });
8097
- executionRevision = execution.revision;
8098
- return execution.results[0];
8227
+ } finally {
8228
+ driver?.clearCheckpoint();
8229
+ for (const id of interactionIds) driver?.clearAnswer?.(id);
8230
+ const active = this.executions.get(run.id);
8231
+ active?.providerToolCalls.delete(toolCall.id);
8232
+ }
8099
8233
  });
8100
8234
  toolQueue = task.then(() => void 0, () => void 0);
8101
8235
  return task;
@@ -8136,6 +8270,9 @@ var AgentRuntime = class _AgentRuntime {
8136
8270
  result = await executeModel(executionContext);
8137
8271
  }
8138
8272
  }
8273
+ if (result.type !== "input_required") {
8274
+ this.cancelLiveInteractions(run.id, result.type === "failed" ? result.error instanceof Error ? result.error.message : "Model execution failed." : "Run ended.");
8275
+ }
8139
8276
  await toolQueue;
8140
8277
  if (this.cancellationRequested.has(run.id) || controller.signal.aborted) {
8141
8278
  const output2 = latestAssistant(run, result.messages, executionContext.messages.length, true);
@@ -8209,6 +8346,7 @@ var AgentRuntime = class _AgentRuntime {
8209
8346
  } catch (error) {
8210
8347
  if (!claim && error instanceof RuntimeError && ["run_state_conflict", "runtime_ownership_lost", "run_not_found"].includes(error.code)) return;
8211
8348
  if (claim) {
8349
+ this.cancelLiveInteractions(run.id, error instanceof Error ? error.message : "Execution failed.");
8212
8350
  await toolQueue;
8213
8351
  if (this.cancellationRequested.has(run.id)) {
8214
8352
  const reason = this.cancellationReasons.get(run.id) ?? "Agent run stopped.";
@@ -8445,11 +8583,17 @@ var AgentRuntime = class _AgentRuntime {
8445
8583
  }
8446
8584
  const results = suspension ? [...suspension.completedResults] : [];
8447
8585
  const startIndex = suspension ? suspension.pendingIndex : 0;
8586
+ const active = this.executions.get(input.run.id);
8448
8587
  for (let index = startIndex; index < input.toolCalls.length; index += 1) {
8449
8588
  const toolCall = input.toolCalls[index];
8450
8589
  const durableTool = input.toolConfig.tools.find((candidate) => candidate.name === toolCall.name);
8451
8590
  const providerToolCallId = toolCall.id;
8452
- const toolCallId = suspension && index >= suspension.pendingIndex && suspension.toolCallIds?.[index] ? suspension.toolCallIds[index] : suspension && index === suspension.pendingIndex && suspension.toolCallId ? suspension.toolCallId : createId("tool");
8591
+ const toolCallId = input.providerInitiated && active?.providerToolCalls.has(providerToolCallId) ? active.providerToolCalls.get(providerToolCallId) : suspension && index >= suspension.pendingIndex && suspension.toolCallIds?.[index] ? suspension.toolCallIds[index] : suspension && index === suspension.pendingIndex && suspension.toolCallId ? suspension.toolCallId : createId("tool");
8592
+ if (input.providerInitiated && !active?.providerToolCalls.has(providerToolCallId)) {
8593
+ active?.providerToolCalls.set(providerToolCallId, toolCallId);
8594
+ }
8595
+ const isReserved = Boolean(active?.reservedToolCalls.has(toolCallId));
8596
+ const isStarted = Boolean(active?.startedToolCalls.has(toolCallId));
8453
8597
  const protocolFailure = (error) => ({
8454
8598
  toolCallId: providerToolCallId,
8455
8599
  toolName: toolCall.name,
@@ -8458,20 +8602,23 @@ var AgentRuntime = class _AgentRuntime {
8458
8602
  error
8459
8603
  });
8460
8604
  if (!durableTool) {
8461
- const reserved = await this.owned.reserveToolCalls({
8462
- runId: input.run.id,
8463
- execution: input.execution,
8464
- expectedRevision: revision,
8465
- requestMessageId: createId("msg"),
8466
- contentBlocks: input.contentBlocks,
8467
- calls: [{
8468
- toolCallId,
8469
- providerToolCallId,
8470
- name: toolCall.name,
8471
- args: toJsonValue(toolCall.args)
8472
- }]
8473
- });
8474
- setRevision(reserved.run.revision);
8605
+ if (!isReserved) {
8606
+ const reserved = await this.owned.reserveToolCalls({
8607
+ runId: input.run.id,
8608
+ execution: input.execution,
8609
+ expectedRevision: revision,
8610
+ requestMessageId: createId("msg"),
8611
+ contentBlocks: input.contentBlocks,
8612
+ calls: [{
8613
+ toolCallId,
8614
+ providerToolCallId,
8615
+ name: toolCall.name,
8616
+ args: toJsonValue(toolCall.args)
8617
+ }]
8618
+ });
8619
+ setRevision(reserved.run.revision);
8620
+ active?.reservedToolCalls.add(toolCallId);
8621
+ }
8475
8622
  const failed = await this.owned.commitToolResult({
8476
8623
  runId: input.run.id,
8477
8624
  execution: input.execution,
@@ -8537,7 +8684,7 @@ var AgentRuntime = class _AgentRuntime {
8537
8684
  reportProgress: () => {
8538
8685
  }
8539
8686
  };
8540
- const answer = suspension && index === suspension.pendingIndex ? suspension.interactionIds?.map((id) => input.driver?.answers().get(id)).find((value) => value !== void 0) : void 0;
8687
+ const answer = suspension && index === suspension.pendingIndex ? suspension.interactionIds?.map((id) => input.driver?.answers().get(id)).find((value) => value !== void 0) : input.providerInitiated && input.interactionIds ? input.interactionIds.map((id) => input.driver?.answers().get(id)).find((value) => value !== void 0) : void 0;
8541
8688
  try {
8542
8689
  if (input.toolConfig.beforeToolCall) {
8543
8690
  const decision = await input.toolConfig.beforeToolCall({
@@ -8552,7 +8699,7 @@ var AgentRuntime = class _AgentRuntime {
8552
8699
  throw new Error("Tool call requested interaction but no interaction driver is active.");
8553
8700
  }
8554
8701
  interactionDriver.request(decision.interaction);
8555
- if (!resumedStart) {
8702
+ if (!resumedStart && !isReserved) {
8556
8703
  const reserved = await this.owned.reserveToolCalls({
8557
8704
  runId: input.run.id,
8558
8705
  execution: input.execution,
@@ -8568,11 +8715,12 @@ var AgentRuntime = class _AgentRuntime {
8568
8715
  }]
8569
8716
  });
8570
8717
  setRevision(reserved.run.revision);
8718
+ active?.reservedToolCalls.add(toolCallId);
8571
8719
  }
8572
8720
  interactionDriver.suspend();
8573
8721
  }
8574
8722
  if ("allow" in decision && !decision.allow) {
8575
- if (!resumedStart) {
8723
+ if (!resumedStart && !isReserved) {
8576
8724
  const reserved = await this.owned.reserveToolCalls({
8577
8725
  runId: input.run.id,
8578
8726
  execution: input.execution,
@@ -8588,6 +8736,7 @@ var AgentRuntime = class _AgentRuntime {
8588
8736
  }]
8589
8737
  });
8590
8738
  setRevision(reserved.run.revision);
8739
+ active?.reservedToolCalls.add(toolCallId);
8591
8740
  }
8592
8741
  const failed = await this.owned.commitToolResult({
8593
8742
  runId: input.run.id,
@@ -8625,7 +8774,7 @@ var AgentRuntime = class _AgentRuntime {
8625
8774
  throw error;
8626
8775
  }
8627
8776
  const reason = error instanceof Error ? error.message : "Tool policy rejected the call.";
8628
- if (!resumedStart) {
8777
+ if (!resumedStart && !isReserved) {
8629
8778
  const reserved = await this.owned.reserveToolCalls({
8630
8779
  runId: input.run.id,
8631
8780
  execution: input.execution,
@@ -8641,6 +8790,7 @@ var AgentRuntime = class _AgentRuntime {
8641
8790
  }]
8642
8791
  });
8643
8792
  setRevision(reserved.run.revision);
8793
+ active?.reservedToolCalls.add(toolCallId);
8644
8794
  }
8645
8795
  const failed = await this.owned.commitToolResult({
8646
8796
  runId: input.run.id,
@@ -8672,22 +8822,25 @@ var AgentRuntime = class _AgentRuntime {
8672
8822
  results.push(protocolFailure(reason));
8673
8823
  continue;
8674
8824
  }
8675
- if (!resumedStart) {
8676
- const reserved = await this.owned.reserveToolCalls({
8677
- runId: input.run.id,
8678
- execution: input.execution,
8679
- expectedRevision: revision,
8680
- requestMessageId: createId("msg"),
8681
- contentBlocks: input.contentBlocks,
8682
- calls: [{
8683
- toolCallId,
8684
- providerToolCallId,
8685
- name: toolCall.name,
8686
- args: toJsonValue(toolCall.args),
8687
- ...pendingPres
8688
- }]
8689
- });
8690
- setRevision(reserved.run.revision);
8825
+ if (!resumedStart && !isStarted) {
8826
+ if (!isReserved) {
8827
+ const reserved = await this.owned.reserveToolCalls({
8828
+ runId: input.run.id,
8829
+ execution: input.execution,
8830
+ expectedRevision: revision,
8831
+ requestMessageId: createId("msg"),
8832
+ contentBlocks: input.contentBlocks,
8833
+ calls: [{
8834
+ toolCallId,
8835
+ providerToolCallId,
8836
+ name: toolCall.name,
8837
+ args: toJsonValue(toolCall.args),
8838
+ ...pendingPres
8839
+ }]
8840
+ });
8841
+ setRevision(reserved.run.revision);
8842
+ active?.reservedToolCalls.add(toolCallId);
8843
+ }
8691
8844
  const inProgressPres = await presentToolCall(durableTool, {
8692
8845
  status: "in_progress",
8693
8846
  args: toJsonValue(toolCall.args)
@@ -8705,6 +8858,7 @@ var AgentRuntime = class _AgentRuntime {
8705
8858
  ...currentToolState._meta !== void 0 ? { _meta: currentToolState._meta } : {}
8706
8859
  });
8707
8860
  setRevision(started.run.revision);
8861
+ active?.startedToolCalls.add(toolCallId);
8708
8862
  }
8709
8863
  const toolResult2 = await this.executeAndCommitTool({
8710
8864
  runId: input.run.id,
@@ -8729,7 +8883,8 @@ var AgentRuntime = class _AgentRuntime {
8729
8883
  signal: input.signal,
8730
8884
  afterToolCall: input.toolConfig.afterToolCall,
8731
8885
  currentToolState,
8732
- options: input.options
8886
+ options: input.options,
8887
+ providerInitiated: input.providerInitiated
8733
8888
  });
8734
8889
  results.push(toolResult2);
8735
8890
  }
@@ -8901,13 +9056,15 @@ var AgentRuntime = class _AgentRuntime {
8901
9056
  };
8902
9057
  } catch (error) {
8903
9058
  if (error instanceof RunInteractionBoundary) {
8904
- const suspended = await this.owned.suspendToolCall({
8905
- runId: input.runId,
8906
- execution: input.execution,
8907
- expectedRevision: input.revision,
8908
- toolCallId: input.toolCallId
8909
- });
8910
- input.setRevision(suspended.run.revision);
9059
+ if (!input.providerInitiated) {
9060
+ const suspended = await this.owned.suspendToolCall({
9061
+ runId: input.runId,
9062
+ execution: input.execution,
9063
+ expectedRevision: input.revision,
9064
+ toolCallId: input.toolCallId
9065
+ });
9066
+ input.setRevision(suspended.run.revision);
9067
+ }
8911
9068
  throw error;
8912
9069
  }
8913
9070
  if (error instanceof RunInteractionCancelledError) throw error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rowan-agent/agent",
3
- "version": "0.19.0",
3
+ "version": "0.19.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",