@rowan-agent/agent 0.18.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +33 -36
  2. package/dist/index.js +281 -136
  3. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -208,25 +208,11 @@ type PhaseMessageManager = {
208
208
  discard(messageId: string): void;
209
209
  };
210
210
 
211
- type UiSlot = "settings" | "model-picker";
212
- type UiContribution = {
213
- slot: "settings";
214
- id: string;
215
- title: string;
216
- description?: string;
217
- settings: SettingsDefinition;
218
- } | {
219
- slot: "model-picker";
220
- id: string;
221
- provider: string;
222
- status?: {
223
- kind: "ready" | "needs-setup" | "error";
224
- message?: string;
225
- };
226
- actions?: {
227
- id: string;
228
- label: string;
229
- }[];
211
+ type HostContribution = {
212
+ readonly kind: string;
213
+ readonly id: string;
214
+ } & {
215
+ readonly [key: string]: JsonValue;
230
216
  };
231
217
  interface ExtensionStateStore {
232
218
  get(key: string): Promise<JsonValue | undefined>;
@@ -592,10 +578,10 @@ interface ExtensionAPI {
592
578
  /** Get the message set by setMessage */
593
579
  getMessage(): string | undefined;
594
580
  };
595
- /** Declarative UI contributions — settings or model picker decorations. */
596
- ui: {
597
- /** Contribute declarative UI to a host slot. Returns a disposer to remove the contribution. */
598
- contribute(contribution: UiContribution): () => void;
581
+ /** Declarative host contributions. */
582
+ host: {
583
+ /** Contribute a declarative declaration to the host. Returns a disposer to remove the contribution. */
584
+ contribute<T extends HostContribution>(contribution: T): () => void;
599
585
  };
600
586
  /** Extension manifest from package.json `rowan` field. */
601
587
  manifest?: ExtensionManifest;
@@ -700,7 +686,7 @@ declare class ExtensionRunner {
700
686
  private bound;
701
687
  private readonly errorListeners;
702
688
  private readonly capabilityListeners;
703
- private readonly uiContributionListeners;
689
+ private readonly hostContributionListeners;
704
690
  /** Current agent context — set by the agent before each phase */
705
691
  currentContext?: AgentContext;
706
692
  constructor(options?: ExtensionRunnerOptions);
@@ -766,13 +752,13 @@ declare class ExtensionRunner {
766
752
  * Returns an unsubscribe function.
767
753
  */
768
754
  onCapabilitiesChanged(listener: (capabilities: readonly ExtensionCapability[]) => void): () => void;
769
- /** Get all contributed UI elements across all extensions. */
770
- getUiContributions(): readonly UiContribution[];
755
+ /** Get all contributed host elements across all extensions. */
756
+ getHostContributions(): readonly HostContribution[];
771
757
  /**
772
- * Subscribe to UI contribution changes (contributions added, removed, or extensions disposed).
758
+ * Subscribe to host contribution changes (contributions added, removed, or extensions disposed).
773
759
  * Returns an unsubscribe function.
774
760
  */
775
- onUiContributionsChanged(listener: (contributions: readonly UiContribution[]) => void): () => void;
761
+ onHostContributionsChanged(listener: (contributions: readonly HostContribution[]) => void): () => void;
776
762
  triggerUiAction(event: {
777
763
  contributionId: string;
778
764
  actionId: string;
@@ -847,8 +833,8 @@ declare class ExtensionRunner {
847
833
  private unregisterTool;
848
834
  private contributeCapability;
849
835
  private notifyCapabilitiesChanged;
850
- private contributeUi;
851
- private notifyUiContributionsChanged;
836
+ private contributeToHost;
837
+ private notifyHostContributionsChanged;
852
838
  private registerPhase;
853
839
  private registerPhaseDefinition;
854
840
  private unregisterPhase;
@@ -1600,8 +1586,8 @@ interface AgentRuntime$1 {
1600
1586
  }): Promise<DurableConsumer>;
1601
1587
  listCapabilities(): readonly ExtensionCapability[];
1602
1588
  onCapabilitiesChanged(listener: (capabilities: readonly ExtensionCapability[]) => void): () => void;
1603
- listUiContributions(): readonly UiContribution[];
1604
- onUiContributionsChanged(listener: (contributions: readonly UiContribution[]) => void): () => void;
1589
+ listHostContributions(): readonly HostContribution[];
1590
+ onHostContributionsChanged(listener: (contributions: readonly HostContribution[]) => void): () => void;
1605
1591
  triggerUiAction(event: {
1606
1592
  contributionId: string;
1607
1593
  actionId: string;
@@ -1703,6 +1689,8 @@ type RunInteractionDriver = Readonly<{
1703
1689
  answers(): ReadonlyMap<string, JsonValue>;
1704
1690
  checkpoint(): JsonValue | undefined;
1705
1691
  clearCheckpoint(): void;
1692
+ answer?(id: string, value: JsonValue): void;
1693
+ clearAnswer?(id: string): void;
1706
1694
  suspend(input?: Readonly<{
1707
1695
  checkpoint?: JsonValue;
1708
1696
  }>): never;
@@ -2043,7 +2031,14 @@ type ModelRetry = Readonly<{
2043
2031
  delayMs: number;
2044
2032
  error: string;
2045
2033
  }>;
2046
- 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, {
2047
2042
  durability: "transient";
2048
2043
  }>;
2049
2044
 
@@ -2422,6 +2417,8 @@ declare class AgentRuntime implements AgentRuntime$1 {
2422
2417
  private readonly retryDelayMs?;
2423
2418
  private constructor();
2424
2419
  static init(options: AgentRuntimeOptions): Promise<AgentRuntime>;
2420
+ private publishLiveInteraction;
2421
+ private cancelLiveInteractions;
2425
2422
  private handleRunEnd;
2426
2423
  loadAgents(input: LoadInput<AgentDefinition>): Promise<LoadResult>;
2427
2424
  loadSkills(input: LoadInput<Skill>): Promise<LoadResult>;
@@ -2499,8 +2496,8 @@ declare class AgentRuntime implements AgentRuntime$1 {
2499
2496
  }): Promise<DurableConsumer>;
2500
2497
  listCapabilities(): readonly ExtensionCapability[];
2501
2498
  onCapabilitiesChanged(listener: (capabilities: readonly ExtensionCapability[]) => void): () => void;
2502
- listUiContributions(): readonly UiContribution[];
2503
- onUiContributionsChanged(listener: (contributions: readonly UiContribution[]) => void): () => void;
2499
+ listHostContributions(): readonly HostContribution[];
2500
+ onHostContributionsChanged(listener: (contributions: readonly HostContribution[]) => void): () => void;
2504
2501
  triggerUiAction(event: {
2505
2502
  contributionId: string;
2506
2503
  actionId: string;
@@ -3306,4 +3303,4 @@ declare function parseFrontmatter<T = Record<string, unknown>>(raw: string): Fro
3306
3303
 
3307
3304
  declare function createCoreTools(input?: CoreToolContext): Tool$1[];
3308
3305
 
3309
- 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, 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 UiContribution, type UiSlot, 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
@@ -1800,32 +1800,20 @@ function createExtensionAPI(hooks, options, runtime, eventBus) {
1800
1800
  getNextPhase: () => nextPhase,
1801
1801
  getMessage: () => outputMessage
1802
1802
  },
1803
- ui: {
1803
+ host: {
1804
1804
  contribute: (contribution) => {
1805
1805
  assertActive();
1806
- if (!contribution || typeof contribution !== "object") {
1807
- throw new TypeError("UI contribution must be an object.");
1806
+ if (!contribution || typeof contribution !== "object" || Array.isArray(contribution)) {
1807
+ throw new TypeError("Host contribution must be an object.");
1808
1808
  }
1809
- if (contribution.slot !== "settings" && contribution.slot !== "model-picker") {
1810
- throw new TypeError(`Unsupported UI contribution slot: "${contribution.slot}".`);
1809
+ if (typeof contribution.kind !== "string" || contribution.kind.trim() === "") {
1810
+ throw new TypeError("Host contribution requires a non-empty kind.");
1811
1811
  }
1812
1812
  if (typeof contribution.id !== "string" || contribution.id.trim() === "") {
1813
- throw new TypeError("UI contribution requires a non-empty id.");
1814
- }
1815
- if (contribution.slot === "settings") {
1816
- if (typeof contribution.title !== "string") {
1817
- throw new TypeError("Settings UI contribution requires a title.");
1818
- }
1819
- if (!contribution.settings || typeof contribution.settings !== "object") {
1820
- throw new TypeError("Settings UI contribution requires a settings definition.");
1821
- }
1813
+ throw new TypeError("Host contribution requires a non-empty id.");
1822
1814
  }
1823
- if (contribution.slot === "model-picker") {
1824
- if (typeof contribution.provider !== "string" || contribution.provider.trim() === "") {
1825
- throw new TypeError("Model-picker UI contribution requires a provider.");
1826
- }
1827
- }
1828
- const dispose = options?.contributeUi ? options.contributeUi(contribution) : () => {
1815
+ assertJsonValue(contribution, "Host contribution");
1816
+ const dispose = options?.contributeToHost ? options.contributeToHost(contribution) : () => {
1829
1817
  };
1830
1818
  trackCleanup?.(dispose);
1831
1819
  return dispose;
@@ -1934,6 +1922,19 @@ function createRunInteractionDriver(state, phase, signal) {
1934
1922
  checkpoint = void 0;
1935
1923
  sync();
1936
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
+ },
1937
1938
  suspend(input = {}) {
1938
1939
  assertActive();
1939
1940
  const pending = this.pending();
@@ -3619,7 +3620,8 @@ async function executeToolCall(input) {
3619
3620
  toolCall: input.toolCall,
3620
3621
  contentBlocks: input.contentBlocks,
3621
3622
  driver: input.driver,
3622
- options: input.options
3623
+ options: input.options,
3624
+ ...input.providerInitiated ? { providerInitiated: true } : {}
3623
3625
  });
3624
3626
  } else {
3625
3627
  const toolContext = {
@@ -3664,7 +3666,7 @@ async function executeToolCalls(input) {
3664
3666
  }
3665
3667
  function createPhaseExecution(config, state, phase, messageManager, toolExecutionManager, registry) {
3666
3668
  const interaction = createRunInteractionDriver(state, phase.name, config.signal);
3667
- const executePhaseTool = async (phaseContext, toolCall, options) => {
3669
+ const executePhaseTool = async (phaseContext, toolCall, options, providerInitiated = false) => {
3668
3670
  return runTurn(async () => {
3669
3671
  await toolExecutionManager.start(toolCall.id, toolCall.name, toolCall.args);
3670
3672
  const tools = phaseContext.tools.filter((tool) => tool.name !== PhaseRouteTool);
@@ -3680,7 +3682,8 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
3680
3682
  tools,
3681
3683
  toolCall,
3682
3684
  driver: interaction,
3683
- options
3685
+ options,
3686
+ providerInitiated
3684
3687
  });
3685
3688
  await toolExecutionManager.end(result.toolCallId, result.toolName, result, !result.ok);
3686
3689
  return result;
@@ -3763,7 +3766,7 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
3763
3766
  name,
3764
3767
  args
3765
3768
  };
3766
- const res = await executePhaseTool(phaseContext, toolCall, options2);
3769
+ const res = await executePhaseTool(phaseContext, toolCall, options2, true);
3767
3770
  return res.ok ? { ok: true, content: res.content } : { ok: false, error: res.error ?? "Tool execution failed", ...res.content !== void 0 ? { content: res.content } : {} };
3768
3771
  },
3769
3772
  report: (update) => {
@@ -5352,7 +5355,6 @@ var TransientRunEventSubscription = class {
5352
5355
  stop() {
5353
5356
  if (this.stopped) return;
5354
5357
  this.stopped = true;
5355
- this.queue.length = 0;
5356
5358
  this.notify();
5357
5359
  }
5358
5360
  notify() {
@@ -5770,8 +5772,8 @@ var ExtensionRunner = class {
5770
5772
  errorListeners = /* @__PURE__ */ new Set();
5771
5773
  // Capability change listeners
5772
5774
  capabilityListeners = /* @__PURE__ */ new Set();
5773
- // UI contribution change listeners
5774
- uiContributionListeners = /* @__PURE__ */ new Set();
5775
+ // Host contribution change listeners
5776
+ hostContributionListeners = /* @__PURE__ */ new Set();
5775
5777
  /** Current agent context — set by the agent before each phase */
5776
5778
  currentContext;
5777
5779
  constructor(options) {
@@ -5875,7 +5877,7 @@ var ExtensionRunner = class {
5875
5877
  tools: /* @__PURE__ */ new Map(),
5876
5878
  phases: /* @__PURE__ */ new Set(),
5877
5879
  capabilities: /* @__PURE__ */ new Map(),
5878
- uiContributions: /* @__PURE__ */ new Map(),
5880
+ hostContributions: /* @__PURE__ */ new Map(),
5879
5881
  cleanup: [],
5880
5882
  runtime: createExtensionRuntime()
5881
5883
  };
@@ -5888,8 +5890,8 @@ var ExtensionRunner = class {
5888
5890
  if (extension.capabilities.size > 0) {
5889
5891
  this.notifyCapabilitiesChanged();
5890
5892
  }
5891
- if (extension.uiContributions.size > 0) {
5892
- this.notifyUiContributionsChanged();
5893
+ if (extension.hostContributions.size > 0) {
5894
+ this.notifyHostContributionsChanged();
5893
5895
  }
5894
5896
  } catch (error) {
5895
5897
  await this.rollbackExtension(extension);
@@ -6019,23 +6021,23 @@ var ExtensionRunner = class {
6019
6021
  this.capabilityListeners.add(listener);
6020
6022
  return () => this.capabilityListeners.delete(listener);
6021
6023
  }
6022
- /** Get all contributed UI elements across all extensions. */
6023
- getUiContributions() {
6024
+ /** Get all contributed host elements across all extensions. */
6025
+ getHostContributions() {
6024
6026
  const result = [];
6025
6027
  for (const ext of this.extensions) {
6026
- for (const contrib of ext.uiContributions.values()) {
6028
+ for (const contrib of ext.hostContributions.values()) {
6027
6029
  result.push(contrib);
6028
6030
  }
6029
6031
  }
6030
6032
  return Object.freeze(result);
6031
6033
  }
6032
6034
  /**
6033
- * Subscribe to UI contribution changes (contributions added, removed, or extensions disposed).
6035
+ * Subscribe to host contribution changes (contributions added, removed, or extensions disposed).
6034
6036
  * Returns an unsubscribe function.
6035
6037
  */
6036
- onUiContributionsChanged(listener) {
6037
- this.uiContributionListeners.add(listener);
6038
- return () => this.uiContributionListeners.delete(listener);
6038
+ onHostContributionsChanged(listener) {
6039
+ this.hostContributionListeners.add(listener);
6040
+ return () => this.hostContributionListeners.delete(listener);
6039
6041
  }
6040
6042
  triggerUiAction(event) {
6041
6043
  this.events.emit("ui.action", event);
@@ -6254,7 +6256,7 @@ var ExtensionRunner = class {
6254
6256
  registerTool: (tool) => this.registerTool(extension, tool),
6255
6257
  unregisterTool: (toolName) => this.unregisterTool(extension, toolName),
6256
6258
  contributeCapability: (contribution) => this.contributeCapability(extension, contribution),
6257
- contributeUi: (contribution) => this.contributeUi(extension, contribution),
6259
+ contributeToHost: (contribution) => this.contributeToHost(extension, contribution),
6258
6260
  context: extContext,
6259
6261
  manifest,
6260
6262
  trackCleanup: (cleanup) => extension.cleanup.push(cleanup),
@@ -6364,38 +6366,38 @@ var ExtensionRunner = class {
6364
6366
  }
6365
6367
  }
6366
6368
  }
6367
- contributeUi(extension, contribution) {
6368
- const key = `${contribution.slot}:${contribution.id}`;
6369
+ contributeToHost(extension, contribution) {
6370
+ const key = `${contribution.kind}:${contribution.id}`;
6369
6371
  const entry = {
6370
6372
  ...contribution
6371
6373
  };
6372
- extension.uiContributions.set(key, entry);
6374
+ extension.hostContributions.set(key, entry);
6373
6375
  if (this.extensions.includes(extension)) {
6374
- this.notifyUiContributionsChanged();
6376
+ this.notifyHostContributionsChanged();
6375
6377
  }
6376
6378
  let disposed = false;
6377
6379
  const dispose = () => {
6378
6380
  if (disposed) return;
6379
6381
  disposed = true;
6380
- if (extension.uiContributions.get(key) === entry) {
6381
- extension.uiContributions.delete(key);
6382
+ if (extension.hostContributions.get(key) === entry) {
6383
+ extension.hostContributions.delete(key);
6382
6384
  if (this.extensions.includes(extension)) {
6383
- this.notifyUiContributionsChanged();
6385
+ this.notifyHostContributionsChanged();
6384
6386
  }
6385
6387
  }
6386
6388
  };
6387
6389
  extension.cleanup.push(dispose);
6388
6390
  return dispose;
6389
6391
  }
6390
- notifyUiContributionsChanged() {
6391
- const contributions = this.getUiContributions();
6392
- for (const listener of this.uiContributionListeners) {
6392
+ notifyHostContributionsChanged() {
6393
+ const contributions = this.getHostContributions();
6394
+ for (const listener of this.hostContributionListeners) {
6393
6395
  try {
6394
6396
  listener(contributions);
6395
6397
  } catch (error) {
6396
6398
  this.emitError({
6397
6399
  extensionPath: "<runtime>",
6398
- event: "ui_contributions_changed",
6400
+ event: "host_contributions_changed",
6399
6401
  error: error instanceof Error ? error.message : String(error),
6400
6402
  stack: error instanceof Error ? error.stack : void 0
6401
6403
  });
@@ -6490,8 +6492,8 @@ var ExtensionRunner = class {
6490
6492
  for (const name of extension.phases) this.phases.delete(name);
6491
6493
  const hadCapabilities = extension.capabilities.size > 0;
6492
6494
  extension.capabilities.clear();
6493
- const hadUiContributions = extension.uiContributions.size > 0;
6494
- extension.uiContributions.clear();
6495
+ const hadHostContributions = extension.hostContributions.size > 0;
6496
+ extension.hostContributions.clear();
6495
6497
  for (const cleanup of [...extension.cleanup].reverse()) {
6496
6498
  await Promise.resolve().then(() => cleanup()).catch(() => void 0);
6497
6499
  }
@@ -6502,8 +6504,8 @@ var ExtensionRunner = class {
6502
6504
  if (hadCapabilities) {
6503
6505
  this.notifyCapabilitiesChanged();
6504
6506
  }
6505
- if (hadUiContributions) {
6506
- this.notifyUiContributionsChanged();
6507
+ if (hadHostContributions) {
6508
+ this.notifyHostContributionsChanged();
6507
6509
  }
6508
6510
  }
6509
6511
  };
@@ -7229,6 +7231,8 @@ function createToolInteractionDriver(driver, input) {
7229
7231
  answers: () => driver.answers(),
7230
7232
  checkpoint: () => resumed ? resumed.toolCheckpoint : stored,
7231
7233
  clearCheckpoint: () => driver.clearCheckpoint(),
7234
+ answer: (id, val) => driver.answer?.(id, val),
7235
+ clearAnswer: (id) => driver.clearAnswer?.(id),
7232
7236
  suspend(options = {}) {
7233
7237
  const interactionIds = [.../* @__PURE__ */ new Set([
7234
7238
  ...requestedIds,
@@ -7369,14 +7373,26 @@ var AgentRuntime = class _AgentRuntime {
7369
7373
  throw error;
7370
7374
  }
7371
7375
  }
7372
- 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) {
7373
7386
  const runLive = this.liveInteractions.get(runId);
7374
- if (runLive) {
7375
- for (const live of runLive.values()) {
7376
- live.reject(new RunInteractionCancelledError("Run ended."));
7377
- }
7378
- 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));
7379
7392
  }
7393
+ }
7394
+ async handleRunEnd(runId, agentId, outcome) {
7395
+ this.cancelLiveInteractions(runId, "Run ended.");
7380
7396
  if (this.startedRuns.has(runId)) {
7381
7397
  this.startedRuns.delete(runId);
7382
7398
  try {
@@ -7610,13 +7626,13 @@ var AgentRuntime = class _AgentRuntime {
7610
7626
  this.assertOpen();
7611
7627
  return this.resources.extensionRunner.onCapabilitiesChanged(listener);
7612
7628
  }
7613
- listUiContributions() {
7629
+ listHostContributions() {
7614
7630
  this.assertOpen();
7615
- return this.resources.extensionRunner.getUiContributions();
7631
+ return this.resources.extensionRunner.getHostContributions();
7616
7632
  }
7617
- onUiContributionsChanged(listener) {
7633
+ onHostContributionsChanged(listener) {
7618
7634
  this.assertOpen();
7619
- return this.resources.extensionRunner.onUiContributionsChanged(listener);
7635
+ return this.resources.extensionRunner.onHostContributionsChanged(listener);
7620
7636
  }
7621
7637
  triggerUiAction(event) {
7622
7638
  this.assertOpen();
@@ -7643,11 +7659,13 @@ var AgentRuntime = class _AgentRuntime {
7643
7659
  runLive = /* @__PURE__ */ new Map();
7644
7660
  this.liveInteractions.set(runId, runLive);
7645
7661
  }
7662
+ this.publishLiveInteraction(runId, interaction);
7646
7663
  return new Promise((resolve9, reject) => {
7647
7664
  const onAbort = () => {
7648
7665
  runLive?.delete(interactionId);
7649
7666
  if (runLive && runLive.size === 0) this.liveInteractions.delete(runId);
7650
7667
  signal.removeEventListener("abort", onAbort);
7668
+ this.publishLiveInteraction(runId, { ...interaction, status: "cancelled" });
7651
7669
  reject(signal.reason ?? new Error("Run aborted"));
7652
7670
  };
7653
7671
  signal.addEventListener("abort", onAbort, { once: true });
@@ -7670,12 +7688,9 @@ var AgentRuntime = class _AgentRuntime {
7670
7688
  if (this.heartbeat) clearInterval(this.heartbeat);
7671
7689
  for (const execution of this.executions.values()) execution.controller.abort();
7672
7690
  this.executions.clear();
7673
- for (const runLive of this.liveInteractions.values()) {
7674
- for (const live of runLive.values()) {
7675
- live.reject(new RunInteractionCancelledError("Runtime closed."));
7676
- }
7691
+ for (const runId of [...this.liveInteractions.keys()]) {
7692
+ this.cancelLiveInteractions(runId, "Runtime closed.");
7677
7693
  }
7678
- this.liveInteractions.clear();
7679
7694
  this.transientEvents.close();
7680
7695
  for (const subscription of this.consumers.values()) subscription.controller.abort();
7681
7696
  await this.resources.closeExtensions();
@@ -7705,8 +7720,10 @@ var AgentRuntime = class _AgentRuntime {
7705
7720
  runLive.delete(input.interactionId);
7706
7721
  if (runLive.size === 0) this.liveInteractions.delete(runId);
7707
7722
  if (input.cancel) {
7723
+ this.publishLiveInteraction(runId, { ...live.interaction, status: "cancelled" });
7708
7724
  live.reject(new RunInteractionCancelledError("Run interaction cancelled."));
7709
7725
  } else if (input.input !== void 0) {
7726
+ this.publishLiveInteraction(runId, { ...live.interaction, status: "answered", answer: input.input });
7710
7727
  live.resolve(input.input);
7711
7728
  } else {
7712
7729
  live.reject(new TypeError("respondInteraction requires input or cancel: true"));
@@ -7722,13 +7739,7 @@ var AgentRuntime = class _AgentRuntime {
7722
7739
  }
7723
7740
  async cancel(runId, reason) {
7724
7741
  this.assertOpen();
7725
- const runLive = this.liveInteractions.get(runId);
7726
- if (runLive) {
7727
- for (const live of runLive.values()) {
7728
- live.reject(new RunInteractionCancelledError(reason ?? "Agent run stopped."));
7729
- }
7730
- this.liveInteractions.delete(runId);
7731
- }
7742
+ this.cancelLiveInteractions(runId, reason ?? "Agent run stopped.");
7732
7743
  const done = this.executionDone.get(runId);
7733
7744
  if (done) {
7734
7745
  this.cancellationRequested.add(runId);
@@ -7857,7 +7868,13 @@ var AgentRuntime = class _AgentRuntime {
7857
7868
  });
7858
7869
  executionRevision = claim.run.revision;
7859
7870
  const controller = new AbortController();
7860
- 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
+ });
7861
7878
  if (this.cancellationRequested.has(run.id)) controller.abort();
7862
7879
  if (!this.startedRuns.has(run.id)) {
7863
7880
  this.startedRuns.add(run.id);
@@ -8089,25 +8106,130 @@ var AgentRuntime = class _AgentRuntime {
8089
8106
  onContext: assembly.setContext,
8090
8107
  runtime: {
8091
8108
  interact: (request) => this.liveInteract(run.id, request, controller.signal),
8092
- tools: ({ toolCall, contentBlocks, driver, options }) => {
8109
+ tools: ({ toolCall, contentBlocks, driver, options, providerInitiated }) => {
8093
8110
  const task = toolQueue.then(async () => {
8094
- const execution = await this.executeToolBatch({
8095
- run,
8096
- agentMetadata: agent.metadata,
8097
- execution: claim.execution,
8098
- expectedRevision: executionRevision,
8099
- toolConfig: executionTools,
8100
- toolCalls: [toolCall],
8101
- contentBlocks,
8102
- signal: controller.signal,
8103
- driver,
8104
- options,
8105
- onRevision: (rev) => {
8106
- 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
+ }
8107
8226
  }
8108
- });
8109
- executionRevision = execution.revision;
8110
- 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
+ }
8111
8233
  });
8112
8234
  toolQueue = task.then(() => void 0, () => void 0);
8113
8235
  return task;
@@ -8148,6 +8270,9 @@ var AgentRuntime = class _AgentRuntime {
8148
8270
  result = await executeModel(executionContext);
8149
8271
  }
8150
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
+ }
8151
8276
  await toolQueue;
8152
8277
  if (this.cancellationRequested.has(run.id) || controller.signal.aborted) {
8153
8278
  const output2 = latestAssistant(run, result.messages, executionContext.messages.length, true);
@@ -8221,6 +8346,7 @@ var AgentRuntime = class _AgentRuntime {
8221
8346
  } catch (error) {
8222
8347
  if (!claim && error instanceof RuntimeError && ["run_state_conflict", "runtime_ownership_lost", "run_not_found"].includes(error.code)) return;
8223
8348
  if (claim) {
8349
+ this.cancelLiveInteractions(run.id, error instanceof Error ? error.message : "Execution failed.");
8224
8350
  await toolQueue;
8225
8351
  if (this.cancellationRequested.has(run.id)) {
8226
8352
  const reason = this.cancellationReasons.get(run.id) ?? "Agent run stopped.";
@@ -8457,11 +8583,17 @@ var AgentRuntime = class _AgentRuntime {
8457
8583
  }
8458
8584
  const results = suspension ? [...suspension.completedResults] : [];
8459
8585
  const startIndex = suspension ? suspension.pendingIndex : 0;
8586
+ const active = this.executions.get(input.run.id);
8460
8587
  for (let index = startIndex; index < input.toolCalls.length; index += 1) {
8461
8588
  const toolCall = input.toolCalls[index];
8462
8589
  const durableTool = input.toolConfig.tools.find((candidate) => candidate.name === toolCall.name);
8463
8590
  const providerToolCallId = toolCall.id;
8464
- 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));
8465
8597
  const protocolFailure = (error) => ({
8466
8598
  toolCallId: providerToolCallId,
8467
8599
  toolName: toolCall.name,
@@ -8470,20 +8602,23 @@ var AgentRuntime = class _AgentRuntime {
8470
8602
  error
8471
8603
  });
8472
8604
  if (!durableTool) {
8473
- const reserved = await this.owned.reserveToolCalls({
8474
- runId: input.run.id,
8475
- execution: input.execution,
8476
- expectedRevision: revision,
8477
- requestMessageId: createId("msg"),
8478
- contentBlocks: input.contentBlocks,
8479
- calls: [{
8480
- toolCallId,
8481
- providerToolCallId,
8482
- name: toolCall.name,
8483
- args: toJsonValue(toolCall.args)
8484
- }]
8485
- });
8486
- 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
+ }
8487
8622
  const failed = await this.owned.commitToolResult({
8488
8623
  runId: input.run.id,
8489
8624
  execution: input.execution,
@@ -8549,7 +8684,7 @@ var AgentRuntime = class _AgentRuntime {
8549
8684
  reportProgress: () => {
8550
8685
  }
8551
8686
  };
8552
- 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;
8553
8688
  try {
8554
8689
  if (input.toolConfig.beforeToolCall) {
8555
8690
  const decision = await input.toolConfig.beforeToolCall({
@@ -8564,7 +8699,7 @@ var AgentRuntime = class _AgentRuntime {
8564
8699
  throw new Error("Tool call requested interaction but no interaction driver is active.");
8565
8700
  }
8566
8701
  interactionDriver.request(decision.interaction);
8567
- if (!resumedStart) {
8702
+ if (!resumedStart && !isReserved) {
8568
8703
  const reserved = await this.owned.reserveToolCalls({
8569
8704
  runId: input.run.id,
8570
8705
  execution: input.execution,
@@ -8580,11 +8715,12 @@ var AgentRuntime = class _AgentRuntime {
8580
8715
  }]
8581
8716
  });
8582
8717
  setRevision(reserved.run.revision);
8718
+ active?.reservedToolCalls.add(toolCallId);
8583
8719
  }
8584
8720
  interactionDriver.suspend();
8585
8721
  }
8586
8722
  if ("allow" in decision && !decision.allow) {
8587
- if (!resumedStart) {
8723
+ if (!resumedStart && !isReserved) {
8588
8724
  const reserved = await this.owned.reserveToolCalls({
8589
8725
  runId: input.run.id,
8590
8726
  execution: input.execution,
@@ -8600,6 +8736,7 @@ var AgentRuntime = class _AgentRuntime {
8600
8736
  }]
8601
8737
  });
8602
8738
  setRevision(reserved.run.revision);
8739
+ active?.reservedToolCalls.add(toolCallId);
8603
8740
  }
8604
8741
  const failed = await this.owned.commitToolResult({
8605
8742
  runId: input.run.id,
@@ -8637,7 +8774,7 @@ var AgentRuntime = class _AgentRuntime {
8637
8774
  throw error;
8638
8775
  }
8639
8776
  const reason = error instanceof Error ? error.message : "Tool policy rejected the call.";
8640
- if (!resumedStart) {
8777
+ if (!resumedStart && !isReserved) {
8641
8778
  const reserved = await this.owned.reserveToolCalls({
8642
8779
  runId: input.run.id,
8643
8780
  execution: input.execution,
@@ -8653,6 +8790,7 @@ var AgentRuntime = class _AgentRuntime {
8653
8790
  }]
8654
8791
  });
8655
8792
  setRevision(reserved.run.revision);
8793
+ active?.reservedToolCalls.add(toolCallId);
8656
8794
  }
8657
8795
  const failed = await this.owned.commitToolResult({
8658
8796
  runId: input.run.id,
@@ -8684,22 +8822,25 @@ var AgentRuntime = class _AgentRuntime {
8684
8822
  results.push(protocolFailure(reason));
8685
8823
  continue;
8686
8824
  }
8687
- if (!resumedStart) {
8688
- const reserved = await this.owned.reserveToolCalls({
8689
- runId: input.run.id,
8690
- execution: input.execution,
8691
- expectedRevision: revision,
8692
- requestMessageId: createId("msg"),
8693
- contentBlocks: input.contentBlocks,
8694
- calls: [{
8695
- toolCallId,
8696
- providerToolCallId,
8697
- name: toolCall.name,
8698
- args: toJsonValue(toolCall.args),
8699
- ...pendingPres
8700
- }]
8701
- });
8702
- 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
+ }
8703
8844
  const inProgressPres = await presentToolCall(durableTool, {
8704
8845
  status: "in_progress",
8705
8846
  args: toJsonValue(toolCall.args)
@@ -8717,6 +8858,7 @@ var AgentRuntime = class _AgentRuntime {
8717
8858
  ...currentToolState._meta !== void 0 ? { _meta: currentToolState._meta } : {}
8718
8859
  });
8719
8860
  setRevision(started.run.revision);
8861
+ active?.startedToolCalls.add(toolCallId);
8720
8862
  }
8721
8863
  const toolResult2 = await this.executeAndCommitTool({
8722
8864
  runId: input.run.id,
@@ -8741,7 +8883,8 @@ var AgentRuntime = class _AgentRuntime {
8741
8883
  signal: input.signal,
8742
8884
  afterToolCall: input.toolConfig.afterToolCall,
8743
8885
  currentToolState,
8744
- options: input.options
8886
+ options: input.options,
8887
+ providerInitiated: input.providerInitiated
8745
8888
  });
8746
8889
  results.push(toolResult2);
8747
8890
  }
@@ -8913,13 +9056,15 @@ var AgentRuntime = class _AgentRuntime {
8913
9056
  };
8914
9057
  } catch (error) {
8915
9058
  if (error instanceof RunInteractionBoundary) {
8916
- const suspended = await this.owned.suspendToolCall({
8917
- runId: input.runId,
8918
- execution: input.execution,
8919
- expectedRevision: input.revision,
8920
- toolCallId: input.toolCallId
8921
- });
8922
- 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
+ }
8923
9068
  throw error;
8924
9069
  }
8925
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.18.0",
3
+ "version": "0.19.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",