@assistant-ui/core 0.2.5 → 0.2.6

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 (91) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/react/index.d.ts +2 -1
  3. package/dist/react/index.js +2 -1
  4. package/dist/react/primitives/message/MessageGroupedParts.d.ts +25 -21
  5. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  6. package/dist/react/primitives/message/MessageGroupedParts.js +6 -7
  7. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  8. package/dist/react/primitives/message/MessageParts.d.ts +2 -1
  9. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  10. package/dist/react/primitives/message/MessageParts.js +9 -4
  11. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  12. package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
  13. package/dist/react/providers/TextMessagePartProvider.js +3 -0
  14. package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
  15. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +3 -1
  16. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  17. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +3 -1
  18. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  19. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  20. package/dist/react/runtimes/external-message-converter.js +7 -3
  21. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  22. package/dist/react/types/MessagePartComponentTypes.d.ts +8 -0
  23. package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
  24. package/dist/react/utils/groupParts.d.ts +40 -12
  25. package/dist/react/utils/groupParts.d.ts.map +1 -1
  26. package/dist/react/utils/groupParts.js +51 -9
  27. package/dist/react/utils/groupParts.js.map +1 -1
  28. package/dist/runtime/api/message-part-runtime.d.ts +8 -0
  29. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  30. package/dist/runtime/api/message-part-runtime.js +13 -0
  31. package/dist/runtime/api/message-part-runtime.js.map +1 -1
  32. package/dist/runtime/api/thread-runtime.d.ts +2 -1
  33. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  34. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -1
  35. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  36. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  37. package/dist/runtime/interfaces/thread-runtime-core.d.ts +7 -1
  38. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  39. package/dist/runtime/utils/thread-message-like.d.ts +10 -0
  40. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  41. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  42. package/dist/runtimes/external-store/external-store-adapter.d.ts +2 -1
  43. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  44. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +2 -1
  45. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  46. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +4 -0
  47. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  48. package/dist/runtimes/local/local-thread-runtime-core.d.ts +2 -1
  49. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  50. package/dist/runtimes/local/local-thread-runtime-core.js +3 -0
  51. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  52. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -0
  53. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  54. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
  55. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  56. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  57. package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
  58. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  59. package/dist/store/clients/thread-message-client.d.ts.map +1 -1
  60. package/dist/store/clients/thread-message-client.js +3 -0
  61. package/dist/store/clients/thread-message-client.js.map +1 -1
  62. package/dist/store/runtime-clients/message-part-runtime-client.js +1 -0
  63. package/dist/store/runtime-clients/message-part-runtime-client.js.map +1 -1
  64. package/dist/store/scopes/part.d.ts +7 -0
  65. package/dist/store/scopes/part.d.ts.map +1 -1
  66. package/dist/types/message.d.ts +6 -0
  67. package/dist/types/message.d.ts.map +1 -1
  68. package/dist/types/message.js.map +1 -1
  69. package/package.json +2 -2
  70. package/src/index.ts +1 -0
  71. package/src/react/index.ts +1 -0
  72. package/src/react/primitives/message/MessageGroupedParts.tsx +38 -31
  73. package/src/react/primitives/message/MessageParts.tsx +14 -1
  74. package/src/react/providers/TextMessagePartProvider.tsx +3 -0
  75. package/src/react/runtimes/external-message-converter.ts +25 -12
  76. package/src/react/types/MessagePartComponentTypes.ts +8 -0
  77. package/src/react/utils/groupParts.ts +67 -22
  78. package/src/runtime/api/message-part-runtime.ts +26 -0
  79. package/src/runtime/base/base-thread-runtime-core.ts +4 -0
  80. package/src/runtime/interfaces/thread-runtime-core.ts +7 -0
  81. package/src/runtime/utils/thread-message-like.ts +7 -0
  82. package/src/runtimes/external-store/external-store-adapter.ts +4 -0
  83. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +7 -0
  84. package/src/runtimes/local/local-thread-runtime-core.ts +5 -0
  85. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
  86. package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
  87. package/src/store/clients/thread-message-client.ts +3 -0
  88. package/src/store/runtime-clients/message-part-runtime-client.ts +2 -0
  89. package/src/store/scopes/part.ts +4 -0
  90. package/src/tests/groupParts.test.ts +118 -32
  91. package/src/types/message.ts +7 -0
@@ -4,7 +4,7 @@ import { ModelContext, ModelContextProvider } from "../../model-context/types.js
4
4
  import { ThreadMessageLike } from "../../runtime/utils/thread-message-like.js";
5
5
  import { ExportedMessageRepository } from "../../runtime/utils/message-repository.js";
6
6
  import { EditComposerRuntimeCore, ThreadComposerRuntimeCore } from "../../runtime/interfaces/composer-runtime-core.js";
7
- import { AddToolResultOptions, ResumeRunConfig, ResumeToolCallOptions, RuntimeCapabilities, SpeechState, StartRunConfig, SubmitFeedbackOptions, ThreadRuntimeEventCallback, ThreadRuntimeEventType, ThreadSuggestion, VoiceSessionState } from "../../runtime/interfaces/thread-runtime-core.js";
7
+ import { AddToolResultOptions, RespondToToolApprovalOptions, ResumeRunConfig, ResumeToolCallOptions, RuntimeCapabilities, SpeechState, StartRunConfig, SubmitFeedbackOptions, ThreadRuntimeEventCallback, ThreadRuntimeEventType, ThreadSuggestion, VoiceSessionState } from "../../runtime/interfaces/thread-runtime-core.js";
8
8
  import { ThreadListRuntimeCore } from "../../runtime/interfaces/thread-list-runtime-core.js";
9
9
  import { BaseSubscribable } from "../../subscribable/subscribable.js";
10
10
  import { RemoteThreadInitializeResponse, RemoteThreadListOptions } from "../../runtimes/remote-thread-list/types.js";
@@ -51,6 +51,7 @@ declare class RemoteThreadListThreadListRuntimeCore extends BaseSubscribable imp
51
51
  cancelRun: () => void;
52
52
  addToolResult: (options: AddToolResultOptions) => void;
53
53
  resumeToolCall: (options: ResumeToolCallOptions) => void;
54
+ respondToToolApproval: (options: RespondToToolApprovalOptions) => void;
54
55
  speak: (messageId: string) => void;
55
56
  stopSpeaking: () => void;
56
57
  connectVoice: () => void;
@@ -97,6 +98,7 @@ declare class RemoteThreadListThreadListRuntimeCore extends BaseSubscribable imp
97
98
  cancelRun: () => void;
98
99
  addToolResult: (options: AddToolResultOptions) => void;
99
100
  resumeToolCall: (options: ResumeToolCallOptions) => void;
101
+ respondToToolApproval: (options: RespondToToolApprovalOptions) => void;
100
102
  speak: (messageId: string) => void;
101
103
  stopSpeaking: () => void;
102
104
  connectVoice: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteThreadListThreadListRuntimeCore.d.ts","names":[],"sources":["../../../src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx"],"mappings":";;;;;;;;;;;;;;cAwBa,qCAAA,SACH,gBAAA,YACG,qBAAA;EAAA,QAEH,QAAA;EAAA,iBACS,YAAA;EAAA,QAET,mBAAA;EAAA,QACA,gBAAA;EAAA,QACA,eAAA;EAAA,QAEA,aAAA;EAAA,iBACS,MAAA;EAAA,IAWN,WAAA,CAAA,GAAW,QAAA,CAAA,MAAA,CAtBtB,iBAAA,EAsBsB,gBAAA;EAIf,qBAAA,CAAA,GAAqB,OAAA;EAuDrB,QAAA,CAAA,GAAY,OAAA;EAAA,iBAoDF,eAAA;cAGf,OAAA,EAAS,uBAAA,EACT,eAAA,EAAiB,oBAAA;EAAA,QAiBX,oBAAA;EAAA,QACA,WAAA;EAED,qBAAA,CAAsB,OAAA,EAAS,uBAAA;EA0B/B,eAAA,CAAA;EAUA,MAAA,CAAA,GAAM,OAAA;EAAA,IAWF,SAAA,CAAA;EAAA,IAIA,aAAA,CAAA;EAAA,IAIA,OAAA,CAAA;EAAA,IAIA,SAAA,CAAA;EAAA,IAIA,iBAAA,CAAA;EAAA,IAIA,WAAA,CAAA;EAAA,IAIA,YAAA,CAAA;EAIJ,wBAAA,CAAA,GAAwB,QAAA;;;eAvClB,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CN,oBAAA,CAAqB,kBAAA,WAA0B,QAAA;;;eANvB,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAexB,WAAA,CAAY,kBAAA,WAA0B,gBAAA;EAIhC,cAAA,CACX,kBAAA,UACA,OAAA;IAAY,SAAA;EAAA,IACX,OAAA;EA6EU,iBAAA,CAAA,GAAqB,OAAA;EAyC3B,UAAA,GAAoB,QAAA,aAAgB,OAAA,CAzCF,8BAAA;EA+FlC,aAAA,GAAuB,QAAA,aAAgB,OAAA;EAkCvC,MAAA,CAAO,kBAAA,UAA4B,QAAA,WAAmB,OAAA;EAAA,QA4B/C,sBAAA;EASD,OAAA,CAAQ,kBAAA,WAA0B,OAAA;EAmBxC,SAAA,CAAU,kBAAA,WAA6B,OAAA;EAqBjC,MAAA,CAAO,kBAAA,WAA0B,OAAA;EAoBjC,MAAA,CAAO,kBAAA,WAA6B,OAAA;EAAA,QAUzC,WAAA;EAED,0BAAA,EAA4B,EAAA;AAAA"}
1
+ {"version":3,"file":"RemoteThreadListThreadListRuntimeCore.d.ts","names":[],"sources":["../../../src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx"],"mappings":";;;;;;;;;;;;;;cAwBa,qCAAA,SACH,gBAAA,YACG,qBAAA;EAAA,QAEH,QAAA;EAAA,iBACS,YAAA;EAAA,QAET,mBAAA;EAAA,QACA,gBAAA;EAAA,QACA,eAAA;EAAA,QAEA,aAAA;EAAA,iBACS,MAAA;EAAA,IAWN,WAAA,CAAA,GAAW,QAAA,CAAA,MAAA,CAtBtB,iBAAA,EAsBsB,gBAAA;EAIf,qBAAA,CAAA,GAAqB,OAAA;EAuDrB,QAAA,CAAA,GAAY,OAAA;EAAA,iBAoDF,eAAA;cAGf,OAAA,EAAS,uBAAA,EACT,eAAA,EAAiB,oBAAA;EAAA,QAiBX,oBAAA;EAAA,QACA,WAAA;EAED,qBAAA,CAAsB,OAAA,EAAS,uBAAA;EA0B/B,eAAA,CAAA;EAUA,MAAA,CAAA,GAAM,OAAA;EAAA,IAWF,SAAA,CAAA;EAAA,IAIA,aAAA,CAAA;EAAA,IAIA,OAAA,CAAA;EAAA,IAIA,SAAA,CAAA;EAAA,IAIA,iBAAA,CAAA;EAAA,IAIA,WAAA,CAAA;EAAA,IAIA,YAAA,CAAA;EAIJ,wBAAA,CAAA,GAAwB,QAAA;;;eAvClB,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CN,oBAAA,CAAqB,kBAAA,WAA0B,QAAA;;;eANvB,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAexB,WAAA,CAAY,kBAAA,WAA0B,gBAAA;EAIhC,cAAA,CACX,kBAAA,UACA,OAAA;IAAY,SAAA;EAAA,IACX,OAAA;EA6EU,iBAAA,CAAA,GAAqB,OAAA;EAyC3B,UAAA,GAAoB,QAAA,aAAgB,OAAA,CAzCF,8BAAA;EA+FlC,aAAA,GAAuB,QAAA,aAAgB,OAAA;EAkCvC,MAAA,CAAO,kBAAA,UAA4B,QAAA,WAAmB,OAAA;EAAA,QA4B/C,sBAAA;EASD,OAAA,CAAQ,kBAAA,WAA0B,OAAA;EAmBxC,SAAA,CAAU,kBAAA,WAA6B,OAAA;EAqBjC,MAAA,CAAO,kBAAA,WAA0B,OAAA;EAoBjC,MAAA,CAAO,kBAAA,WAA6B,OAAA;EAAA,QAUzC,WAAA;EAED,0BAAA,EAA4B,EAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"external-message-converter.d.ts","names":[],"sources":["../../../src/react/runtimes/external-message-converter.ts"],"mappings":";;;;;;kBAwBiB,2BAAA;EAAA,KACH,OAAA,IACP,iBAAA;IAAA,SACU,aAAA;MAAA,SACE,YAAA;IAAA;EAAA;IAIX,IAAA;IACA,UAAA;IACA,QAAA;IACA,MAAA;IACA,QAAA;IACA,OAAA;IACA,QAAA,YAAoB,aAAA;EAAA;EAAA,KAGd,QAAA;IAAA,SACD,YAAA,GAAe,MAAA,SAAe,mBAAA;IAAA,SAC9B,KAAA,GAAQ,iBAAA;IAAA,SACR,aAAA,GAAgB,MAAA,SAAe,aAAA;EAAA;EAAA,KAG9B,QAAA,OACV,OAAA,EAAS,CAAA,EACT,QAAA,EAAU,QAAA,KACP,OAAA,GAAU,OAAA;AAAA;AAAA,cA4QJ,uBAAA,aAAqC,OAAA,EAChD,QAAA,EAAU,CAAA,IACV,QAAA,EAAU,2BAAA,CAA4B,QAAA,CAAS,CAAA,GAC/C,SAAA,WACA,QAAA,EAAU,2BAAA,CAA4B,QAAA,KAAQ,aAAA;AAAA,cA8CnC,2BAAA,aAAyC,OAAA;EAAS,QAAA;EAAA,QAAA;EAAA,SAAA;EAAA,YAAA;EAAA;AAAA;EAO7D,QAAA,EAAU,2BAAA,CAA4B,QAAA,CAAS,CAAA;EAC/C,QAAA,EAAU,CAAA;EACV,SAAA;EACA,YAAA;EACA,QAAA,GAAW,2BAAA,CAA4B,QAAA;AAAA,MACxC,aAAA"}
1
+ {"version":3,"file":"external-message-converter.d.ts","names":[],"sources":["../../../src/react/runtimes/external-message-converter.ts"],"mappings":";;;;;;kBAwCiB,2BAAA;EAAA,KACH,OAAA,IACP,iBAAA;IAAA,SACU,aAAA;MAAA,SACE,YAAA;IAAA;EAAA;IAIX,IAAA;IACA,UAAA;IACA,QAAA;IACA,MAAA;IACA,QAAA;IACA,OAAA;IACA,QAAA,YAAoB,aAAA;EAAA;EAAA,KAGd,QAAA;IAAA,SACD,YAAA,GAAe,MAAA,SAAe,mBAAA;IAAA,SAC9B,KAAA,GAAQ,iBAAA;IAAA,SACR,aAAA,GAAgB,MAAA,SAAe,aAAA;EAAA;EAAA,KAG9B,QAAA,OACV,OAAA,EAAS,CAAA,EACT,QAAA,EAAU,QAAA,KACP,OAAA,GAAU,OAAA;AAAA;AAAA,cA4QJ,uBAAA,aAAqC,OAAA,EAChD,QAAA,EAAU,CAAA,IACV,QAAA,EAAU,2BAAA,CAA4B,QAAA,CAAS,CAAA,GAC/C,SAAA,WACA,QAAA,EAAU,2BAAA,CAA4B,QAAA,KAAQ,aAAA;AAAA,cA+CnC,2BAAA,aAAyC,OAAA;EAAS,QAAA;EAAA,QAAA;EAAA,SAAA;EAAA,YAAA;EAAA;AAAA;EAO7D,QAAA,EAAU,2BAAA,CAA4B,QAAA,CAAS,CAAA;EAC/C,QAAA,EAAU,CAAA;EACV,SAAA;EACA,YAAA;EACA,QAAA,GAAW,2BAAA,CAA4B,QAAA;AAAA,MACxC,aAAA"}
@@ -6,6 +6,11 @@ import { fromThreadMessageLike } from "../../runtime/utils/thread-message-like.j
6
6
  import { ThreadMessageConverter } from "../../runtimes/external-store/thread-message-converter.js";
7
7
  import { useMemo } from "react";
8
8
  //#region src/react/runtimes/external-message-converter.ts
9
+ const isPendingToolCall = (c) => c.type === "tool-call" && c.result === void 0;
10
+ const isInterruptedToolCall = (c) => {
11
+ if (c.type !== "tool-call" || c.result !== void 0) return false;
12
+ return c.interrupt != null || c.approval != null && c.approval.approved === void 0;
13
+ };
9
14
  const mergeInnerMessages = (existing, incoming) => ({ [symbolInnerMessage]: [...existing[symbolInnerMessage] ?? [], ...incoming[symbolInnerMessage] ?? []] });
10
15
  const joinExternalMessages = (messages) => {
11
16
  const assistantMessage = {
@@ -158,8 +163,7 @@ const convertExternalMessages = (messages, callback, isRunning, metadata) => {
158
163
  const result = chunks.map((message, idx) => {
159
164
  const isLast = idx === chunks.length - 1;
160
165
  const joined = joinExternalMessages(message.outputs);
161
- const hasPendingToolCalls = typeof joined.content === "object" && joined.content.some((c) => c.type === "tool-call" && c.result === void 0);
162
- const autoStatus = getAutoStatus(isLast, isRunning, hasPendingToolCalls, hasPendingToolCalls, isLast ? metadata.error : void 0);
166
+ const autoStatus = getAutoStatus(isLast, isRunning, typeof joined.content === "object" && joined.content.some(isInterruptedToolCall), typeof joined.content === "object" && joined.content.some(isPendingToolCall), isLast ? metadata.error : void 0);
163
167
  const newMessage = fromThreadMessageLike(joined, idx.toString(), autoStatus);
164
168
  bindExternalStoreMessage(newMessage, message.inputs);
165
169
  return newMessage;
@@ -203,7 +207,7 @@ const useExternalMessageConverter = ({ callback, messages, isRunning, joinStrate
203
207
  const threadMessages = state.converterCache.convertMessages(chunks, (cache, message, idx) => {
204
208
  const isLast = idx === chunks.length - 1;
205
209
  const joined = joinExternalMessages(message.outputs);
206
- const autoStatus = getAutoStatus(isLast, isRunning, typeof joined.content === "object" && joined.content.some((c) => c.type === "tool-call" && c.result === void 0), typeof joined.content === "object" && joined.content.some((c) => c.type === "tool-call" && c.result === void 0), isLast ? state.metadata.error : void 0);
210
+ const autoStatus = getAutoStatus(isLast, isRunning, typeof joined.content === "object" && joined.content.some(isInterruptedToolCall), typeof joined.content === "object" && joined.content.some(isPendingToolCall), isLast ? state.metadata.error : void 0);
207
211
  if (cache && (cache.role !== "assistant" || !isAutoStatus(cache.status) || cache.status === autoStatus)) {
208
212
  if (shallowArrayEqual(getExternalStoreMessages(cache), message.inputs)) return cache;
209
213
  }
@@ -1 +1 @@
1
- {"version":3,"file":"external-message-converter.js","names":["unsupportedRole"],"sources":["../../../src/react/runtimes/external-message-converter.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { ThreadMessageConverter } from \"../../runtimes/external-store/thread-message-converter\";\nimport {\n getExternalStoreMessages,\n symbolInnerMessage,\n bindExternalStoreMessage,\n} from \"../../runtime/utils/external-store-message\";\nimport {\n fromThreadMessageLike,\n type ThreadMessageLike,\n} from \"../../runtime/utils/thread-message-like\";\nimport { getAutoStatus, isAutoStatus } from \"../../runtime/utils/auto-status\";\nimport type { ToolExecutionStatus } from \"./useToolInvocations\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { generateErrorMessageId } from \"../../utils/id\";\nimport type {\n ThreadAssistantMessage,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"../../types/message\";\nimport type { MessageTiming } from \"../../types/message\";\n\nexport namespace useExternalMessageConverter {\n export type Message =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: \"concat-content\" | \"none\";\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n messages?: readonly ThreadMessage[];\n };\n\n export type Metadata = {\n readonly toolStatuses?: Record<string, ToolExecutionStatus>;\n readonly error?: ReadonlyJSONValue;\n readonly messageTiming?: Record<string, MessageTiming>;\n };\n\n export type Callback<T> = (\n message: T,\n metadata: Metadata,\n ) => Message | Message[];\n}\n\ntype CallbackResult<T> = {\n input: T;\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype ChunkResult<T> = {\n inputs: T[];\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst mergeInnerMessages = (existing: object, incoming: object) => ({\n [symbolInnerMessage]: [\n ...((existing as any)[symbolInnerMessage] ?? []),\n ...((incoming as any)[symbolInnerMessage] ?? []),\n ],\n});\n\nconst joinExternalMessages = (\n messages: readonly useExternalMessageConverter.Message[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = assistantMessage.content.findIndex(\n (c) => c.type === \"tool-call\" && c.toolCallId === output.toolCallId,\n );\n // Ignore orphaned tool results so one bad tool message does not\n // prevent rendering the rest of the conversation.\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName !== undefined) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n messages: output.messages,\n };\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n\n if (output.metadata.timing) {\n assistantMessage.metadata.timing = output.metadata.timing;\n }\n\n if (output.metadata.submittedFeedback) {\n assistantMessage.metadata.submittedFeedback =\n output.metadata.submittedFeedback;\n }\n }\n // TODO keep this in sync\n }\n\n // Add content parts, merging reasoning parts with same parentId\n for (const part of content) {\n if (part.type === \"tool-call\") {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"tool-call\" && c.toolCallId === part.toolCallId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n ...part,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n\n if (\n part.type === \"reasoning\" &&\n \"parentId\" in part &&\n part.parentId\n ) {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"reasoning\" &&\n \"parentId\" in c &&\n c.parentId === part.parentId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n text: `${existing.text}\\n\\n${part.text}`,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n assistantMessage.content.push(part);\n }\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nconst chunkExternalMessages = <T>(\n callbackResults: CallbackResult<T>[],\n joinStrategy?: \"concat-content\" | \"none\",\n) => {\n const results: ChunkResult<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: useExternalMessageConverter.Message[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nfunction createErrorAssistantMessage(\n error: ReadonlyJSONValue,\n): ThreadAssistantMessage {\n const msg: ThreadAssistantMessage = {\n id: generateErrorMessageId(),\n role: \"assistant\",\n content: [],\n status: { type: \"incomplete\", reason: \"error\", error },\n createdAt: new Date(),\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n custom: {},\n steps: [],\n },\n };\n bindExternalStoreMessage(msg, []);\n return msg;\n}\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: useExternalMessageConverter.Callback<T>,\n isRunning: boolean,\n metadata: useExternalMessageConverter.Metadata,\n) => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n const output = callback(message, metadata);\n const outputs = Array.isArray(output) ? output : [output];\n const result = { input: message, outputs };\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults);\n\n const result = chunks.map((message, idx) => {\n const isLast = idx === chunks.length - 1;\n const joined = joinExternalMessages(message.outputs);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(\n (c) => c.type === \"tool-call\" && c.result === undefined,\n );\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasPendingToolCalls,\n hasPendingToolCalls,\n isLast ? metadata.error : undefined,\n );\n const newMessage = fromThreadMessageLike(\n joined,\n idx.toString(),\n autoStatus,\n );\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n });\n\n if (metadata.error) {\n const lastMessage = result.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n result.push(createErrorAssistantMessage(metadata.error));\n }\n }\n\n return result;\n};\n\nexport const useExternalMessageConverter = <T extends WeakKey>({\n callback,\n messages,\n isRunning,\n joinStrategy,\n metadata,\n}: {\n callback: useExternalMessageConverter.Callback<T>;\n messages: T[];\n isRunning: boolean;\n joinStrategy?: \"concat-content\" | \"none\" | undefined;\n metadata?: useExternalMessageConverter.Metadata | undefined;\n}) => {\n const state = useMemo(\n () => ({\n metadata: metadata ?? {},\n callback,\n callbackCache: new WeakMap<T, CallbackResult<T>>(),\n chunkCache: new WeakMap<\n useExternalMessageConverter.Message,\n ChunkResult<T>\n >(),\n converterCache: new ThreadMessageConverter(),\n }),\n [callback, metadata],\n );\n\n return useMemo(() => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n let result = state.callbackCache.get(message);\n if (!result) {\n const output = state.callback(message, state.metadata);\n const outputs = Array.isArray(output) ? output : [output];\n result = { input: message, outputs };\n state.callbackCache.set(message, result);\n }\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults, joinStrategy).map(\n (m) => {\n const key = m.outputs[0];\n if (!key) return m;\n\n const cached = state.chunkCache.get(key);\n if (cached && shallowArrayEqual(cached.outputs, m.outputs))\n return cached;\n state.chunkCache.set(key, m);\n return m;\n },\n );\n\n const threadMessages = state.converterCache.convertMessages(\n chunks,\n (cache, message, idx) => {\n const isLast = idx === chunks.length - 1;\n\n const joined = joinExternalMessages(message.outputs);\n const hasSuspendedToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(\n (c) => c.type === \"tool-call\" && c.result === undefined,\n );\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(\n (c) => c.type === \"tool-call\" && c.result === undefined,\n );\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasSuspendedToolCalls,\n hasPendingToolCalls,\n isLast ? state.metadata.error : undefined,\n );\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n ) {\n const inputs = getExternalStoreMessages<T>(cache);\n if (shallowArrayEqual(inputs, message.inputs)) {\n return cache;\n }\n }\n\n const newMessage = fromThreadMessageLike(\n joined,\n idx.toString(),\n autoStatus,\n );\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n },\n );\n\n bindExternalStoreMessage(threadMessages, messages);\n\n if (state.metadata.error) {\n const lastMessage = threadMessages.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n threadMessages.push(createErrorAssistantMessage(state.metadata.error));\n }\n }\n\n return threadMessages;\n }, [state, messages, isRunning, joinStrategy]);\n};\n\nconst shallowArrayEqual = (a: unknown[], b: unknown[]) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"external-message-converter.js","names":["unsupportedRole"],"sources":["../../../src/react/runtimes/external-message-converter.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { ThreadMessageConverter } from \"../../runtimes/external-store/thread-message-converter\";\nimport {\n getExternalStoreMessages,\n symbolInnerMessage,\n bindExternalStoreMessage,\n} from \"../../runtime/utils/external-store-message\";\nimport {\n fromThreadMessageLike,\n type ThreadMessageLike,\n} from \"../../runtime/utils/thread-message-like\";\nimport { getAutoStatus, isAutoStatus } from \"../../runtime/utils/auto-status\";\nimport type { ToolExecutionStatus } from \"./useToolInvocations\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { generateErrorMessageId } from \"../../utils/id\";\nimport type {\n ThreadAssistantMessage,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"../../types/message\";\nimport type { MessageTiming } from \"../../types/message\";\n\ntype ThreadMessageLikeContentItem = Exclude<\n ThreadMessageLike[\"content\"],\n string\n>[number];\n\nconst isPendingToolCall = (c: ThreadMessageLikeContentItem): boolean =>\n c.type === \"tool-call\" && c.result === undefined;\n\nconst isInterruptedToolCall = (c: ThreadMessageLikeContentItem): boolean => {\n if (c.type !== \"tool-call\" || c.result !== undefined) return false;\n return (\n c.interrupt != null ||\n (c.approval != null && c.approval.approved === undefined)\n );\n};\n\nexport namespace useExternalMessageConverter {\n export type Message =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: \"concat-content\" | \"none\";\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n messages?: readonly ThreadMessage[];\n };\n\n export type Metadata = {\n readonly toolStatuses?: Record<string, ToolExecutionStatus>;\n readonly error?: ReadonlyJSONValue;\n readonly messageTiming?: Record<string, MessageTiming>;\n };\n\n export type Callback<T> = (\n message: T,\n metadata: Metadata,\n ) => Message | Message[];\n}\n\ntype CallbackResult<T> = {\n input: T;\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype ChunkResult<T> = {\n inputs: T[];\n outputs: useExternalMessageConverter.Message[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst mergeInnerMessages = (existing: object, incoming: object) => ({\n [symbolInnerMessage]: [\n ...((existing as any)[symbolInnerMessage] ?? []),\n ...((incoming as any)[symbolInnerMessage] ?? []),\n ],\n});\n\nconst joinExternalMessages = (\n messages: readonly useExternalMessageConverter.Message[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = assistantMessage.content.findIndex(\n (c) => c.type === \"tool-call\" && c.toolCallId === output.toolCallId,\n );\n // Ignore orphaned tool results so one bad tool message does not\n // prevent rendering the rest of the conversation.\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName !== undefined) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n messages: output.messages,\n };\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n\n if (output.metadata.timing) {\n assistantMessage.metadata.timing = output.metadata.timing;\n }\n\n if (output.metadata.submittedFeedback) {\n assistantMessage.metadata.submittedFeedback =\n output.metadata.submittedFeedback;\n }\n }\n // TODO keep this in sync\n }\n\n // Add content parts, merging reasoning parts with same parentId\n for (const part of content) {\n if (part.type === \"tool-call\") {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"tool-call\" && c.toolCallId === part.toolCallId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n ...part,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n\n if (\n part.type === \"reasoning\" &&\n \"parentId\" in part &&\n part.parentId\n ) {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"reasoning\" &&\n \"parentId\" in c &&\n c.parentId === part.parentId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n text: `${existing.text}\\n\\n${part.text}`,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n assistantMessage.content.push(part);\n }\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nconst chunkExternalMessages = <T>(\n callbackResults: CallbackResult<T>[],\n joinStrategy?: \"concat-content\" | \"none\",\n) => {\n const results: ChunkResult<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: useExternalMessageConverter.Message[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nfunction createErrorAssistantMessage(\n error: ReadonlyJSONValue,\n): ThreadAssistantMessage {\n const msg: ThreadAssistantMessage = {\n id: generateErrorMessageId(),\n role: \"assistant\",\n content: [],\n status: { type: \"incomplete\", reason: \"error\", error },\n createdAt: new Date(),\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n custom: {},\n steps: [],\n },\n };\n bindExternalStoreMessage(msg, []);\n return msg;\n}\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: useExternalMessageConverter.Callback<T>,\n isRunning: boolean,\n metadata: useExternalMessageConverter.Metadata,\n) => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n const output = callback(message, metadata);\n const outputs = Array.isArray(output) ? output : [output];\n const result = { input: message, outputs };\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults);\n\n const result = chunks.map((message, idx) => {\n const isLast = idx === chunks.length - 1;\n const joined = joinExternalMessages(message.outputs);\n const hasInterruptedToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isInterruptedToolCall);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isPendingToolCall);\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasInterruptedToolCalls,\n hasPendingToolCalls,\n isLast ? metadata.error : undefined,\n );\n const newMessage = fromThreadMessageLike(\n joined,\n idx.toString(),\n autoStatus,\n );\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n });\n\n if (metadata.error) {\n const lastMessage = result.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n result.push(createErrorAssistantMessage(metadata.error));\n }\n }\n\n return result;\n};\n\nexport const useExternalMessageConverter = <T extends WeakKey>({\n callback,\n messages,\n isRunning,\n joinStrategy,\n metadata,\n}: {\n callback: useExternalMessageConverter.Callback<T>;\n messages: T[];\n isRunning: boolean;\n joinStrategy?: \"concat-content\" | \"none\" | undefined;\n metadata?: useExternalMessageConverter.Metadata | undefined;\n}) => {\n const state = useMemo(\n () => ({\n metadata: metadata ?? {},\n callback,\n callbackCache: new WeakMap<T, CallbackResult<T>>(),\n chunkCache: new WeakMap<\n useExternalMessageConverter.Message,\n ChunkResult<T>\n >(),\n converterCache: new ThreadMessageConverter(),\n }),\n [callback, metadata],\n );\n\n return useMemo(() => {\n const callbackResults: CallbackResult<T>[] = [];\n for (const message of messages) {\n let result = state.callbackCache.get(message);\n if (!result) {\n const output = state.callback(message, state.metadata);\n const outputs = Array.isArray(output) ? output : [output];\n result = { input: message, outputs };\n state.callbackCache.set(message, result);\n }\n callbackResults.push(result);\n }\n\n const chunks = chunkExternalMessages(callbackResults, joinStrategy).map(\n (m) => {\n const key = m.outputs[0];\n if (!key) return m;\n\n const cached = state.chunkCache.get(key);\n if (cached && shallowArrayEqual(cached.outputs, m.outputs))\n return cached;\n state.chunkCache.set(key, m);\n return m;\n },\n );\n\n const threadMessages = state.converterCache.convertMessages(\n chunks,\n (cache, message, idx) => {\n const isLast = idx === chunks.length - 1;\n\n const joined = joinExternalMessages(message.outputs);\n const hasInterruptedToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isInterruptedToolCall);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isPendingToolCall);\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasInterruptedToolCalls,\n hasPendingToolCalls,\n isLast ? state.metadata.error : undefined,\n );\n\n if (\n cache &&\n (cache.role !== \"assistant\" ||\n !isAutoStatus(cache.status) ||\n cache.status === autoStatus)\n ) {\n const inputs = getExternalStoreMessages<T>(cache);\n if (shallowArrayEqual(inputs, message.inputs)) {\n return cache;\n }\n }\n\n const newMessage = fromThreadMessageLike(\n joined,\n idx.toString(),\n autoStatus,\n );\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n },\n );\n\n bindExternalStoreMessage(threadMessages, messages);\n\n if (state.metadata.error) {\n const lastMessage = threadMessages.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n threadMessages.push(createErrorAssistantMessage(state.metadata.error));\n }\n }\n\n return threadMessages;\n }, [state, messages, isRunning, joinStrategy]);\n};\n\nconst shallowArrayEqual = (a: unknown[], b: unknown[]) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n"],"mappings":"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"}
@@ -41,6 +41,14 @@ type ToolCallMessagePartProps<TArgs = any, TResult = unknown> = MessagePartState
41
41
  * paused frontend tool execution.
42
42
  */
43
43
  resume: (payload: unknown) => void;
44
+ /**
45
+ * Responds to a server-side tool approval gate. Only valid while
46
+ * `approval` is set on the part and `approval.approved === undefined`.
47
+ */
48
+ respondToApproval: (response: {
49
+ approved: boolean;
50
+ reason?: string;
51
+ }) => void;
44
52
  };
45
53
  /** Component used to render a tool-call message part. */
46
54
  type ToolCallMessagePartComponent<TArgs = any, TResult = any> = ComponentType<ToolCallMessagePartProps<TArgs, TResult>>;
@@ -1 +1 @@
1
- {"version":3,"file":"MessagePartComponentTypes.d.ts","names":[],"sources":["../../../src/react/types/MessagePartComponentTypes.ts"],"mappings":";;;;;;;KAkBY,qBAAA;EACV,MAAA,EAAQ,iBAAiB;AAAA;AAAA,KAEf,yBAAA,GAA4B,aAAa,CAAC,qBAAA;AAAA,KAE1C,oBAAA,GAAuB,gBAAA,GAAmB,eAAe;AAAA,KACzD,wBAAA,GAA2B,aAAa,CAAC,oBAAA;AAAA,KAEzC,yBAAA,GAA4B,gBAAA,GAAmB,oBAAoB;AAAA,KACnE,6BAAA,GACV,aAAa,CAAC,yBAAA;AAAA,KAEJ,mBAAA,GAAsB,iBAAiB;EACjD,UAAA;EACA,QAAA;AAAA;AAAA,KAEU,uBAAA,GAA0B,aAAa,CAAC,mBAAA;AAAA,KAExC,sBAAA,GAAyB,gBAAA,GAAmB,iBAAiB;AAAA,KAC7D,0BAAA,GAA6B,aAAa,CAAC,sBAAA;AAAA,KAE3C,qBAAA,GAAwB,gBAAA,GAAmB,gBAAgB;AAAA,KAC3D,yBAAA,GAA4B,aAAa,CAAC,qBAAA;AAAA,KAE1C,oBAAA,GAAuB,gBAAA,GAAmB,eAAe;AAAA,KACzD,wBAAA,GAA2B,aAAa,CAAC,oBAAA;AAAA,KAEzC,8BAAA,GAAiC,gBAAA,GAC3C,yBAAyB;AAAA,KACf,kCAAA,GACV,aAAa,CAAC,8BAAA;AAAA,KAEJ,oBAAA,YAAgC,gBAAA,GAC1C,eAAA,CAAgB,CAAA;AAAA,KACN,wBAAA,YAAoC,aAAA,CAC9C,oBAAA,CAAqB,CAAA;AAAA,KAGX,wBAAA,mCAGR,gBAAA,GACF,mBAAA,CAAoB,KAAA,EAAO,OAAA;EAlCjB;;;;AAAmE;AAC/E;EAwCI,SAAA,GAAY,MAAA,EAAQ,OAAA,GAAU,YAAA,CAAa,OAAA;;;AAvCN;AAEzC;EA0CI,MAAA,GAAS,OAAA;AAAA;;KAID,4BAAA,+BAGR,aAAA,CAAc,wBAAA,CAAyB,KAAA,EAAO,OAAA;AAAA,KAEtC,qBAAA,GAAwB,SAAS;AAAA,KACjC,yBAAA,GAA4B,aAAa,CAAC,qBAAA;;AAlD5C;AAEV;;;;AAAuE;AAEvE;KAwDY,6BAAA,GAAgC,MAAM,SAAS,aAAA;AAAA,KAE/C,4BAAA,GAA+B,gBAAA,GACzC,uBAAuB;AAAA,KACb,gCAAA,GACV,aAAa,CAAC,4BAAA;AAAA,KAEJ,uBAAA;EA9DA,+BAgEV,IAAA,EAAM,gBAAA;EAEN,UAAA,EAAY,6BAAA,EAlE+D;EAoE3E,QAAA,GAAW,aAAA;IAAgB,SAAA;IAAmB,KAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"MessagePartComponentTypes.d.ts","names":[],"sources":["../../../src/react/types/MessagePartComponentTypes.ts"],"mappings":";;;;;;;KAkBY,qBAAA;EACV,MAAA,EAAQ,iBAAiB;AAAA;AAAA,KAEf,yBAAA,GAA4B,aAAa,CAAC,qBAAA;AAAA,KAE1C,oBAAA,GAAuB,gBAAA,GAAmB,eAAe;AAAA,KACzD,wBAAA,GAA2B,aAAa,CAAC,oBAAA;AAAA,KAEzC,yBAAA,GAA4B,gBAAA,GAAmB,oBAAoB;AAAA,KACnE,6BAAA,GACV,aAAa,CAAC,yBAAA;AAAA,KAEJ,mBAAA,GAAsB,iBAAiB;EACjD,UAAA;EACA,QAAA;AAAA;AAAA,KAEU,uBAAA,GAA0B,aAAa,CAAC,mBAAA;AAAA,KAExC,sBAAA,GAAyB,gBAAA,GAAmB,iBAAiB;AAAA,KAC7D,0BAAA,GAA6B,aAAa,CAAC,sBAAA;AAAA,KAE3C,qBAAA,GAAwB,gBAAA,GAAmB,gBAAgB;AAAA,KAC3D,yBAAA,GAA4B,aAAa,CAAC,qBAAA;AAAA,KAE1C,oBAAA,GAAuB,gBAAA,GAAmB,eAAe;AAAA,KACzD,wBAAA,GAA2B,aAAa,CAAC,oBAAA;AAAA,KAEzC,8BAAA,GAAiC,gBAAA,GAC3C,yBAAyB;AAAA,KACf,kCAAA,GACV,aAAa,CAAC,8BAAA;AAAA,KAEJ,oBAAA,YAAgC,gBAAA,GAC1C,eAAA,CAAgB,CAAA;AAAA,KACN,wBAAA,YAAoC,aAAA,CAC9C,oBAAA,CAAqB,CAAA;AAAA,KAGX,wBAAA,mCAGR,gBAAA,GACF,mBAAA,CAAoB,KAAA,EAAO,OAAA;EAlCjB;;;;AAAmE;AAC/E;EAwCI,SAAA,GAAY,MAAA,EAAQ,OAAA,GAAU,YAAA,CAAa,OAAA;;;AAvCN;AAEzC;EA0CI,MAAA,GAAS,OAAA;;;;;EAKT,iBAAA,GAAoB,QAAA;IAClB,QAAA;IACA,MAAA;EAAA;AAAA;;KAKM,4BAAA,+BAGR,aAAA,CAAc,wBAAA,CAAyB,KAAA,EAAO,OAAA;AAAA,KAEtC,qBAAA,GAAwB,SAAS;AAAA,KACjC,yBAAA,GAA4B,aAAa,CAAC,qBAAA;;;;AAtDmB;AACzE;;;;KA+DY,6BAAA,GAAgC,MAAM,SAAS,aAAA;AAAA,KAE/C,4BAAA,GAA+B,gBAAA,GACzC,uBAAuB;AAAA,KACb,gCAAA,GACV,aAAa,CAAC,4BAAA;AAAA,KAEJ,uBAAA;EApEwB,+BAsElC,IAAA,EAAM,gBAAA,EArEI;EAuEV,UAAA,EAAY,6BAAA;EAEZ,QAAA,GAAW,aAAA;IAAgB,SAAA;IAAmB,KAAA;EAAA;AAAA"}
@@ -1,3 +1,5 @@
1
+ import { PartState } from "../../store/scopes/part.js";
2
+
1
3
  //#region src/react/utils/groupParts.d.ts
2
4
  /**
3
5
  * Hierarchical adjacent-coalescing grouping for message parts.
@@ -11,12 +13,44 @@
11
13
  * (`"0.1.0"`), stable under append-only streaming.
12
14
  */
13
15
  /**
14
- * Public group key type. Group keys must be prefixed with `group-` so
15
- * that a unified `switch (part.type)` in the renderer can distinguish
16
- * a group key (e.g. `"group-thought"`) from a real part type
17
- * (`"text"`, `"tool-call"`).
16
+ * Symbol attached to memoizable `groupBy` functions (e.g. those returned
17
+ * by {@link groupPartByType}). Carries a string fingerprint of the config
18
+ * so `MessagePrimitive.GroupedParts` can memo the tree on
19
+ * `[parts, memoKey]` across renders — even when the helper call site
20
+ * reconstructs the function each render.
18
21
  */
19
- type GroupKey<TKey extends `group-${string}` = `group-${string}`> = TKey | readonly TKey[] | null | undefined;
22
+ declare const GROUPBY_MEMO_KEY: unique symbol;
23
+ /**
24
+ * Synthetic part-type key recognized by {@link groupPartByType}: a
25
+ * tool-call whose `mcp.app.resourceUri` points at an assistant-ui MCP
26
+ * app. Map this key to control how MCP-app tool calls are grouped —
27
+ * separately from regular `"tool-call"` parts.
28
+ */
29
+ type GroupPartType = PartState["type"] | "mcp-app";
30
+ /**
31
+ * Build a `groupBy` from a `part.type → group-key path` lookup.
32
+ * Parts whose type isn't in the map are left ungrouped. The returned
33
+ * function carries a stable {@link GROUPBY_MEMO_KEY} fingerprint so
34
+ * `<MessagePrimitive.GroupedParts>` can memoize its tree across renders.
35
+ *
36
+ * Special key `"mcp-app"` matches tool-call parts that point at an
37
+ * assistant-ui MCP app resource (`ui://...`) and takes precedence over
38
+ * the `"tool-call"` entry for those parts.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * <MessagePrimitive.GroupedParts
43
+ * groupBy={groupPartByType({
44
+ * reasoning: ["group-thought", "group-reasoning"],
45
+ * "tool-call": ["group-thought", "group-tool"],
46
+ * "mcp-app": [],
47
+ * })}
48
+ * >
49
+ * {({ part, children }) => { ... }}
50
+ * </MessagePrimitive.GroupedParts>
51
+ * ```
52
+ */
53
+ declare const groupPartByType: <TKey extends `group-${string}`>(map: Partial<Readonly<Record<GroupPartType, readonly TKey[]>>>) => ((part: PartState) => readonly TKey[]);
20
54
  type GroupNode = GroupNodeGroup | GroupNodePart;
21
55
  interface GroupNodeGroup {
22
56
  readonly type: "group";
@@ -35,12 +69,6 @@ interface GroupNodePart {
35
69
  /** Structural React key: sibling-index path within parent. */
36
70
  readonly nodeKey: string;
37
71
  }
38
- /**
39
- * Normalize a `groupBy` return value to a path array.
40
- * `null`/`undefined`/`[]` → `[]` (ungrouped).
41
- * `"foo"` → `["foo"]`. Arrays pass through.
42
- */
43
- declare const normalizeGroupKey: (key: GroupKey) => readonly string[];
44
72
  /**
45
73
  * Build the group tree from an array of normalized group paths.
46
74
  * `paths[i]` is the path for part `i`. The output tree contains one
@@ -48,5 +76,5 @@ declare const normalizeGroupKey: (key: GroupKey) => readonly string[];
48
76
  */
49
77
  declare const buildGroupTree: (paths: readonly (readonly string[])[]) => readonly GroupNode[];
50
78
  //#endregion
51
- export { GroupKey, GroupNode, GroupNodeGroup, GroupNodePart, buildGroupTree, normalizeGroupKey };
79
+ export { GROUPBY_MEMO_KEY, GroupNode, GroupNodeGroup, GroupNodePart, buildGroupTree, groupPartByType };
52
80
  //# sourceMappingURL=groupParts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"groupParts.d.ts","names":[],"sources":["../../../src/react/utils/groupParts.ts"],"mappings":";;AAkBA;;;;;;;;AAEiB;AAIjB;;;;AAAsD;AAEtD;;KARY,QAAA,uDACR,IAAA,YACS,IAAI;AAAA,KAIL,SAAA,GAAY,cAAA,GAAiB,aAAa;AAAA,UAErC,cAAA;EAAA,SACN,IAAA;EAIA;EAAA,SAFA,GAAA;EAKA;EAAA,SAHA,OAAA;EAG4B;EAAA,SAD5B,OAAA;EAAA,SACA,QAAA,WAAmB,SAAS;AAAA;AAAA,UAGtB,aAAA;EAAA,SACN,IAAA;EAAA;EAAA,SAEA,KAAA;EAEA;EAAA,SAAA,OAAA;AAAA;AAUX;;;;AAA+C;AAA/C,cAAa,iBAAA,GAAqB,GAAa,EAAR,QAAQ;;;;AA0B1B;;cAFR,cAAA,GACX,KAAA,8CACU,SAAS"}
1
+ {"version":3,"file":"groupParts.d.ts","names":[],"sources":["../../../src/react/utils/groupParts.ts"],"mappings":";;;;;AAsBA;;;;AAEC;AAAC;;;;AAQ4B;AAyB9B;;;;;;AAzB8B,cAVjB,gBAAA;;;;;;;KAUR,aAAA,GAAgB,SAAS;;;;;;;;;;AA2BQ;AAuBtC;;;;AAAsD;AAEtD;;;;;;;;cA3Ba,eAAA,mCACX,GAAA,EAAK,OAAA,CAAQ,QAAA,CAAS,MAAA,CAAO,aAAA,WAAwB,IAAA,YAClD,IAAA,EAAM,SAAA,cAAuB,IAAA;AAAA,KAuBtB,SAAA,GAAY,cAAA,GAAiB,aAAa;AAAA,UAErC,cAAA;EAAA,SACN,IAAA;EAUM;EAAA,SARN,GAAA;;WAEA,OAAA;EAOA;EAAA,SALA,OAAA;EAAA,SACA,QAAA,WAAmB,SAAS;AAAA;AAAA,UAGtB,aAAA;EAAA,SACN,IAAA;EAoGV;EAAA,SAlGU,KAAA;EAwBT;EAAA,SAtBS,OAAA;AAAA;;;;;;cAqBE,cAAA,GACX,KAAA,8CACU,SAAS"}
@@ -1,14 +1,56 @@
1
+ import { isMcpAppUri } from "../../types/message.js";
1
2
  //#region src/react/utils/groupParts.ts
2
- const EMPTY_PATH = Object.freeze([]);
3
3
  /**
4
- * Normalize a `groupBy` return value to a path array.
5
- * `null`/`undefined`/`[]` → `[]` (ungrouped).
6
- * `"foo"` `["foo"]`. Arrays pass through.
4
+ * Hierarchical adjacent-coalescing grouping for message parts.
5
+ *
6
+ * Given a group path per part (from `groupBy`), builds a tree of group
7
+ * nodes wrapping individual parts. Adjacent parts sharing a path prefix
8
+ * coalesce into the same group; ungrouped parts are direct children of
9
+ * the root.
10
+ *
11
+ * Each node gets a structural `nodeKey` built from sibling indices
12
+ * (`"0.1.0"`), stable under append-only streaming.
7
13
  */
8
- const normalizeGroupKey = (key) => {
9
- if (key == null) return EMPTY_PATH;
10
- if (typeof key === "string") return [key];
11
- return key;
14
+ /**
15
+ * Symbol attached to memoizable `groupBy` functions (e.g. those returned
16
+ * by {@link groupPartByType}). Carries a string fingerprint of the config
17
+ * so `MessagePrimitive.GroupedParts` can memo the tree on
18
+ * `[parts, memoKey]` across renders — even when the helper call site
19
+ * reconstructs the function each render.
20
+ */
21
+ const GROUPBY_MEMO_KEY = Symbol.for("@assistant-ui/groupBy.memoKey");
22
+ /**
23
+ * Build a `groupBy` from a `part.type → group-key path` lookup.
24
+ * Parts whose type isn't in the map are left ungrouped. The returned
25
+ * function carries a stable {@link GROUPBY_MEMO_KEY} fingerprint so
26
+ * `<MessagePrimitive.GroupedParts>` can memoize its tree across renders.
27
+ *
28
+ * Special key `"mcp-app"` matches tool-call parts that point at an
29
+ * assistant-ui MCP app resource (`ui://...`) and takes precedence over
30
+ * the `"tool-call"` entry for those parts.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * <MessagePrimitive.GroupedParts
35
+ * groupBy={groupPartByType({
36
+ * reasoning: ["group-thought", "group-reasoning"],
37
+ * "tool-call": ["group-thought", "group-tool"],
38
+ * "mcp-app": [],
39
+ * })}
40
+ * >
41
+ * {({ part, children }) => { ... }}
42
+ * </MessagePrimitive.GroupedParts>
43
+ * ```
44
+ */
45
+ const groupPartByType = (map) => {
46
+ const lookup = map;
47
+ const fn = ((part) => {
48
+ if (part.type === "tool-call" && lookup["mcp-app"] !== void 0 && isMcpAppUri(part.mcp?.app?.resourceUri)) return lookup["mcp-app"];
49
+ return lookup[part.type] ?? [];
50
+ });
51
+ const sortedEntries = Object.keys(map).sort().map((k) => [k, map[k]]);
52
+ fn[GROUPBY_MEMO_KEY] = `groupPartByType:${JSON.stringify(sortedEntries)}`;
53
+ return fn;
12
54
  };
13
55
  const makeChildNodeKey = (parent) => {
14
56
  const idx = parent.nextChildIdx++;
@@ -65,6 +107,6 @@ const buildGroupTree = (paths) => {
65
107
  return root.children;
66
108
  };
67
109
  //#endregion
68
- export { buildGroupTree, normalizeGroupKey };
110
+ export { GROUPBY_MEMO_KEY, buildGroupTree, groupPartByType };
69
111
 
70
112
  //# sourceMappingURL=groupParts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"groupParts.js","names":[],"sources":["../../../src/react/utils/groupParts.ts"],"sourcesContent":["/**\n * Hierarchical adjacent-coalescing grouping for message parts.\n *\n * Given a group path per part (from `groupBy`), builds a tree of group\n * nodes wrapping individual parts. Adjacent parts sharing a path prefix\n * coalesce into the same group; ungrouped parts are direct children of\n * the root.\n *\n * Each node gets a structural `nodeKey` built from sibling indices\n * (`\"0.1.0\"`), stable under append-only streaming.\n */\n\n/**\n * Public group key type. Group keys must be prefixed with `group-` so\n * that a unified `switch (part.type)` in the renderer can distinguish\n * a group key (e.g. `\"group-thought\"`) from a real part type\n * (`\"text\"`, `\"tool-call\"`).\n */\nexport type GroupKey<TKey extends `group-${string}` = `group-${string}`> =\n | TKey\n | readonly TKey[]\n | null\n | undefined;\n\nexport type GroupNode = GroupNodeGroup | GroupNodePart;\n\nexport interface GroupNodeGroup {\n readonly type: \"group\";\n /** Current-level group key (last segment of the path). */\n readonly key: string;\n /** Structural React key: sibling-index path, e.g. `\"0.1.0\"`. */\n readonly nodeKey: string;\n /** Indices of parts in this subtree, in order. */\n readonly indices: readonly number[];\n readonly children: readonly GroupNode[];\n}\n\nexport interface GroupNodePart {\n readonly type: \"part\";\n /** Index of the part in the message. */\n readonly index: number;\n /** Structural React key: sibling-index path within parent. */\n readonly nodeKey: string;\n}\n\nconst EMPTY_PATH: readonly string[] = Object.freeze([]);\n\n/**\n * Normalize a `groupBy` return value to a path array.\n * `null`/`undefined`/`[]` → `[]` (ungrouped).\n * `\"foo\"` → `[\"foo\"]`. Arrays pass through.\n */\nexport const normalizeGroupKey = (key: GroupKey): readonly string[] => {\n if (key == null) return EMPTY_PATH;\n if (typeof key === \"string\") return [key];\n return key;\n};\n\ninterface BuildFrame {\n key: string;\n nodeKey: string;\n indices: number[];\n children: GroupNode[];\n nextChildIdx: number;\n}\n\nconst makeChildNodeKey = (parent: BuildFrame): string => {\n const idx = parent.nextChildIdx++;\n return parent.nodeKey === \"\" ? String(idx) : `${parent.nodeKey}.${idx}`;\n};\n\n/**\n * Build the group tree from an array of normalized group paths.\n * `paths[i]` is the path for part `i`. The output tree contains one\n * `part` node per part and one `group` node per coalesced run.\n */\nexport const buildGroupTree = (\n paths: readonly (readonly string[])[],\n): readonly GroupNode[] => {\n const root: BuildFrame = {\n key: \"\",\n nodeKey: \"\",\n indices: [],\n children: [],\n nextChildIdx: 0,\n };\n const stack: BuildFrame[] = [root];\n\n const closeTop = (): void => {\n const closing = stack.pop()!;\n const parent = stack[stack.length - 1]!;\n parent.children.push({\n type: \"group\",\n key: closing.key,\n nodeKey: closing.nodeKey,\n indices: closing.indices,\n children: closing.children,\n });\n };\n\n for (let i = 0; i < paths.length; i++) {\n const path = paths[i]!;\n\n // Find the longest prefix shared between currently-open groups\n // (excluding root) and this part's path.\n let common = 0;\n while (\n common < stack.length - 1 &&\n common < path.length &&\n stack[common + 1]!.key === path[common]\n ) {\n common++;\n }\n\n // Close groups not on this path.\n while (stack.length - 1 > common) {\n closeTop();\n }\n\n // Open new groups down to the part's depth.\n while (stack.length - 1 < path.length) {\n const parent = stack[stack.length - 1]!;\n stack.push({\n key: path[stack.length - 1]!,\n nodeKey: makeChildNodeKey(parent),\n indices: [],\n children: [],\n nextChildIdx: 0,\n });\n }\n\n // Push this part as a leaf in the deepest open group (or root).\n const top = stack[stack.length - 1]!;\n top.children.push({\n type: \"part\",\n index: i,\n nodeKey: makeChildNodeKey(top),\n });\n\n // Record the part index in every open ancestor group.\n for (let s = 1; s < stack.length; s++) {\n stack[s]!.indices.push(i);\n }\n }\n\n // Close any still-open groups.\n while (stack.length > 1) {\n closeTop();\n }\n\n return root.children;\n};\n"],"mappings":";AA6CA,MAAM,aAAgC,OAAO,OAAO,CAAC,CAAC;;;;;;AAOtD,MAAa,qBAAqB,QAAqC;CACrE,IAAI,OAAO,MAAM,OAAO;CACxB,IAAI,OAAO,QAAQ,UAAU,OAAO,CAAC,GAAG;CACxC,OAAO;AACT;AAUA,MAAM,oBAAoB,WAA+B;CACvD,MAAM,MAAM,OAAO;CACnB,OAAO,OAAO,YAAY,KAAK,OAAO,GAAG,IAAI,GAAG,OAAO,QAAQ,GAAG;AACpE;;;;;;AAOA,MAAa,kBACX,UACyB;CACzB,MAAM,OAAmB;EACvB,KAAK;EACL,SAAS;EACT,SAAS,CAAC;EACV,UAAU,CAAC;EACX,cAAc;CAChB;CACA,MAAM,QAAsB,CAAC,IAAI;CAEjC,MAAM,iBAAuB;EAC3B,MAAM,UAAU,MAAM,IAAI;EAE1B,MADqB,MAAM,SAAS,GAC7B,SAAS,KAAK;GACnB,MAAM;GACN,KAAK,QAAQ;GACb,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,UAAU,QAAQ;EACpB,CAAC;CACH;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,OAAO,MAAM;EAInB,IAAI,SAAS;EACb,OACE,SAAS,MAAM,SAAS,KACxB,SAAS,KAAK,UACd,MAAM,SAAS,GAAI,QAAQ,KAAK,SAEhC;EAIF,OAAO,MAAM,SAAS,IAAI,QACxB,SAAS;EAIX,OAAO,MAAM,SAAS,IAAI,KAAK,QAAQ;GACrC,MAAM,SAAS,MAAM,MAAM,SAAS;GACpC,MAAM,KAAK;IACT,KAAK,KAAK,MAAM,SAAS;IACzB,SAAS,iBAAiB,MAAM;IAChC,SAAS,CAAC;IACV,UAAU,CAAC;IACX,cAAc;GAChB,CAAC;EACH;EAGA,MAAM,MAAM,MAAM,MAAM,SAAS;EACjC,IAAI,SAAS,KAAK;GAChB,MAAM;GACN,OAAO;GACP,SAAS,iBAAiB,GAAG;EAC/B,CAAC;EAGD,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,MAAM,GAAI,QAAQ,KAAK,CAAC;CAE5B;CAGA,OAAO,MAAM,SAAS,GACpB,SAAS;CAGX,OAAO,KAAK;AACd"}
1
+ {"version":3,"file":"groupParts.js","names":[],"sources":["../../../src/react/utils/groupParts.ts"],"sourcesContent":["import { isMcpAppUri } from \"../../types/message\";\nimport type { PartState } from \"../../store/scopes/part\";\n\n/**\n * Hierarchical adjacent-coalescing grouping for message parts.\n *\n * Given a group path per part (from `groupBy`), builds a tree of group\n * nodes wrapping individual parts. Adjacent parts sharing a path prefix\n * coalesce into the same group; ungrouped parts are direct children of\n * the root.\n *\n * Each node gets a structural `nodeKey` built from sibling indices\n * (`\"0.1.0\"`), stable under append-only streaming.\n */\n\n/**\n * Symbol attached to memoizable `groupBy` functions (e.g. those returned\n * by {@link groupPartByType}). Carries a string fingerprint of the config\n * so `MessagePrimitive.GroupedParts` can memo the tree on\n * `[parts, memoKey]` across renders — even when the helper call site\n * reconstructs the function each render.\n */\nexport const GROUPBY_MEMO_KEY: unique symbol = Symbol.for(\n \"@assistant-ui/groupBy.memoKey\",\n);\n\n/**\n * Synthetic part-type key recognized by {@link groupPartByType}: a\n * tool-call whose `mcp.app.resourceUri` points at an assistant-ui MCP\n * app. Map this key to control how MCP-app tool calls are grouped —\n * separately from regular `\"tool-call\"` parts.\n */\ntype GroupPartType = PartState[\"type\"] | \"mcp-app\";\n\n/**\n * Build a `groupBy` from a `part.type → group-key path` lookup.\n * Parts whose type isn't in the map are left ungrouped. The returned\n * function carries a stable {@link GROUPBY_MEMO_KEY} fingerprint so\n * `<MessagePrimitive.GroupedParts>` can memoize its tree across renders.\n *\n * Special key `\"mcp-app\"` matches tool-call parts that point at an\n * assistant-ui MCP app resource (`ui://...`) and takes precedence over\n * the `\"tool-call\"` entry for those parts.\n *\n * @example\n * ```tsx\n * <MessagePrimitive.GroupedParts\n * groupBy={groupPartByType({\n * reasoning: [\"group-thought\", \"group-reasoning\"],\n * \"tool-call\": [\"group-thought\", \"group-tool\"],\n * \"mcp-app\": [],\n * })}\n * >\n * {({ part, children }) => { ... }}\n * </MessagePrimitive.GroupedParts>\n * ```\n */\nexport const groupPartByType = <TKey extends `group-${string}`>(\n map: Partial<Readonly<Record<GroupPartType, readonly TKey[]>>>,\n): ((part: PartState) => readonly TKey[]) => {\n const lookup = map as Readonly<Record<string, readonly TKey[] | undefined>>;\n const fn = ((part) => {\n if (\n part.type === \"tool-call\" &&\n lookup[\"mcp-app\"] !== undefined &&\n isMcpAppUri(part.mcp?.app?.resourceUri)\n ) {\n return lookup[\"mcp-app\"]!;\n }\n return lookup[part.type] ?? [];\n }) as ((part: PartState) => readonly TKey[]) & {\n [GROUPBY_MEMO_KEY]?: string;\n };\n // Sort keys so the fingerprint is insensitive to map insertion order —\n // two maps with the same key/value pairs but different declaration order\n // would otherwise hash differently and invalidate the memo unnecessarily.\n const sortedKeys = Object.keys(map).sort();\n const sortedEntries = sortedKeys.map((k) => [k, map[k as keyof typeof map]]);\n fn[GROUPBY_MEMO_KEY] = `groupPartByType:${JSON.stringify(sortedEntries)}`;\n return fn;\n};\n\nexport type GroupNode = GroupNodeGroup | GroupNodePart;\n\nexport interface GroupNodeGroup {\n readonly type: \"group\";\n /** Current-level group key (last segment of the path). */\n readonly key: string;\n /** Structural React key: sibling-index path, e.g. `\"0.1.0\"`. */\n readonly nodeKey: string;\n /** Indices of parts in this subtree, in order. */\n readonly indices: readonly number[];\n readonly children: readonly GroupNode[];\n}\n\nexport interface GroupNodePart {\n readonly type: \"part\";\n /** Index of the part in the message. */\n readonly index: number;\n /** Structural React key: sibling-index path within parent. */\n readonly nodeKey: string;\n}\n\ninterface BuildFrame {\n key: string;\n nodeKey: string;\n indices: number[];\n children: GroupNode[];\n nextChildIdx: number;\n}\n\nconst makeChildNodeKey = (parent: BuildFrame): string => {\n const idx = parent.nextChildIdx++;\n return parent.nodeKey === \"\" ? String(idx) : `${parent.nodeKey}.${idx}`;\n};\n\n/**\n * Build the group tree from an array of normalized group paths.\n * `paths[i]` is the path for part `i`. The output tree contains one\n * `part` node per part and one `group` node per coalesced run.\n */\nexport const buildGroupTree = (\n paths: readonly (readonly string[])[],\n): readonly GroupNode[] => {\n const root: BuildFrame = {\n key: \"\",\n nodeKey: \"\",\n indices: [],\n children: [],\n nextChildIdx: 0,\n };\n const stack: BuildFrame[] = [root];\n\n const closeTop = (): void => {\n const closing = stack.pop()!;\n const parent = stack[stack.length - 1]!;\n parent.children.push({\n type: \"group\",\n key: closing.key,\n nodeKey: closing.nodeKey,\n indices: closing.indices,\n children: closing.children,\n });\n };\n\n for (let i = 0; i < paths.length; i++) {\n const path = paths[i]!;\n\n // Find the longest prefix shared between currently-open groups\n // (excluding root) and this part's path.\n let common = 0;\n while (\n common < stack.length - 1 &&\n common < path.length &&\n stack[common + 1]!.key === path[common]\n ) {\n common++;\n }\n\n // Close groups not on this path.\n while (stack.length - 1 > common) {\n closeTop();\n }\n\n // Open new groups down to the part's depth.\n while (stack.length - 1 < path.length) {\n const parent = stack[stack.length - 1]!;\n stack.push({\n key: path[stack.length - 1]!,\n nodeKey: makeChildNodeKey(parent),\n indices: [],\n children: [],\n nextChildIdx: 0,\n });\n }\n\n // Push this part as a leaf in the deepest open group (or root).\n const top = stack[stack.length - 1]!;\n top.children.push({\n type: \"part\",\n index: i,\n nodeKey: makeChildNodeKey(top),\n });\n\n // Record the part index in every open ancestor group.\n for (let s = 1; s < stack.length; s++) {\n stack[s]!.indices.push(i);\n }\n }\n\n // Close any still-open groups.\n while (stack.length > 1) {\n closeTop();\n }\n\n return root.children;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsBA,MAAa,mBAAkC,OAAO,IACpD,+BACF;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAa,mBACX,QAC2C;CAC3C,MAAM,SAAS;CACf,MAAM,OAAO,SAAS;EACpB,IACE,KAAK,SAAS,eACd,OAAO,eAAe,KAAA,KACtB,YAAY,KAAK,KAAK,KAAK,WAAW,GAEtC,OAAO,OAAO;EAEhB,OAAO,OAAO,KAAK,SAAS,CAAC;CAC/B;CAOA,MAAM,gBADa,OAAO,KAAK,GAAG,EAAE,KACL,EAAE,KAAK,MAAM,CAAC,GAAG,IAAI,EAAsB,CAAC;CAC3E,GAAG,oBAAoB,mBAAmB,KAAK,UAAU,aAAa;CACtE,OAAO;AACT;AA+BA,MAAM,oBAAoB,WAA+B;CACvD,MAAM,MAAM,OAAO;CACnB,OAAO,OAAO,YAAY,KAAK,OAAO,GAAG,IAAI,GAAG,OAAO,QAAQ,GAAG;AACpE;;;;;;AAOA,MAAa,kBACX,UACyB;CACzB,MAAM,OAAmB;EACvB,KAAK;EACL,SAAS;EACT,SAAS,CAAC;EACV,UAAU,CAAC;EACX,cAAc;CAChB;CACA,MAAM,QAAsB,CAAC,IAAI;CAEjC,MAAM,iBAAuB;EAC3B,MAAM,UAAU,MAAM,IAAI;EAE1B,MADqB,MAAM,SAAS,GAC7B,SAAS,KAAK;GACnB,MAAM;GACN,KAAK,QAAQ;GACb,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,UAAU,QAAQ;EACpB,CAAC;CACH;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,OAAO,MAAM;EAInB,IAAI,SAAS;EACb,OACE,SAAS,MAAM,SAAS,KACxB,SAAS,KAAK,UACd,MAAM,SAAS,GAAI,QAAQ,KAAK,SAEhC;EAIF,OAAO,MAAM,SAAS,IAAI,QACxB,SAAS;EAIX,OAAO,MAAM,SAAS,IAAI,KAAK,QAAQ;GACrC,MAAM,SAAS,MAAM,MAAM,SAAS;GACpC,MAAM,KAAK;IACT,KAAK,KAAK,MAAM,SAAS;IACzB,SAAS,iBAAiB,MAAM;IAChC,SAAS,CAAC;IACV,UAAU,CAAC;IACX,cAAc;GAChB,CAAC;EACH;EAGA,MAAM,MAAM,MAAM,MAAM,SAAS;EACjC,IAAI,SAAS,KAAK;GAChB,MAAM;GACN,OAAO;GACP,SAAS,iBAAiB,GAAG;EAC/B,CAAC;EAGD,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,MAAM,GAAI,QAAQ,KAAK,CAAC;CAE5B;CAGA,OAAO,MAAM,SAAS,GACpB,SAAS;CAGX,OAAO,KAAK;AACd"}
@@ -14,6 +14,10 @@ type MessagePartSnapshotBinding = SubscribableWithState<MessagePartState, Messag
14
14
  type MessagePartRuntime = {
15
15
  addToolResult(result: any | ToolResponse<any>): void;
16
16
  resumeToolCall(payload: unknown): void;
17
+ respondToToolApproval(response: {
18
+ approved: boolean;
19
+ reason?: string;
20
+ }): void;
17
21
  readonly path: MessagePartRuntimePath;
18
22
  getState(): MessagePartState;
19
23
  subscribe(callback: () => void): Unsubscribe;
@@ -28,6 +32,10 @@ declare class MessagePartRuntimeImpl implements MessagePartRuntime {
28
32
  getState(): MessagePartState;
29
33
  addToolResult(result: any | ToolResponse<any>): void;
30
34
  resumeToolCall(payload: unknown): void;
35
+ respondToToolApproval(response: {
36
+ approved: boolean;
37
+ reason?: string;
38
+ }): void;
31
39
  subscribe(callback: () => void): Unsubscribe;
32
40
  }
33
41
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"message-part-runtime.d.ts","names":[],"sources":["../../../src/runtime/api/message-part-runtime.ts"],"mappings":";;;;;;;;;KAaY,gBAAA,IACR,qBAAA,GACA,0BAAA;EAAA,SAEO,MAAA,EAAQ,iBAAA,GAAoB,yBAAA;AAAA;AAAA,KAGlC,0BAAA,GAA6B,qBAAA,CAChC,gBAAA,EACA,sBAAA;AAAA,KAGU,kBAAA;EACV,aAAA,CAAc,MAAA,QAAc,YAAA;EAC5B,cAAA,CAAe,OAAA;EAAA,SAEN,IAAA,EAAM,sBAAA;EACf,QAAA,IAAY,gBAAA;EACZ,SAAA,CAAU,QAAA,eAAuB,WAAA;AAAA;AAAA,cAGtB,sBAAA,YAAkC,kBAAA;EAAA,QAMnC,cAAA;EAAA,QACA,UAAA;EAAA,QACA,SAAA;EAAA,IAPC,IAAA,CAAA,GAAI,sBAAA;cAKL,cAAA,EAAgB,0BAAA,EAChB,UAAA,GAAa,mBAAA,cACb,SAAA,GAAY,wBAAA;EAAA,UAKZ,sBAAA,CAAA;EAOH,QAAA,CAAA,GAAQ,gBAAA;EAIR,aAAA,CAAc,MAAA,QAAc,YAAA;EA8B5B,cAAA,CAAe,OAAA;EAgBf,SAAA,CAAU,QAAA,eAAoB,WAAA;AAAA"}
1
+ {"version":3,"file":"message-part-runtime.d.ts","names":[],"sources":["../../../src/runtime/api/message-part-runtime.ts"],"mappings":";;;;;;;;;KAaY,gBAAA,IACR,qBAAA,GACA,0BAAA;EAAA,SAEO,MAAA,EAAQ,iBAAA,GAAoB,yBAAA;AAAA;AAAA,KAGlC,0BAAA,GAA6B,qBAAA,CAChC,gBAAA,EACA,sBAAA;AAAA,KAGU,kBAAA;EACV,aAAA,CAAc,MAAA,QAAc,YAAA;EAC5B,cAAA,CAAe,OAAA;EACf,qBAAA,CAAsB,QAAA;IAAY,QAAA;IAAmB,MAAA;EAAA;EAAA,SAE5C,IAAA,EAAM,sBAAA;EACf,QAAA,IAAY,gBAAA;EACZ,SAAA,CAAU,QAAA,eAAuB,WAAA;AAAA;AAAA,cAGtB,sBAAA,YAAkC,kBAAA;EAAA,QAMnC,cAAA;EAAA,QACA,UAAA;EAAA,QACA,SAAA;EAAA,IAPC,IAAA,CAAA,GAAI,sBAAA;cAKL,cAAA,EAAgB,0BAAA,EAChB,UAAA,GAAa,mBAAA,cACb,SAAA,GAAY,wBAAA;EAAA,UAKZ,sBAAA,CAAA;EAQH,QAAA,CAAA,GAAQ,gBAAA;EAIR,aAAA,CAAc,MAAA,QAAc,YAAA;EA8B5B,cAAA,CAAe,OAAA;EAgBf,qBAAA,CAAsB,QAAA;IAC3B,QAAA;IACA,MAAA;EAAA;EAsBK,SAAA,CAAU,QAAA,eAAoB,WAAA;AAAA"}
@@ -16,6 +16,7 @@ var MessagePartRuntimeImpl = class {
16
16
  __internal_bindMethods() {
17
17
  this.addToolResult = this.addToolResult.bind(this);
18
18
  this.resumeToolCall = this.resumeToolCall.bind(this);
19
+ this.respondToToolApproval = this.respondToToolApproval.bind(this);
19
20
  this.getState = this.getState.bind(this);
20
21
  this.subscribe = this.subscribe.bind(this);
21
22
  }
@@ -53,6 +54,18 @@ var MessagePartRuntimeImpl = class {
53
54
  payload
54
55
  });
55
56
  }
57
+ respondToToolApproval(response) {
58
+ const state = this.contentBinding.getState();
59
+ if (!state) throw new Error("Message part is not available");
60
+ if (state.type !== "tool-call") throw new Error("Tried to respond to tool approval on non-tool message part");
61
+ if (!state.approval || state.approval.approved !== void 0) throw new Error("Tool call has no pending approval");
62
+ if (!this.threadApi) throw new Error("Thread API is not available");
63
+ this.threadApi.getState().respondToToolApproval({
64
+ approvalId: state.approval.id,
65
+ approved: response.approved,
66
+ ...response.reason != null && { reason: response.reason }
67
+ });
68
+ }
56
69
  subscribe(callback) {
57
70
  return this.contentBinding.subscribe(callback);
58
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"message-part-runtime.js","names":[],"sources":["../../../src/runtime/api/message-part-runtime.ts"],"sourcesContent":["import type {\n ThreadAssistantMessagePart,\n ThreadUserMessagePart,\n ToolCallMessagePartStatus,\n} from \"../../types/message\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { MessagePartStatus } from \"../../types/message\";\nimport type { SubscribableWithState } from \"../../subscribable/subscribable\";\nimport type { ThreadRuntimeCoreBinding } from \"./thread-runtime\";\nimport type { MessageStateBinding } from \"./bindings\";\nimport type { MessagePartRuntimePath } from \"./paths\";\nimport { ToolResponse } from \"assistant-stream\";\n\nexport type MessagePartState = (\n | ThreadUserMessagePart\n | ThreadAssistantMessagePart\n) & {\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n};\n\ntype MessagePartSnapshotBinding = SubscribableWithState<\n MessagePartState,\n MessagePartRuntimePath\n>;\n\nexport type MessagePartRuntime = {\n addToolResult(result: any | ToolResponse<any>): void;\n resumeToolCall(payload: unknown): void;\n\n readonly path: MessagePartRuntimePath;\n getState(): MessagePartState;\n subscribe(callback: () => void): Unsubscribe;\n};\n\nexport class MessagePartRuntimeImpl implements MessagePartRuntime {\n public get path() {\n return this.contentBinding.path;\n }\n\n constructor(\n private contentBinding: MessagePartSnapshotBinding,\n private messageApi?: MessageStateBinding,\n private threadApi?: ThreadRuntimeCoreBinding,\n ) {\n this.__internal_bindMethods();\n }\n\n protected __internal_bindMethods() {\n this.addToolResult = this.addToolResult.bind(this);\n this.resumeToolCall = this.resumeToolCall.bind(this);\n this.getState = this.getState.bind(this);\n this.subscribe = this.subscribe.bind(this);\n }\n\n public getState() {\n return this.contentBinding.getState();\n }\n\n public addToolResult(result: any | ToolResponse<any>) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to add tool result to non-tool message part\");\n\n if (!this.messageApi)\n throw new Error(\n \"Message API is not available. This is likely a bug in assistant-ui.\",\n );\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const message = this.messageApi.getState();\n if (!message) throw new Error(\"Message is not available\");\n\n const toolName = state.toolName;\n const toolCallId = state.toolCallId;\n\n const response = ToolResponse.toResponse(result);\n this.threadApi.getState().addToolResult({\n messageId: message.id,\n toolName,\n toolCallId,\n result: response.result,\n artifact: response.artifact,\n isError: response.isError,\n });\n }\n\n public resumeToolCall(payload: unknown) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to resume tool call on non-tool message part\");\n\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const toolCallId = state.toolCallId;\n this.threadApi.getState().resumeToolCall({\n toolCallId,\n payload,\n });\n }\n\n public subscribe(callback: () => void) {\n return this.contentBinding.subscribe(callback);\n }\n}\n"],"mappings":";;AAkCA,IAAa,yBAAb,MAAkE;CAMtD;CACA;CACA;CAPV,IAAW,OAAO;EAChB,OAAO,KAAK,eAAe;CAC7B;CAEA,YACE,gBACA,YACA,WACA;EAHQ,KAAA,iBAAA;EACA,KAAA,aAAA;EACA,KAAA,YAAA;EAER,KAAK,uBAAuB;CAC9B;CAEA,yBAAmC;EACjC,KAAK,gBAAgB,KAAK,cAAc,KAAK,IAAI;EACjD,KAAK,iBAAiB,KAAK,eAAe,KAAK,IAAI;EACnD,KAAK,WAAW,KAAK,SAAS,KAAK,IAAI;EACvC,KAAK,YAAY,KAAK,UAAU,KAAK,IAAI;CAC3C;CAEA,WAAkB;EAChB,OAAO,KAAK,eAAe,SAAS;CACtC;CAEA,cAAqB,QAAiC;EACpD,MAAM,QAAQ,KAAK,eAAe,SAAS;EAC3C,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,+BAA+B;EAE3D,IAAI,MAAM,SAAS,aACjB,MAAM,IAAI,MAAM,mDAAmD;EAErE,IAAI,CAAC,KAAK,YACR,MAAM,IAAI,MACR,qEACF;EACF,IAAI,CAAC,KAAK,WAAW,MAAM,IAAI,MAAM,6BAA6B;EAElE,MAAM,UAAU,KAAK,WAAW,SAAS;EACzC,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,0BAA0B;EAExD,MAAM,WAAW,MAAM;EACvB,MAAM,aAAa,MAAM;EAEzB,MAAM,WAAW,aAAa,WAAW,MAAM;EAC/C,KAAK,UAAU,SAAS,EAAE,cAAc;GACtC,WAAW,QAAQ;GACnB;GACA;GACA,QAAQ,SAAS;GACjB,UAAU,SAAS;GACnB,SAAS,SAAS;EACpB,CAAC;CACH;CAEA,eAAsB,SAAkB;EACtC,MAAM,QAAQ,KAAK,eAAe,SAAS;EAC3C,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,+BAA+B;EAE3D,IAAI,MAAM,SAAS,aACjB,MAAM,IAAI,MAAM,oDAAoD;EAEtE,IAAI,CAAC,KAAK,WAAW,MAAM,IAAI,MAAM,6BAA6B;EAElE,MAAM,aAAa,MAAM;EACzB,KAAK,UAAU,SAAS,EAAE,eAAe;GACvC;GACA;EACF,CAAC;CACH;CAEA,UAAiB,UAAsB;EACrC,OAAO,KAAK,eAAe,UAAU,QAAQ;CAC/C;AACF"}
1
+ {"version":3,"file":"message-part-runtime.js","names":[],"sources":["../../../src/runtime/api/message-part-runtime.ts"],"sourcesContent":["import type {\n ThreadAssistantMessagePart,\n ThreadUserMessagePart,\n ToolCallMessagePartStatus,\n} from \"../../types/message\";\nimport type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { MessagePartStatus } from \"../../types/message\";\nimport type { SubscribableWithState } from \"../../subscribable/subscribable\";\nimport type { ThreadRuntimeCoreBinding } from \"./thread-runtime\";\nimport type { MessageStateBinding } from \"./bindings\";\nimport type { MessagePartRuntimePath } from \"./paths\";\nimport { ToolResponse } from \"assistant-stream\";\n\nexport type MessagePartState = (\n | ThreadUserMessagePart\n | ThreadAssistantMessagePart\n) & {\n readonly status: MessagePartStatus | ToolCallMessagePartStatus;\n};\n\ntype MessagePartSnapshotBinding = SubscribableWithState<\n MessagePartState,\n MessagePartRuntimePath\n>;\n\nexport type MessagePartRuntime = {\n addToolResult(result: any | ToolResponse<any>): void;\n resumeToolCall(payload: unknown): void;\n respondToToolApproval(response: { approved: boolean; reason?: string }): void;\n\n readonly path: MessagePartRuntimePath;\n getState(): MessagePartState;\n subscribe(callback: () => void): Unsubscribe;\n};\n\nexport class MessagePartRuntimeImpl implements MessagePartRuntime {\n public get path() {\n return this.contentBinding.path;\n }\n\n constructor(\n private contentBinding: MessagePartSnapshotBinding,\n private messageApi?: MessageStateBinding,\n private threadApi?: ThreadRuntimeCoreBinding,\n ) {\n this.__internal_bindMethods();\n }\n\n protected __internal_bindMethods() {\n this.addToolResult = this.addToolResult.bind(this);\n this.resumeToolCall = this.resumeToolCall.bind(this);\n this.respondToToolApproval = this.respondToToolApproval.bind(this);\n this.getState = this.getState.bind(this);\n this.subscribe = this.subscribe.bind(this);\n }\n\n public getState() {\n return this.contentBinding.getState();\n }\n\n public addToolResult(result: any | ToolResponse<any>) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to add tool result to non-tool message part\");\n\n if (!this.messageApi)\n throw new Error(\n \"Message API is not available. This is likely a bug in assistant-ui.\",\n );\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const message = this.messageApi.getState();\n if (!message) throw new Error(\"Message is not available\");\n\n const toolName = state.toolName;\n const toolCallId = state.toolCallId;\n\n const response = ToolResponse.toResponse(result);\n this.threadApi.getState().addToolResult({\n messageId: message.id,\n toolName,\n toolCallId,\n result: response.result,\n artifact: response.artifact,\n isError: response.isError,\n });\n }\n\n public resumeToolCall(payload: unknown) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\"Tried to resume tool call on non-tool message part\");\n\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n const toolCallId = state.toolCallId;\n this.threadApi.getState().resumeToolCall({\n toolCallId,\n payload,\n });\n }\n\n public respondToToolApproval(response: {\n approved: boolean;\n reason?: string;\n }) {\n const state = this.contentBinding.getState();\n if (!state) throw new Error(\"Message part is not available\");\n\n if (state.type !== \"tool-call\")\n throw new Error(\n \"Tried to respond to tool approval on non-tool message part\",\n );\n\n if (!state.approval || state.approval.approved !== undefined)\n throw new Error(\"Tool call has no pending approval\");\n\n if (!this.threadApi) throw new Error(\"Thread API is not available\");\n\n this.threadApi.getState().respondToToolApproval({\n approvalId: state.approval.id,\n approved: response.approved,\n ...(response.reason != null && { reason: response.reason }),\n });\n }\n\n public subscribe(callback: () => void) {\n return this.contentBinding.subscribe(callback);\n }\n}\n"],"mappings":";;AAmCA,IAAa,yBAAb,MAAkE;CAMtD;CACA;CACA;CAPV,IAAW,OAAO;EAChB,OAAO,KAAK,eAAe;CAC7B;CAEA,YACE,gBACA,YACA,WACA;EAHQ,KAAA,iBAAA;EACA,KAAA,aAAA;EACA,KAAA,YAAA;EAER,KAAK,uBAAuB;CAC9B;CAEA,yBAAmC;EACjC,KAAK,gBAAgB,KAAK,cAAc,KAAK,IAAI;EACjD,KAAK,iBAAiB,KAAK,eAAe,KAAK,IAAI;EACnD,KAAK,wBAAwB,KAAK,sBAAsB,KAAK,IAAI;EACjE,KAAK,WAAW,KAAK,SAAS,KAAK,IAAI;EACvC,KAAK,YAAY,KAAK,UAAU,KAAK,IAAI;CAC3C;CAEA,WAAkB;EAChB,OAAO,KAAK,eAAe,SAAS;CACtC;CAEA,cAAqB,QAAiC;EACpD,MAAM,QAAQ,KAAK,eAAe,SAAS;EAC3C,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,+BAA+B;EAE3D,IAAI,MAAM,SAAS,aACjB,MAAM,IAAI,MAAM,mDAAmD;EAErE,IAAI,CAAC,KAAK,YACR,MAAM,IAAI,MACR,qEACF;EACF,IAAI,CAAC,KAAK,WAAW,MAAM,IAAI,MAAM,6BAA6B;EAElE,MAAM,UAAU,KAAK,WAAW,SAAS;EACzC,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,0BAA0B;EAExD,MAAM,WAAW,MAAM;EACvB,MAAM,aAAa,MAAM;EAEzB,MAAM,WAAW,aAAa,WAAW,MAAM;EAC/C,KAAK,UAAU,SAAS,EAAE,cAAc;GACtC,WAAW,QAAQ;GACnB;GACA;GACA,QAAQ,SAAS;GACjB,UAAU,SAAS;GACnB,SAAS,SAAS;EACpB,CAAC;CACH;CAEA,eAAsB,SAAkB;EACtC,MAAM,QAAQ,KAAK,eAAe,SAAS;EAC3C,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,+BAA+B;EAE3D,IAAI,MAAM,SAAS,aACjB,MAAM,IAAI,MAAM,oDAAoD;EAEtE,IAAI,CAAC,KAAK,WAAW,MAAM,IAAI,MAAM,6BAA6B;EAElE,MAAM,aAAa,MAAM;EACzB,KAAK,UAAU,SAAS,EAAE,eAAe;GACvC;GACA;EACF,CAAC;CACH;CAEA,sBAA6B,UAG1B;EACD,MAAM,QAAQ,KAAK,eAAe,SAAS;EAC3C,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,+BAA+B;EAE3D,IAAI,MAAM,SAAS,aACjB,MAAM,IAAI,MACR,4DACF;EAEF,IAAI,CAAC,MAAM,YAAY,MAAM,SAAS,aAAa,KAAA,GACjD,MAAM,IAAI,MAAM,mCAAmC;EAErD,IAAI,CAAC,KAAK,WAAW,MAAM,IAAI,MAAM,6BAA6B;EAElE,KAAK,UAAU,SAAS,EAAE,sBAAsB;GAC9C,YAAY,MAAM,SAAS;GAC3B,UAAU,SAAS;GACnB,GAAI,SAAS,UAAU,QAAQ,EAAE,QAAQ,SAAS,OAAO;EAC3D,CAAC;CACH;CAEA,UAAiB,UAAsB;EACrC,OAAO,KAAK,eAAe,UAAU,QAAQ;CAC/C;AACF"}
@@ -7,7 +7,7 @@ import { ThreadMessageLike } from "../utils/thread-message-like.js";
7
7
  import { ExportedMessageRepository } from "../utils/message-repository.js";
8
8
  import { QuoteInfo } from "../../types/quote.js";
9
9
  import { ComposerRuntimeEventCallback, ComposerRuntimeEventType, DictationState, EditComposerRuntimeCore, SendOptions } from "../interfaces/composer-runtime-core.js";
10
- import { AddToolResultOptions, ResumeRunConfig, ResumeToolCallOptions, RuntimeCapabilities, SpeechState, StartRunConfig, SubmitFeedbackOptions, ThreadRuntimeCore, ThreadRuntimeEventCallback, ThreadRuntimeEventType, ThreadSuggestion, VoiceSessionState } from "../interfaces/thread-runtime-core.js";
10
+ import { AddToolResultOptions, RespondToToolApprovalOptions, ResumeRunConfig, ResumeToolCallOptions, RuntimeCapabilities, SpeechState, StartRunConfig, SubmitFeedbackOptions, ThreadRuntimeCore, ThreadRuntimeEventCallback, ThreadRuntimeEventType, ThreadSuggestion, VoiceSessionState } from "../interfaces/thread-runtime-core.js";
11
11
  import { ThreadListItemRuntimePath, ThreadRuntimePath } from "./paths.js";
12
12
  import { Subscribable, SubscribableWithState } from "../../subscribable/subscribable.js";
13
13
  import { ThreadListItemState } from "./bindings.js";
@@ -189,6 +189,7 @@ declare class ThreadRuntimeImpl implements ThreadRuntime {
189
189
  cancelRun: () => void;
190
190
  addToolResult: (options: AddToolResultOptions) => void;
191
191
  resumeToolCall: (options: ResumeToolCallOptions) => void;
192
+ respondToToolApproval: (options: RespondToToolApprovalOptions) => void;
192
193
  speak: (messageId: string) => void;
193
194
  stopSpeaking: () => void;
194
195
  connectVoice: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"thread-runtime.d.ts","names":[],"sources":["../../../src/runtime/api/thread-runtime.ts"],"mappings":"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"}
1
+ {"version":3,"file":"thread-runtime.d.ts","names":[],"sources":["../../../src/runtime/api/thread-runtime.ts"],"mappings":"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"}
@@ -7,7 +7,7 @@ import { RealtimeVoiceAdapter } from "../../adapters/voice.js";
7
7
  import { ModelContext, ModelContextProvider } from "../../model-context/types.js";
8
8
  import { ThreadMessageLike } from "../utils/thread-message-like.js";
9
9
  import { ExportedMessageRepository, MessageRepository } from "../utils/message-repository.js";
10
- import { AddToolResultOptions, ResumeRunConfig, ResumeToolCallOptions, RuntimeCapabilities, SpeechState, StartRunConfig, SubmitFeedbackOptions, ThreadRuntimeCore, ThreadRuntimeEventCallback, ThreadRuntimeEventPayload, ThreadRuntimeEventType, ThreadSuggestion, VoiceSessionState } from "../interfaces/thread-runtime-core.js";
10
+ import { AddToolResultOptions, RespondToToolApprovalOptions, ResumeRunConfig, ResumeToolCallOptions, RuntimeCapabilities, SpeechState, StartRunConfig, SubmitFeedbackOptions, ThreadRuntimeCore, ThreadRuntimeEventCallback, ThreadRuntimeEventPayload, ThreadRuntimeEventType, ThreadSuggestion, VoiceSessionState } from "../interfaces/thread-runtime-core.js";
11
11
  import { DefaultThreadComposerRuntimeCore } from "./default-thread-composer-runtime-core.js";
12
12
  import { DefaultEditComposerRuntimeCore } from "./default-edit-composer-runtime-core.js";
13
13
  //#region src/runtime/base/base-thread-runtime-core.d.ts
@@ -34,6 +34,7 @@ declare abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
34
34
  abstract resumeRun(config: ResumeRunConfig): void;
35
35
  abstract addToolResult(options: AddToolResultOptions): void;
36
36
  abstract resumeToolCall(options: ResumeToolCallOptions): void;
37
+ abstract respondToToolApproval(options: RespondToToolApprovalOptions): void;
37
38
  abstract cancelRun(): void;
38
39
  abstract exportExternalState(): any;
39
40
  abstract importExternalState(state: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"base-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/base-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;KAoCK,kBAAA;EACH,MAAA,GAAS,sBAAA;EACT,QAAA,GAAW,eAAA;EACX,WAAA,GAAc,iBAAA;EACd,KAAA,GAAQ,oBAAA;AAAA;AAAA,uBAGY,qBAAA,YAAiC,iBAAA;EAAA,iBAkExB,gBAAA;EAAA,QAjErB,cAAA;EAAA,QACA,cAAA;EAAA,mBAEW,UAAA,EAAU,iBAAA;EAAA,aACT,QAAA,CAAA,GAAY,kBAAA;EAAA,aACZ,UAAA,CAAA;EAAA,aACA,cAAA,CAAA;EAAA,aACA,SAAA,CAAA;EAAA,aACA,WAAA,CAAA,YAAwB,gBAAA;EAAA,aACxB,MAAA,CAAA;EAAA,aAEA,YAAA,CAAA,GAAgB,mBAAA;EAAA,SACpB,MAAA,CAAO,OAAA,EAAS,aAAA;EAAA,SAChB,QAAA,CAAS,MAAA,EAAQ,cAAA;EAAA,SACjB,SAAA,CAAU,MAAA,EAAQ,eAAA;EAAA,SAClB,aAAA,CAAc,OAAA,EAAS,oBAAA;EAAA,SACvB,cAAA,CAAe,OAAA,EAAS,qBAAA;EAAA,SACxB,SAAA,CAAA;EAAA,SACA,mBAAA,CAAA;EAAA,SACA,mBAAA,CAAoB,KAAA;EAAA,UAE1B,cAAA,EAAgB,aAAA;EAAA,UAChB,gBAAA;EAAA,QACF,qBAAA;EAAA,QACA,sBAAA;EAAA,QACA,iBAAA;EAAA,UAEE,uBAAA,CAAA;EAAA,UAKA,gBAAA,CAAA,YAA6B,aAAA;EAAA,IAI5B,QAAA,CAAA,YAAqB,aAAA;EAAA,IAgBrB,KAAA,CAAA,gEAAK,kBAAA,oCAAA,iBAAA;EAAA,SAWA,QAAA,EAAQ,gCAAA;cAEK,gBAAA,EAAkB,oBAAA;EAExC,eAAA,CAAA,GAF4D,YAAA;EAAA,QAM3D,cAAA;EACD,eAAA,CAAgB,SAAA,WAAiB,8BAAA;EAGjC,SAAA,CAAU,SAAA;EAeV,cAAA,CAAe,SAAA;;;;;EAsBf,WAAA,CAAY,SAAA;EAOZ,cAAA,CAAe,QAAA;EAAA,UAKZ,kBAAA,CAAA;EAIH,uBAAA,WAAkC,sBAAA,CAAA,CACvC,KAAA,EAAO,CAAA,EACP,OAAA,EAAS,yBAAA,CAA0B,CAAA;EAQ9B,SAAA,CAAU,QAAA,eAAuB,WAAA;EAKjC,cAAA,CAAA;IAAiB,SAAA;IAAW;EAAA,GAAQ,qBAAA;EAAA,QAqBnC,aAAA;EACD,MAAA,EAAQ,WAAA;EAER,KAAA,CAAM,SAAA;EA8BN,YAAA,CAAA;EAAA,QAMC,aAAA;EAAA,QACA,YAAA;EACD,KAAA,EAAO,iBAAA;EAAA,QAEN,YAAA;EAAA,QACA,uBAAA;EAED,cAAA;EAEA,oBAAA,GAAwB,QAAA,iBAAuB,WAAA;EAK/C,YAAA,CAAA;EAAA,QA+DC,oBAAA;EAAA,QAEA,sBAAA;EAAA,QA8DA,4BAAA;EAaD,eAAA,CAAA;EAeA,SAAA,CAAA;EAUA,WAAA,CAAA;EAAA,UAUG,iBAAA,CAAA;EAOH,MAAA,CAAA,GAAM,yBAAA;EAIN,MAAA,CAAO,IAAA,EAAM,yBAAA;EAOb,KAAA,CAAM,eAAA,YAA2B,iBAAA;EAAA,QAIhC,iBAAA;EAKD,WAAA,WAAsB,sBAAA,CAAA,CAC3B,KAAA,EAAO,CAAA,EACP,QAAA,EAAU,0BAAA,CAA2B,CAAA,IAAE,WAAA;AAAA"}
1
+ {"version":3,"file":"base-thread-runtime-core.d.ts","names":[],"sources":["../../../src/runtime/base/base-thread-runtime-core.ts"],"mappings":";;;;;;;;;;;;;KAqCK,kBAAA;EACH,MAAA,GAAS,sBAAA;EACT,QAAA,GAAW,eAAA;EACX,WAAA,GAAc,iBAAA;EACd,KAAA,GAAQ,oBAAA;AAAA;AAAA,uBAGY,qBAAA,YAAiC,iBAAA;EAAA,iBAqExB,gBAAA;EAAA,QApErB,cAAA;EAAA,QACA,cAAA;EAAA,mBAEW,UAAA,EAAU,iBAAA;EAAA,aACT,QAAA,CAAA,GAAY,kBAAA;EAAA,aACZ,UAAA,CAAA;EAAA,aACA,cAAA,CAAA;EAAA,aACA,SAAA,CAAA;EAAA,aACA,WAAA,CAAA,YAAwB,gBAAA;EAAA,aACxB,MAAA,CAAA;EAAA,aAEA,YAAA,CAAA,GAAgB,mBAAA;EAAA,SACpB,MAAA,CAAO,OAAA,EAAS,aAAA;EAAA,SAChB,QAAA,CAAS,MAAA,EAAQ,cAAA;EAAA,SACjB,SAAA,CAAU,MAAA,EAAQ,eAAA;EAAA,SAClB,aAAA,CAAc,OAAA,EAAS,oBAAA;EAAA,SACvB,cAAA,CAAe,OAAA,EAAS,qBAAA;EAAA,SACxB,qBAAA,CACd,OAAA,EAAS,4BAAA;EAAA,SAEK,SAAA,CAAA;EAAA,SACA,mBAAA,CAAA;EAAA,SACA,mBAAA,CAAoB,KAAA;EAAA,UAE1B,cAAA,EAAgB,aAAA;EAAA,UAChB,gBAAA;EAAA,QACF,qBAAA;EAAA,QACA,sBAAA;EAAA,QACA,iBAAA;EAAA,UAEE,uBAAA,CAAA;EAAA,UAKA,gBAAA,CAAA,YAA6B,aAAA;EAAA,IAI5B,QAAA,CAAA,YAAqB,aAAA;EAAA,IAgBrB,KAAA,CAAA,gEAAK,kBAAA,oCAAA,iBAAA;EAAA,SAWA,QAAA,EAAQ,gCAAA;cAEK,gBAAA,EAAkB,oBAAA;EAExC,eAAA,CAAA,GAF4D,YAAA;EAAA,QAM3D,cAAA;EACD,eAAA,CAAgB,SAAA,WAAiB,8BAAA;EAGjC,SAAA,CAAU,SAAA;EAeV,cAAA,CAAe,SAAA;;;;;EAsBf,WAAA,CAAY,SAAA;EAOZ,cAAA,CAAe,QAAA;EAAA,UAKZ,kBAAA,CAAA;EAIH,uBAAA,WAAkC,sBAAA,CAAA,CACvC,KAAA,EAAO,CAAA,EACP,OAAA,EAAS,yBAAA,CAA0B,CAAA;EAQ9B,SAAA,CAAU,QAAA,eAAuB,WAAA;EAKjC,cAAA,CAAA;IAAiB,SAAA;IAAW;EAAA,GAAQ,qBAAA;EAAA,QAqBnC,aAAA;EACD,MAAA,EAAQ,WAAA;EAER,KAAA,CAAM,SAAA;EA8BN,YAAA,CAAA;EAAA,QAMC,aAAA;EAAA,QACA,YAAA;EACD,KAAA,EAAO,iBAAA;EAAA,QAEN,YAAA;EAAA,QACA,uBAAA;EAED,cAAA;EAEA,oBAAA,GAAwB,QAAA,iBAAuB,WAAA;EAK/C,YAAA,CAAA;EAAA,QA+DC,oBAAA;EAAA,QAEA,sBAAA;EAAA,QA8DA,4BAAA;EAaD,eAAA,CAAA;EAeA,SAAA,CAAA;EAUA,WAAA,CAAA;EAAA,UAUG,iBAAA,CAAA;EAOH,MAAA,CAAA,GAAM,yBAAA;EAIN,MAAA,CAAO,IAAA,EAAM,yBAAA;EAOb,KAAA,CAAM,eAAA,YAA2B,iBAAA;EAAA,QAIhC,iBAAA;EAKD,WAAA,WAAsB,sBAAA,CAAA,CAC3B,KAAA,EAAO,CAAA,EACP,QAAA,EAAU,0BAAA,CAA2B,CAAA,IAAE,WAAA;AAAA"}