@agent-native/core 0.208.0 → 0.209.0-nightly-20261014070126

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 (74) hide show
  1. package/agent-native.eject.json +1 -0
  2. package/dist/agent/approval-key.d.ts +2 -0
  3. package/dist/agent/approval-key.js +12 -0
  4. package/dist/agent/context-xray/tokenize.js +12 -3
  5. package/dist/agent/engine/translate-anthropic.js +4 -0
  6. package/dist/agent/engine/types.d.ts +2 -0
  7. package/dist/agent/production-agent.d.ts +20 -5
  8. package/dist/agent/production-agent.js +227 -34
  9. package/dist/agent/run-manager.js +57 -11
  10. package/dist/agent/run-store.d.ts +10 -0
  11. package/dist/agent/run-store.js +49 -4
  12. package/dist/agent/thread-data-builder.d.ts +2 -0
  13. package/dist/agent/thread-data-builder.js +288 -14
  14. package/dist/agent/tool-approval-store.d.ts +3 -1
  15. package/dist/agent/tool-approval-store.js +26 -12
  16. package/dist/agent/tool-call-journal.d.ts +1 -1
  17. package/dist/agent/tool-call-journal.js +5 -3
  18. package/dist/agent/types.d.ts +7 -0
  19. package/dist/client/chat/agentkit-agent-native.js +18 -0
  20. package/dist/client/chat/agentkit-protocol.js +56 -5
  21. package/dist/client/chat/runtime.d.ts +10 -0
  22. package/dist/client/chat/runtime.js +257 -26
  23. package/dist/client/sse-event-processor.d.ts +22 -0
  24. package/dist/client/sse-event-processor.js +91 -11
  25. package/dist/collab/struct-routes.d.ts +1 -1
  26. package/dist/connections/catalog.d.ts +24 -1
  27. package/dist/connections/catalog.js +12 -0
  28. package/dist/data-programs/schema.d.ts +1 -0
  29. package/dist/data-programs/schema.js +3 -0
  30. package/dist/data-programs/store.js +2 -1
  31. package/dist/deploy/build.js +16 -14
  32. package/dist/eject/workspace-connections.js +1 -0
  33. package/dist/extensions/fetch-tool.js +114 -23
  34. package/dist/extensions/schema.d.ts +1 -0
  35. package/dist/extensions/schema.js +3 -0
  36. package/dist/extensions/store.js +2 -1
  37. package/dist/extensions/web-content.d.ts +5 -1
  38. package/dist/extensions/web-content.js +24 -6
  39. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  40. package/dist/notifications/routes.d.ts +1 -1
  41. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  42. package/dist/provider-api/actions/provider-api.d.ts +9 -9
  43. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  44. package/dist/provider-api/index.d.ts +2 -0
  45. package/dist/provider-api/index.js +95 -12
  46. package/dist/resources/handlers.d.ts +1 -1
  47. package/dist/server/agent-engine-default-model-route.d.ts +2 -2
  48. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  49. package/dist/server/auth.js +1 -0
  50. package/dist/server/core-routes-plugin.js +1 -0
  51. package/dist/server/index.d.ts +2 -1
  52. package/dist/server/index.js +2 -1
  53. package/dist/server/realtime-token.d.ts +1 -1
  54. package/dist/server/transcribe-voice.d.ts +1 -1
  55. package/dist/server/workspace-provider-oauth.d.ts +1 -1
  56. package/dist/server/workspace-provider-oauth.js +2 -0
  57. package/dist/shared/context-status.js +1 -1
  58. package/dist/shared/optional-peer-ssr.d.ts +2 -0
  59. package/dist/shared/optional-peer-ssr.js +123 -0
  60. package/dist/shared/tool-inputs.d.ts +2 -0
  61. package/dist/shared/tool-inputs.js +56 -0
  62. package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
  63. package/dist/tracking/index.d.ts +1 -0
  64. package/dist/tracking/index.js +1 -0
  65. package/dist/vite/client.js +46 -3
  66. package/dist/workspace-connections/store.d.ts +3 -1
  67. package/dist/workspace-connections/store.js +18 -8
  68. package/dist/workspace-files/constants.d.ts +3 -0
  69. package/dist/workspace-files/constants.js +3 -0
  70. package/dist/workspace-files/store.d.ts +2 -3
  71. package/dist/workspace-files/store.js +2 -3
  72. package/docs/content/automations.mdx +19 -13
  73. package/package.json +3 -3
  74. package/src/eject/workspace-connections.ts +1 -0
@@ -1,4 +1,5 @@
1
1
  import { AGENT_TOOL_CALL_HISTORY_MEDIA_TYPE, AGENT_TOOL_RESULT_HISTORY_MEDIA_TYPE, AGENTKIT_PROTOCOL_VERSION, AgentProtocolValidationError, approvalResponseFromResume, createCapabilityUnavailableError, createCapabilityUnsupportedError, inferAgentActivityKind, negotiateAgentKitProtocolVersion, resumeEntryFromApproval, resumeOptionId, } from "@agent-native/agentkit/protocol";
2
+ import { approvalKeyForHistory } from "../../agent/approval-key.js";
2
3
  import { AUTO_CONTINUE_OF_RUN_METADATA_KEY, AUTO_CONTINUE_PROMPT, AUTO_CONTINUE_REFUSAL_CODES, CONTINUE_OF_RUN_METADATA_KEY, CONTINUE_UNAVAILABLE_CODE, } from "../../agent/auto-continue.js";
3
4
  import { isPersistableAttachmentUrl } from "../../shared/attachments.js";
4
5
  import { parseBase64DataUrl } from "../../shared/data-url.js";
@@ -536,6 +537,16 @@ function runtimePartToProtocolPart(part, fallbackTextFormat) {
536
537
  name: part.toolName,
537
538
  input: part.input,
538
539
  inputText: part.inputText,
540
+ ...(part.approval?.approvalKey
541
+ ? {
542
+ approvalKey: part.approval.askId
543
+ ? approvalKeyForHistory(part.approval.approvalKey)
544
+ : part.approval.approvalKey,
545
+ }
546
+ : {}),
547
+ ...(part.approval?.askId
548
+ ? { approvalAskId: part.approval.askId }
549
+ : {}),
539
550
  },
540
551
  };
541
552
  case "tool-result":
@@ -548,6 +559,10 @@ function runtimePartToProtocolPart(part, fallbackTextFormat) {
548
559
  result: part.result,
549
560
  resultText: part.resultText,
550
561
  isError: part.isError,
562
+ ...(typeof part.approvalPause === "boolean"
563
+ ? { approvalPause: part.approvalPause }
564
+ : {}),
565
+ ...(part.approvalAskId ? { approvalAskId: part.approvalAskId } : {}),
551
566
  },
552
567
  };
553
568
  case "data":
@@ -606,6 +621,18 @@ function protocolPartToRuntimePart(part) {
606
621
  ...(typeof data.inputText === "string"
607
622
  ? { inputText: data.inputText }
608
623
  : {}),
624
+ ...(typeof data.approvalKey === "string" &&
625
+ data.approvalKey.length > 0
626
+ ? {
627
+ approval: {
628
+ approvalKey: data.approvalKey,
629
+ ...(typeof data.approvalAskId === "string" &&
630
+ data.approvalAskId.length > 0
631
+ ? { askId: data.approvalAskId }
632
+ : {}),
633
+ },
634
+ }
635
+ : {}),
609
636
  };
610
637
  }
611
638
  if (part.mediaType === AGENT_TOOL_RESULT_HISTORY_MEDIA_TYPE) {
@@ -621,6 +648,13 @@ function protocolPartToRuntimePart(part) {
621
648
  ? { resultText: data.resultText }
622
649
  : {}),
623
650
  ...(data.isError === true ? { isError: true } : {}),
651
+ ...(typeof data.approvalPause === "boolean"
652
+ ? { approvalPause: data.approvalPause }
653
+ : {}),
654
+ ...(typeof data.approvalAskId === "string" &&
655
+ data.approvalAskId.length > 0
656
+ ? { approvalAskId: data.approvalAskId }
657
+ : {}),
624
658
  };
625
659
  }
626
660
  return {
@@ -1756,7 +1790,10 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
1756
1790
  if (invocation)
1757
1791
  run.actions.set(event.toolCall.id, invocation);
1758
1792
  const messageId = runtimeToolMessageId(run, event.toolCall.metadata);
1759
- const toolCall = runtimeToolToProtocolTool(event.toolCall, "running", undefined, undefined, messageId);
1793
+ const toolCall = {
1794
+ ...runtimeToolToProtocolTool(event.toolCall, "running", undefined, undefined, messageId),
1795
+ runId: run.runId,
1796
+ };
1760
1797
  if (messageId) {
1761
1798
  run.pendingToolMessageAssociations.delete(toolCall.id);
1762
1799
  }
@@ -1815,10 +1852,23 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
1815
1852
  const invocation = run.actions.get(event.toolCallId);
1816
1853
  const previousTool = run.activeTools.get(event.toolCallId);
1817
1854
  const metadata = mergeProtocolMetadata(previousTool?.metadata, invocation?.metadata, event.metadata, base.metadata, {
1818
- ...(event.completedSideEffect ? { completedSideEffect: true } : {}),
1855
+ ...(event.completedSideEffect
1856
+ ? { completedSideEffect: true }
1857
+ : {}),
1819
1858
  ...(event.chatUI ? { chatUI: event.chatUI } : {}),
1820
1859
  ...(event.mcpApp ? { mcpApp: event.mcpApp } : {}),
1821
- });
1860
+ }) ?? {};
1861
+ if (event.approvalPause === true) {
1862
+ metadata.approvalPause = true;
1863
+ if (event.approvalAskId) {
1864
+ metadata.approvalAskId = event.approvalAskId;
1865
+ }
1866
+ }
1867
+ else {
1868
+ delete metadata.approvalPause;
1869
+ delete metadata.approvalAskId;
1870
+ }
1871
+ const protocolMetadata = Object.keys(metadata).length > 0 ? metadata : undefined;
1822
1872
  const actionResult = invocation
1823
1873
  ? actionResultFromTool({
1824
1874
  invocation,
@@ -1826,7 +1876,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
1826
1876
  result: event.result,
1827
1877
  resultText: event.resultText,
1828
1878
  error,
1829
- metadata,
1879
+ metadata: protocolMetadata,
1830
1880
  })
1831
1881
  : undefined;
1832
1882
  if (invocation)
@@ -1845,8 +1895,9 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
1845
1895
  status,
1846
1896
  output: event.result !== undefined ? event.result : event.resultText,
1847
1897
  error,
1898
+ runId: run.runId,
1848
1899
  ...(messageId ? { messageId } : {}),
1849
- ...(metadata ? { metadata } : {}),
1900
+ ...(protocolMetadata ? { metadata: protocolMetadata } : {}),
1850
1901
  };
1851
1902
  if (messageId) {
1852
1903
  run.pendingToolMessageAssociations.delete(event.toolCallId);
@@ -45,6 +45,12 @@ export interface AgentChatRuntimeToolCallPart extends AgentChatRuntimeContentPar
45
45
  readonly toolName: string;
46
46
  readonly input?: unknown;
47
47
  readonly inputText?: string;
48
+ readonly approval?: {
49
+ readonly approvalKey: string;
50
+ readonly askId?: string;
51
+ };
52
+ /** Keeps the exact approved invocation available within the continuation budget. */
53
+ readonly approvedReplay?: true;
48
54
  }
49
55
  export interface AgentChatRuntimeToolResultPart extends AgentChatRuntimeContentPartBase<"tool-result"> {
50
56
  readonly toolCallId: AgentChatRuntimeToolCallId;
@@ -52,6 +58,8 @@ export interface AgentChatRuntimeToolResultPart extends AgentChatRuntimeContentP
52
58
  readonly result?: unknown;
53
59
  readonly resultText?: string;
54
60
  readonly isError?: boolean;
61
+ readonly approvalPause?: boolean;
62
+ readonly approvalAskId?: string;
55
63
  readonly mcpApp?: AgentMcpAppPayload;
56
64
  readonly chatUI?: ActionChatUIConfig;
57
65
  }
@@ -310,6 +318,8 @@ export interface AgentChatRuntimeToolDoneEvent extends AgentChatRuntimeEventBase
310
318
  readonly resultText?: string;
311
319
  readonly error?: string;
312
320
  readonly completedSideEffect?: boolean;
321
+ readonly approvalPause?: boolean;
322
+ readonly approvalAskId?: string;
313
323
  readonly mcpApp?: AgentMcpAppPayload;
314
324
  readonly chatUI?: ActionChatUIConfig;
315
325
  }
@@ -4,7 +4,7 @@ import { agentEngineStatusUrlForChatApi, requireAgentEngineConfiguredForDispatch
4
4
  import { getOrCreateAnalyticsSessionId } from "../analytics-session.js";
5
5
  import { agentChatStreamingUrl, agentNativePath } from "../api-path.js";
6
6
  import { CHAT_REQUEST_TOO_LARGE_MESSAGE } from "../error-format.js";
7
- import { appendMissingFinalResponseWarning, } from "../sse-event-processor.js";
7
+ import { appendMissingFinalResponseWarning, findApprovalToolCallIndex, } from "../sse-event-processor.js";
8
8
  import { runOutcomeForCode } from "./run-outcome.js";
9
9
  export const AGENT_NATIVE_RUN_RESUME_STATE_METADATA_KEY = "agentNativeRunResumeState";
10
10
  const AGENTKIT_TOOL_HISTORY_OMISSION_MESSAGE_ID_PREFIX = "agentkit-tool-history-omission";
@@ -946,6 +946,42 @@ function structuredToolHistoryCandidateByteCost(candidate) {
946
946
  return (candidate.assistantParts.reduce((bytes, part) => bytes + structuredHistoryPartByteCost("assistant", part), 0) +
947
947
  candidate.resultParts.reduce((bytes, part) => bytes + structuredHistoryPartByteCost("user", part), 0));
948
948
  }
949
+ function approvedToolHistoryParts(history, askId) {
950
+ let call;
951
+ let result;
952
+ for (const message of history) {
953
+ for (const part of message.content) {
954
+ if (message.role === "assistant" &&
955
+ part.type === "tool-call" &&
956
+ part.approvalAskId === askId) {
957
+ call = part;
958
+ }
959
+ else if (message.role === "user" &&
960
+ part.type === "tool-result" &&
961
+ part.approvalPause === true &&
962
+ part.approvalAskId === askId) {
963
+ result = part;
964
+ }
965
+ }
966
+ }
967
+ return { call, result };
968
+ }
969
+ function approvedToolHistoryError(code, status) {
970
+ return Object.assign(new Error(status === 413 ? CHAT_REQUEST_TOO_LARGE_MESSAGE : "The agent run failed."), { code, status, retryable: false });
971
+ }
972
+ function assertApprovedToolHistory(history, askIds, status) {
973
+ for (const askId of askIds) {
974
+ const { call, result } = approvedToolHistoryParts(history, askId);
975
+ if (!call || !result) {
976
+ if (status === 413)
977
+ throw approvedToolHistoryError("http_413", 413);
978
+ throw approvedToolHistoryError("approved_tool_call_history_missing", 422);
979
+ }
980
+ if (!Object.prototype.hasOwnProperty.call(call, "input")) {
981
+ throw approvedToolHistoryError("http_413", 413);
982
+ }
983
+ }
984
+ }
949
985
  function structuredTextHistoryCandidateByteCost(candidate) {
950
986
  return candidate.parts.reduce((bytes, part) => bytes + structuredHistoryPartByteCost(candidate.role, part), 0);
951
987
  }
@@ -1187,8 +1223,8 @@ function boundedJsonStringify(value, maxBytes) {
1187
1223
  return { status: "unserializable" };
1188
1224
  }
1189
1225
  }
1190
- function toolInputForStructuredHistory(input) {
1191
- const serialization = boundedJsonStringify(input, MAX_TOOL_HISTORY_VALUE_BYTES);
1226
+ function toolInputForStructuredHistory(input, maxBytes = MAX_TOOL_HISTORY_VALUE_BYTES) {
1227
+ const serialization = boundedJsonStringify(input, maxBytes);
1192
1228
  if (serialization.status === "too-large") {
1193
1229
  return { omissionText: TOOL_INPUT_SIZE_OMISSION_TEXT };
1194
1230
  }
@@ -1737,16 +1773,55 @@ function boundaryToolResultPartsToOmit(messages, supplementalMessages, sources,
1737
1773
  }
1738
1774
  return partsToOmit;
1739
1775
  }
1740
- function nativeStructuredHistoryFromMessages(messages, currentPrompt, currentAttachmentUrls, supplementalMessages = [], supplementalHistoryOmitted = false, supplementalToolHistoryOmitted = false) {
1776
+ function assertUnambiguousKeyOnlyApprovedHistory(sources, approvedToolCalls, approvedToolCallAskIds) {
1777
+ if (!approvedToolCalls.length || approvedToolCallAskIds.length > 0)
1778
+ return;
1779
+ const approvedKeys = new Set(approvedToolCalls);
1780
+ const callCountsByKey = new Map();
1781
+ for (const { message, parts, priority } of sources) {
1782
+ if (message.role !== "assistant")
1783
+ continue;
1784
+ for (const part of parts) {
1785
+ if (part.type !== "tool-call" ||
1786
+ !part.approval ||
1787
+ !approvedKeys.has(part.approval.approvalKey)) {
1788
+ continue;
1789
+ }
1790
+ let calls = callCountsByKey.get(part.approval.approvalKey);
1791
+ if (!calls) {
1792
+ calls = { history: new Map(), supplemental: new Set() };
1793
+ callCountsByKey.set(part.approval.approvalKey, calls);
1794
+ }
1795
+ if (priority) {
1796
+ calls.supplemental.add(part.toolCallId);
1797
+ }
1798
+ else {
1799
+ calls.history.set(part.toolCallId, (calls.history.get(part.toolCallId) ?? 0) + 1);
1800
+ }
1801
+ }
1802
+ }
1803
+ for (const calls of callCountsByKey.values()) {
1804
+ const historyCallCount = [...calls.history.values()].reduce((count, occurrences) => count + occurrences, 0);
1805
+ const supplementalCallCount = [...calls.supplemental].filter((toolCallId) => !calls.history.has(toolCallId)).length;
1806
+ if (historyCallCount + supplementalCallCount > 1) {
1807
+ throw approvedToolHistoryError("approved_tool_call_history_ambiguous", 422);
1808
+ }
1809
+ }
1810
+ }
1811
+ function nativeStructuredHistoryFromMessages(messages, currentPrompt, currentAttachmentUrls, supplementalMessages = [], supplementalHistoryOmitted = false, supplementalToolHistoryOmitted = false, approvedToolCalls = [], approvedToolCallAskIds = []) {
1741
1812
  const structuredHistory = [];
1813
+ const approvedToolCallSet = new Set(approvedToolCalls);
1814
+ const approvedToolCallAskIdSet = new Set(approvedToolCallAskIds);
1742
1815
  const callCandidates = [];
1743
1816
  const resultReferences = [];
1817
+ const approvalAskIdByToolCallId = new Map();
1744
1818
  const toolHistoryParts = new Set();
1745
1819
  const textHistoryParts = new Set();
1746
1820
  const textCandidates = [];
1747
1821
  let toolHistoryPosition = 0;
1748
1822
  let hasToolHistory = false;
1749
1823
  const sources = boundedStructuredHistorySources(messages, currentPrompt, supplementalMessages, currentAttachmentUrls);
1824
+ assertUnambiguousKeyOnlyApprovedHistory(sources.messages, approvedToolCalls, approvedToolCallAskIds);
1750
1825
  const boundaryResultsToOmit = boundaryToolResultPartsToOmit(messages, supplementalMessages, sources, supplementalToolHistoryOmitted);
1751
1826
  for (const { message, parts, priority, textPriority } of sources.messages) {
1752
1827
  if (message.role !== "user" && message.role !== "assistant")
@@ -1822,9 +1897,20 @@ function nativeStructuredHistoryFromMessages(messages, currentPrompt, currentAtt
1822
1897
  addToolInputText(part.inputText);
1823
1898
  }
1824
1899
  }
1900
+ const approvedReplay = part.approvedReplay === true ||
1901
+ (part.approval !== undefined &&
1902
+ approvedToolCallSet.has(part.approval.approvalKey) &&
1903
+ (approvedToolCallAskIdSet.size === 0 ||
1904
+ (part.approval.askId !== undefined &&
1905
+ approvedToolCallAskIdSet.has(part.approval.askId))));
1906
+ if (approvedReplay && part.input === undefined) {
1907
+ throw approvedToolHistoryError("approved_tool_call_input_unavailable", 422);
1908
+ }
1825
1909
  const input = part.input === undefined
1826
1910
  ? undefined
1827
- : toolInputForStructuredHistory(part.input);
1911
+ : toolInputForStructuredHistory(part.input, approvedReplay
1912
+ ? MAX_ADDED_TOOL_HISTORY_BYTES
1913
+ : MAX_TOOL_HISTORY_VALUE_BYTES);
1828
1914
  if (input && "omissionText" in input) {
1829
1915
  addToolInputText(input.omissionText);
1830
1916
  }
@@ -1833,7 +1919,20 @@ function nativeStructuredHistoryFromMessages(messages, currentPrompt, currentAtt
1833
1919
  id: part.toolCallId,
1834
1920
  name: part.toolName,
1835
1921
  ...(input && "input" in input ? { input: input.input } : {}),
1922
+ ...(part.approval?.askId
1923
+ ? { approvalAskId: part.approval.askId }
1924
+ : {}),
1925
+ // The ask ID selects this call server-side; its key repeats large inputs.
1926
+ ...(part.approval?.approvalKey && !part.approval.askId
1927
+ ? { approvalKey: part.approval.approvalKey }
1928
+ : {}),
1836
1929
  };
1930
+ if (part.approval?.askId) {
1931
+ approvalAskIdByToolCallId.set(part.toolCallId, part.approval.askId);
1932
+ }
1933
+ else {
1934
+ approvalAskIdByToolCallId.delete(part.toolCallId);
1935
+ }
1837
1936
  content.push(callPart);
1838
1937
  candidateAssistantParts.push(callPart);
1839
1938
  toolHistoryParts.add(callPart);
@@ -1867,6 +1966,14 @@ function nativeStructuredHistoryFromMessages(messages, currentPrompt, currentAtt
1867
1966
  ...(part.toolName ? { toolName: part.toolName } : {}),
1868
1967
  content: toolResultForStructuredHistory(part.result, part.resultText),
1869
1968
  ...(part.isError ? { isError: true } : {}),
1969
+ ...(part.approvalPause === true ? { approvalPause: true } : {}),
1970
+ ...((part.approvalAskId ??
1971
+ approvalAskIdByToolCallId.get(part.toolCallId))
1972
+ ? {
1973
+ approvalAskId: part.approvalAskId ??
1974
+ approvalAskIdByToolCallId.get(part.toolCallId),
1975
+ }
1976
+ : {}),
1870
1977
  };
1871
1978
  results.push(resultPart);
1872
1979
  toolHistoryParts.add(resultPart);
@@ -1888,15 +1995,34 @@ function nativeStructuredHistoryFromMessages(messages, currentPrompt, currentAtt
1888
1995
  !sources.hasAttachmentHistory &&
1889
1996
  !supplementalHistoryOmitted &&
1890
1997
  !supplementalToolHistoryOmitted) {
1998
+ assertApprovedToolHistory([], approvedToolCallAskIds, 422);
1891
1999
  return undefined;
1892
2000
  }
1893
- return boundStructuredToolHistory(structuredHistory, callCandidates, resultReferences, textCandidates, toolHistoryParts, textHistoryParts, sources.omitted ||
2001
+ assertApprovedToolHistory(structuredHistory, approvedToolCallAskIds, 422);
2002
+ const boundedHistory = boundStructuredToolHistory(structuredHistory, callCandidates, resultReferences, textCandidates, toolHistoryParts, textHistoryParts, sources.omitted ||
1894
2003
  supplementalHistoryOmitted ||
1895
2004
  supplementalToolHistoryOmitted);
1896
- }
1897
- function pendingApprovalRuntimeMessages(state) {
2005
+ assertApprovedToolHistory(boundedHistory, approvedToolCallAskIds, 413);
2006
+ return boundedHistory;
2007
+ }
2008
+ function isPendingApprovedToolCall(part, approvedToolCallSet, approvedToolCallAskIdSet) {
2009
+ return (part.approval !== undefined &&
2010
+ approvedToolCallSet.has(part.approval.approvalKey) &&
2011
+ (approvedToolCallAskIdSet.size === 0 ||
2012
+ (part.approval.askId !== undefined &&
2013
+ approvedToolCallAskIdSet.has(part.approval.askId))) &&
2014
+ (part.result === undefined || part.approvalPause === true));
2015
+ }
2016
+ function pendingApprovalRuntimeMessages(state, approvedToolCalls, approvedToolCallAskIds) {
1898
2017
  const messagesReversed = [];
2018
+ const approvedToolCallSet = new Set(approvedToolCalls);
2019
+ const approvedToolCallAskIdSet = new Set(approvedToolCallAskIds);
2020
+ const approvedCallCount = state.message.content.filter((part) => part.type === "tool-call" &&
2021
+ isPendingApprovedToolCall(part, approvedToolCallSet, approvedToolCallAskIdSet)).length;
2022
+ const reservedApprovalCallCount = Math.min(approvedCallCount, MAX_TOOL_HISTORY_CALLS);
2023
+ const unapprovedToolPartLimit = MAX_STRUCTURED_HISTORY_TOOL_SOURCE_PARTS - reservedApprovalCallCount * 2;
1899
2024
  let selectedToolPartCount = 0;
2025
+ let selectedApprovalCallCount = 0;
1900
2026
  let selectedTextPartCount = 0;
1901
2027
  let scannedPartCount = 0;
1902
2028
  let omitted = false;
@@ -1921,22 +2047,45 @@ function pendingApprovalRuntimeMessages(state) {
1921
2047
  });
1922
2048
  continue;
1923
2049
  }
1924
- if (part.type !== "tool-call" || part.result === undefined)
2050
+ if (part.type !== "tool-call")
1925
2051
  continue;
1926
- if (selectedToolPartCount + 2 > MAX_STRUCTURED_HISTORY_TOOL_SOURCE_PARTS) {
1927
- omitted = true;
1928
- toolHistoryOmitted = true;
2052
+ const awaitingApproval = part.toolCallId === state.message.pendingApprovalToolCallId;
2053
+ const isApprovedPendingCall = isPendingApprovedToolCall(part, approvedToolCallSet, approvedToolCallAskIdSet);
2054
+ if (part.result === undefined &&
2055
+ !isApprovedPendingCall &&
2056
+ !awaitingApproval) {
1929
2057
  continue;
1930
2058
  }
1931
- selectedToolPartCount += 2;
2059
+ if (isApprovedPendingCall) {
2060
+ if (selectedApprovalCallCount >= MAX_TOOL_HISTORY_CALLS) {
2061
+ omitted = true;
2062
+ toolHistoryOmitted = true;
2063
+ continue;
2064
+ }
2065
+ selectedApprovalCallCount++;
2066
+ }
2067
+ else {
2068
+ if (selectedToolPartCount + 2 > unapprovedToolPartLimit) {
2069
+ omitted = true;
2070
+ toolHistoryOmitted = true;
2071
+ continue;
2072
+ }
2073
+ selectedToolPartCount += 2;
2074
+ }
1932
2075
  messagesReversed.push({
1933
2076
  role: "user",
1934
2077
  content: [
1935
2078
  {
1936
2079
  type: "tool-result",
1937
2080
  toolCallId: part.toolCallId,
1938
- result: part.result,
2081
+ ...(part.approval?.askId
2082
+ ? { approvalAskId: part.approval.askId }
2083
+ : {}),
2084
+ result: awaitingApproval || (isApprovedPendingCall && !part.result?.trim())
2085
+ ? "Awaiting human approval. This action did NOT execute."
2086
+ : part.result,
1939
2087
  ...(part.isError ? { isError: true } : {}),
2088
+ ...(isApprovedPendingCall ? { approvalPause: true } : {}),
1940
2089
  },
1941
2090
  ],
1942
2091
  });
@@ -1948,6 +2097,8 @@ function pendingApprovalRuntimeMessages(state) {
1948
2097
  toolCallId: part.toolCallId,
1949
2098
  toolName: part.toolName,
1950
2099
  input: part.args,
2100
+ approval: part.approval,
2101
+ ...(isApprovedPendingCall ? { approvedReplay: true } : {}),
1951
2102
  },
1952
2103
  ],
1953
2104
  });
@@ -2195,10 +2346,17 @@ function mapAgentNativeEvent(raw, input) {
2195
2346
  ? part.toolCallId === ev.id
2196
2347
  : part.result === undefined && part.toolName === toolName));
2197
2348
  if (toolCall?.type === "tool-call") {
2349
+ if (toolCall.result !== undefined && toolCall.approvalPause === true) {
2350
+ toolCall.approvalResumeCandidate = true;
2351
+ }
2352
+ else {
2353
+ delete toolCall.approvalResumeCandidate;
2354
+ }
2198
2355
  toolCall.args = ev.input ?? {};
2199
2356
  toolCall.argsText = JSON.stringify(toolCall.args);
2200
2357
  if (structuredMeta)
2201
2358
  toolCall.structuredMeta = structuredMeta;
2359
+ delete toolCall.approvalPauseCandidate;
2202
2360
  }
2203
2361
  else {
2204
2362
  input.message.content.push({
@@ -2242,7 +2400,19 @@ function mapAgentNativeEvent(raw, input) {
2242
2400
  (storedToolCall?.type === "tool-call" ? storedToolCall.toolCallId : "");
2243
2401
  const structuredMeta = agentNativeStructuredMeta(ev);
2244
2402
  if (storedToolCall?.type === "tool-call") {
2245
- storedToolCall.result = agentNativeToolResultText(ev.result);
2403
+ const resultText = agentNativeToolResultText(ev.result);
2404
+ storedToolCall.result = resultText;
2405
+ const legacyApprovalPause = ev.approvalPause === undefined &&
2406
+ storedToolCall.approvalPauseCandidate === true;
2407
+ if (ev.approvalPause === true || legacyApprovalPause) {
2408
+ storedToolCall.approvalPause = true;
2409
+ }
2410
+ else {
2411
+ delete storedToolCall.approvalPause;
2412
+ delete storedToolCall.approval;
2413
+ }
2414
+ delete storedToolCall.approvalPauseCandidate;
2415
+ delete storedToolCall.approvalResumeCandidate;
2246
2416
  storedToolCall.isError = ev.isError === true || Boolean(ev.error);
2247
2417
  storedToolCall.completedSideEffect = ev.completedSideEffect === true;
2248
2418
  if (ev.mcpApp)
@@ -2252,6 +2422,14 @@ function mapAgentNativeEvent(raw, input) {
2252
2422
  if (structuredMeta)
2253
2423
  storedToolCall.structuredMeta = structuredMeta;
2254
2424
  }
2425
+ // The approval gate emits a placeholder tool_done before execution.
2426
+ if (input.message.pendingApprovalToolCallId === toolCallId &&
2427
+ !input.message.approvalPending &&
2428
+ storedToolCall?.type === "tool-call" &&
2429
+ storedToolCall.result !== undefined &&
2430
+ storedToolCall.approvalPause !== true) {
2431
+ input.message.pendingApprovalToolCallId = undefined;
2432
+ }
2255
2433
  const metadata = definedMetadata({ ...base.metadata, ...structuredMeta });
2256
2434
  const events = [
2257
2435
  {
@@ -2265,6 +2443,8 @@ function mapAgentNativeEvent(raw, input) {
2265
2443
  resultText: ev.result,
2266
2444
  error: ev.error,
2267
2445
  completedSideEffect: ev.completedSideEffect === true,
2446
+ approvalPause: storedToolCall?.approvalPause === true,
2447
+ approvalAskId: storedToolCall?.approval?.askId,
2268
2448
  mcpApp: ev.mcpApp,
2269
2449
  chatUI: ev.chatUI,
2270
2450
  },
@@ -2323,15 +2503,33 @@ function mapAgentNativeEvent(raw, input) {
2323
2503
  }
2324
2504
  if (ev.type === "approval_required") {
2325
2505
  input.message.approvalPending = true;
2506
+ const approvalKey = ev.approvalKey;
2507
+ let approvalToolCallId = ev.toolCallId ?? ev.id;
2508
+ if (typeof approvalKey === "string" && approvalKey.length > 0) {
2509
+ const approvalToolCallIndex = findApprovalToolCallIndex(input.message.content, ev.tool ?? "unknown", approvalToolCallId, ev.input);
2510
+ const part = input.message.content[approvalToolCallIndex];
2511
+ if (part?.type === "tool-call") {
2512
+ approvalToolCallId ??= part.toolCallId;
2513
+ part.approval = {
2514
+ approvalKey,
2515
+ ...(ev.askId ? { askId: ev.askId } : {}),
2516
+ ...(ev.allowPersistentApproval === false
2517
+ ? { allowPersistentApproval: false }
2518
+ : {}),
2519
+ };
2520
+ part.approvalPauseCandidate = true;
2521
+ delete part.approvalResumeCandidate;
2522
+ }
2523
+ }
2524
+ input.message.pendingApprovalToolCallId = approvalToolCallId;
2326
2525
  return [
2327
2526
  {
2328
2527
  type: "approval-request",
2329
2528
  ...base,
2330
- approvalId: ev.approvalKey ?? ev.id ?? createRuntimeId("approval"),
2529
+ approvalId: ev.askId ?? ev.approvalKey ?? ev.id ?? createRuntimeId("approval"),
2331
2530
  // `approval_required` carries the model-side call id as `toolCallId`,
2332
- // not `id`. Without this the request falls back to matching by tool
2333
- // name, which picks the wrong call when two are pending at once.
2334
- toolCallId: ev.toolCallId ?? ev.id,
2531
+ // not `id`. When older frames omit both ids, use the unique input match.
2532
+ toolCallId: approvalToolCallId,
2335
2533
  toolName: ev.tool,
2336
2534
  message: ev.label ?? "Approve this tool call?",
2337
2535
  input: ev.input,
@@ -2747,6 +2945,7 @@ function mapAgentNativeEvent(raw, input) {
2747
2945
  return [];
2748
2946
  }
2749
2947
  const AGENT_NATIVE_APPROVED_TOOL_CALLS_METADATA_KEY = "agentNativeApprovedToolCalls";
2948
+ const AGENT_NATIVE_APPROVED_TOOL_CALL_ASK_IDS_METADATA_KEY = "agentNativeApprovedToolCallAskIds";
2750
2949
  const AGENT_NATIVE_CONTINUATION_TURN_ID_METADATA_KEY = "agentNativeContinuationTurnId";
2751
2950
  const AGENT_NATIVE_INTERNAL_CONTINUATION_METADATA_KEY = "agentNativeInternalContinuation";
2752
2951
  function metadataString(metadata, key) {
@@ -2929,6 +3128,7 @@ export function createAgentNativeChatRuntime(options = {}) {
2929
3128
  .join("\n") ??
2930
3129
  "";
2931
3130
  const approvedToolCalls = metadataStringList(turn.metadata, AGENT_NATIVE_APPROVED_TOOL_CALLS_METADATA_KEY);
3131
+ const approvedToolCallAskIds = metadataStringList(turn.metadata, AGENT_NATIVE_APPROVED_TOOL_CALL_ASK_IDS_METADATA_KEY);
2932
3132
  const continuationTurnId = metadataString(turn.metadata, AGENT_NATIVE_CONTINUATION_TURN_ID_METADATA_KEY);
2933
3133
  const autoContinueOfRunId = metadataString(turn.metadata, AUTO_CONTINUE_OF_RUN_METADATA_KEY);
2934
3134
  const continueOfRunId = metadataString(turn.metadata, CONTINUE_OF_RUN_METADATA_KEY);
@@ -2946,9 +3146,9 @@ export function createAgentNativeChatRuntime(options = {}) {
2946
3146
  const history = nativeHistoryFromMessages(messagesForHistory, prompt, currentAttachmentUrlSet);
2947
3147
  const loadedSkillSlugs = loadedSkillSlugsFromMessages(turn.messages);
2948
3148
  const pendingApprovalHistory = approvedToolCalls && continuationMessageState
2949
- ? pendingApprovalRuntimeMessages(continuationMessageState)
3149
+ ? pendingApprovalRuntimeMessages(continuationMessageState, approvedToolCalls, approvedToolCallAskIds ?? [])
2950
3150
  : { messages: [], omitted: false, toolHistoryOmitted: false };
2951
- const structuredHistory = nativeStructuredHistoryFromMessages(messagesForHistory, prompt, currentAttachmentUrlSet, pendingApprovalHistory.messages, pendingApprovalHistory.omitted, pendingApprovalHistory.toolHistoryOmitted);
3151
+ const structuredHistory = nativeStructuredHistoryFromMessages(messagesForHistory, prompt, currentAttachmentUrlSet, pendingApprovalHistory.messages, pendingApprovalHistory.omitted, pendingApprovalHistory.toolHistoryOmitted, approvedToolCalls, approvedToolCallAskIds);
2952
3152
  return {
2953
3153
  message: prompt,
2954
3154
  ...(latestUserMessage?.id
@@ -2976,6 +3176,7 @@ export function createAgentNativeChatRuntime(options = {}) {
2976
3176
  ? { skipPendingSelectionContext: true }
2977
3177
  : {}),
2978
3178
  ...(approvedToolCalls ? { approvedToolCalls } : {}),
3179
+ ...(approvedToolCallAskIds ? { approvedToolCallAskIds } : {}),
2979
3180
  ...(options.mode ? { mode: options.mode } : {}),
2980
3181
  ...((turn.model ?? options.model)
2981
3182
  ? { model: turn.model ?? options.model }
@@ -3000,6 +3201,7 @@ export function createAgentNativeChatRuntime(options = {}) {
3000
3201
  content: [],
3001
3202
  started: false,
3002
3203
  approvalPending: false,
3204
+ pendingApprovalToolCallId: undefined,
3003
3205
  connectionPending: false,
3004
3206
  },
3005
3207
  };
@@ -3019,7 +3221,10 @@ export function createAgentNativeChatRuntime(options = {}) {
3019
3221
  continueTurn: ({ session, continuation, previousTurn, startTurn }) => {
3020
3222
  // Only the continuation that names a stopped run continues it; an approval
3021
3223
  // or connection answered later is not another continuation of that run.
3022
- const { [AUTO_CONTINUE_OF_RUN_METADATA_KEY]: _autoContinueOf, [CONTINUE_OF_RUN_METADATA_KEY]: _continueOf, ...previousMetadata } = previousTurn?.metadata ?? {};
3224
+ const { [AUTO_CONTINUE_OF_RUN_METADATA_KEY]: _autoContinueOf, [CONTINUE_OF_RUN_METADATA_KEY]: _continueOf, [AGENT_NATIVE_APPROVED_TOOL_CALLS_METADATA_KEY]: _approvedToolCalls, [AGENT_NATIVE_APPROVED_TOOL_CALL_ASK_IDS_METADATA_KEY]: _approvedToolCallAskIds, ...previousMetadata } = previousTurn?.metadata ?? {};
3225
+ const continuationMetadata = { ...continuation.metadata };
3226
+ delete continuationMetadata[AGENT_NATIVE_APPROVED_TOOL_CALLS_METADATA_KEY];
3227
+ delete continuationMetadata[AGENT_NATIVE_APPROVED_TOOL_CALL_ASK_IDS_METADATA_KEY];
3023
3228
  const turnToContinue = continuation.attachments?.length
3024
3229
  ? { ...previousTurn, attachments: continuation.attachments }
3025
3230
  : previousTurn;
@@ -3044,7 +3249,7 @@ export function createAgentNativeChatRuntime(options = {}) {
3044
3249
  `The ${connection.id} connection is now available. Continue the requested work.`,
3045
3250
  metadata: {
3046
3251
  ...previousMetadata,
3047
- ...continuation.metadata,
3252
+ ...continuationMetadata,
3048
3253
  [AGENT_NATIVE_CONTINUATION_TURN_ID_METADATA_KEY]: continuation.turnId,
3049
3254
  [AGENT_NATIVE_INTERNAL_CONTINUATION_METADATA_KEY]: true,
3050
3255
  },
@@ -3063,7 +3268,7 @@ export function createAgentNativeChatRuntime(options = {}) {
3063
3268
  prompt: continuation.prompt,
3064
3269
  metadata: {
3065
3270
  ...previousMetadata,
3066
- ...continuation.metadata,
3271
+ ...continuationMetadata,
3067
3272
  [AGENT_NATIVE_CONTINUATION_TURN_ID_METADATA_KEY]: continuation.turnId,
3068
3273
  [AGENT_NATIVE_INTERNAL_CONTINUATION_METADATA_KEY]: true,
3069
3274
  },
@@ -3079,6 +3284,25 @@ export function createAgentNativeChatRuntime(options = {}) {
3079
3284
  });
3080
3285
  }
3081
3286
  const messageState = messageStates.get(messageStateKey);
3287
+ const approvalParts = [
3288
+ ...(turnToContinue?.messages ?? []).flatMap((message) => message.content),
3289
+ ...(messageState?.message.content ?? []),
3290
+ ].filter((part) => part.type === "tool-call" &&
3291
+ (part.approval?.askId === approval.id ||
3292
+ part.approval?.approvalKey === approval.id));
3293
+ if (approvalParts.length > 1) {
3294
+ throw approvedToolHistoryError("approved_tool_call_history_ambiguous", 422);
3295
+ }
3296
+ const approvalPart = approvalParts[0];
3297
+ const approvalKey = approvalPart?.type === "tool-call"
3298
+ ? approvalPart.approval?.approvalKey
3299
+ : undefined;
3300
+ const approvalAskId = approvalPart?.type === "tool-call"
3301
+ ? approvalPart.approval?.askId
3302
+ : undefined;
3303
+ if (!approvalKey) {
3304
+ throw approvedToolHistoryError("approved_tool_call_history_missing", 422);
3305
+ }
3082
3306
  if (messageState)
3083
3307
  messageState.message.approvalPending = false;
3084
3308
  return startTurn({
@@ -3087,8 +3311,15 @@ export function createAgentNativeChatRuntime(options = {}) {
3087
3311
  "Approved. Go ahead and run the requested action.",
3088
3312
  metadata: {
3089
3313
  ...previousMetadata,
3090
- ...continuation.metadata,
3091
- [AGENT_NATIVE_APPROVED_TOOL_CALLS_METADATA_KEY]: [approval.id],
3314
+ ...continuationMetadata,
3315
+ [AGENT_NATIVE_APPROVED_TOOL_CALLS_METADATA_KEY]: [approvalKey],
3316
+ ...(approvalAskId
3317
+ ? {
3318
+ [AGENT_NATIVE_APPROVED_TOOL_CALL_ASK_IDS_METADATA_KEY]: [
3319
+ approvalAskId,
3320
+ ],
3321
+ }
3322
+ : {}),
3092
3323
  [AGENT_NATIVE_CONTINUATION_TURN_ID_METADATA_KEY]: continuation.turnId,
3093
3324
  [AGENT_NATIVE_INTERNAL_CONTINUATION_METADATA_KEY]: true,
3094
3325
  },