@assistant-ui/core 0.3.11 → 0.3.13

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 (132) hide show
  1. package/dist/index.d.ts +6 -5
  2. package/dist/index.js +2 -2
  3. package/dist/index.js.map +1 -1
  4. package/dist/internal.d.ts +6 -5
  5. package/dist/internal.js +5 -4
  6. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  7. package/dist/react/client/interactable-model-context.js +5 -1
  8. package/dist/react/client/interactable-model-context.js.map +1 -1
  9. package/dist/runtime/api/message-runtime.d.ts +2 -3
  10. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  11. package/dist/runtime/api/message-runtime.js +2 -16
  12. package/dist/runtime/api/message-runtime.js.map +1 -1
  13. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  14. package/dist/runtime/api/thread-runtime.js +5 -1
  15. package/dist/runtime/api/thread-runtime.js.map +1 -1
  16. package/dist/runtime/base/base-composer-runtime-core.d.ts +25 -0
  17. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  18. package/dist/runtime/base/base-composer-runtime-core.js +64 -11
  19. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  20. package/dist/runtime/base/base-thread-runtime-core.d.ts +14 -0
  21. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  22. package/dist/runtime/base/base-thread-runtime-core.js +31 -0
  23. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  24. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  25. package/dist/runtime/base/default-edit-composer-runtime-core.js +1 -6
  26. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  27. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  28. package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -4
  29. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  30. package/dist/runtime/internal.d.ts +4 -4
  31. package/dist/runtime/internal.js +4 -4
  32. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +15 -0
  33. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
  34. package/dist/runtime/queue/message-queue.js +23 -10
  35. package/dist/runtime/queue/message-queue.js.map +1 -1
  36. package/dist/runtimes/external-store/external-store-adapter.d.ts +7 -0
  37. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  38. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +3 -1
  39. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  40. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +49 -13
  41. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  42. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  43. package/dist/runtimes/local/local-thread-runtime-core.js +2 -1
  44. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  45. package/dist/store/clients/external-thread.d.ts +61 -0
  46. package/dist/store/clients/external-thread.d.ts.map +1 -0
  47. package/dist/store/clients/external-thread.js +1445 -0
  48. package/dist/store/clients/external-thread.js.map +1 -0
  49. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  50. package/dist/store/clients/runtime-adapter.js +5 -2
  51. package/dist/store/clients/runtime-adapter.js.map +1 -1
  52. package/dist/store/clients/single-thread-list.d.ts +9 -0
  53. package/dist/store/clients/single-thread-list.d.ts.map +1 -0
  54. package/dist/store/clients/single-thread-list.js +175 -0
  55. package/dist/store/clients/single-thread-list.js.map +1 -0
  56. package/dist/store/clients/suggestions.d.ts +3 -1
  57. package/dist/store/clients/suggestions.d.ts.map +1 -1
  58. package/dist/store/clients/suggestions.js +65 -37
  59. package/dist/store/clients/suggestions.js.map +1 -1
  60. package/dist/store/index.d.ts +5 -3
  61. package/dist/store/index.js +4 -2
  62. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  63. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +64 -50
  64. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  65. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  66. package/dist/store/runtime-clients/thread-runtime-client.js +98 -82
  67. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  68. package/dist/store/scope-registration.d.ts +2 -2
  69. package/dist/store/scopes/suggestions.d.ts +6 -1
  70. package/dist/store/scopes/suggestions.d.ts.map +1 -1
  71. package/dist/store/scopes/thread.d.ts +17 -0
  72. package/dist/store/scopes/thread.d.ts.map +1 -1
  73. package/dist/types/augmentations.d.ts +33 -0
  74. package/dist/types/augmentations.d.ts.map +1 -0
  75. package/dist/types/augmentations.js +0 -0
  76. package/dist/types/error.d.ts +15 -1
  77. package/dist/types/error.d.ts.map +1 -1
  78. package/dist/types/error.js +18 -1
  79. package/dist/types/error.js.map +1 -1
  80. package/dist/types/message.d.ts +2 -0
  81. package/dist/types/message.d.ts.map +1 -1
  82. package/dist/types/message.js.map +1 -1
  83. package/dist/utils/normalizePartStatus.d.ts +3 -2
  84. package/dist/utils/normalizePartStatus.d.ts.map +1 -1
  85. package/dist/utils/normalizePartStatus.js +15 -1
  86. package/dist/utils/normalizePartStatus.js.map +1 -1
  87. package/package.json +5 -5
  88. package/src/index.ts +7 -0
  89. package/src/internal.ts +1 -1
  90. package/src/react/client/interactable-model-context.ts +6 -1
  91. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +114 -0
  92. package/src/runtime/api/message-runtime.test.ts +1 -1
  93. package/src/runtime/api/message-runtime.ts +2 -35
  94. package/src/runtime/api/thread-runtime.ts +8 -1
  95. package/src/runtime/base/base-composer-runtime-core.ts +100 -8
  96. package/src/runtime/base/base-thread-runtime-core.ts +36 -0
  97. package/src/runtime/base/default-edit-composer-runtime-core.ts +1 -15
  98. package/src/runtime/base/default-thread-composer-runtime-core.ts +1 -11
  99. package/src/runtime/queue/external-thread-queue-adapter.ts +17 -0
  100. package/src/runtime/queue/message-queue.ts +26 -9
  101. package/src/runtimes/external-store/external-store-adapter.ts +7 -0
  102. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +100 -26
  103. package/src/runtimes/local/local-thread-runtime-core.ts +4 -1
  104. package/src/store/clients/external-thread.ts +1255 -0
  105. package/src/store/clients/runtime-adapter.ts +5 -2
  106. package/src/store/clients/single-thread-list.ts +116 -0
  107. package/src/store/clients/suggestions.ts +39 -13
  108. package/src/store/index.ts +6 -0
  109. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +13 -28
  110. package/src/store/runtime-clients/thread-runtime-client.ts +5 -0
  111. package/src/store/scopes/suggestions.ts +6 -0
  112. package/src/store/scopes/thread.ts +17 -0
  113. package/src/tests/append-interactable-snapshots.test.ts +350 -0
  114. package/src/tests/base-composer-runtime-core-send.test.ts +126 -0
  115. package/src/tests/base-composer-runtime-core.test.ts +108 -1
  116. package/src/tests/default-edit-composer-runtime-core.test.ts +0 -68
  117. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +300 -0
  118. package/src/tests/external-thread-attachments.test.tsx +584 -0
  119. package/src/tests/external-thread-branches.test.tsx +157 -0
  120. package/src/tests/external-thread-feedback.test.tsx +204 -0
  121. package/src/tests/external-thread-parity.test.tsx +548 -0
  122. package/src/tests/external-thread-refetch.test.tsx +117 -0
  123. package/src/tests/external-thread-speech.test.tsx +328 -0
  124. package/src/tests/external-thread-suggestions.test.tsx +59 -0
  125. package/src/tests/message-queue.test.ts +26 -0
  126. package/src/tests/thread-message-like.test.ts +39 -0
  127. package/src/tests/thread-switch-events.test.tsx +136 -0
  128. package/src/types/augmentations.ts +33 -0
  129. package/src/types/error.ts +24 -0
  130. package/src/types/message.ts +2 -0
  131. package/src/utils/normalizePartStatus.ts +27 -0
  132. package/src/tests/default-thread-composer-runtime-core.test.ts +0 -82
@@ -0,0 +1,1445 @@
1
+ import { fileMatchesAccept } from "../../adapters/attachment.js";
2
+ import { getThreadMessageText } from "../../utils/text.js";
3
+ import { toMessagePartStatus } from "../../utils/normalizePartStatus.js";
4
+ import { resolveToolApprovalResponse } from "../../runtime/utils/resolveToolApprovalResponse.js";
5
+ import { isCreateAttachment } from "../../types/attachment.js";
6
+ import { ThreadSuggestions } from "./suggestions.js";
7
+ import { ModelContext } from "./model-context-client.js";
8
+ import { DataRenderers } from "../../react/client/DataRenderers.js";
9
+ import { Tools } from "../../react/client/Tools.js";
10
+ import { SingleThreadList } from "./single-thread-list.js";
11
+ import { ToolResponse } from "assistant-stream";
12
+ import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
13
+ import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
14
+ import { resource, withKey } from "@assistant-ui/tap";
15
+ import { Derived, attachTransformScopes, useClientLookup, useClientResource } from "@assistant-ui/store/client";
16
+ //#region src/store/clients/external-thread.ts
17
+ const EMPTY_QUEUE_ITEMS = [];
18
+ const EMPTY_BRANCH_IDS = [];
19
+ const EMPTY_SUGGESTIONS = [];
20
+ const COMPLETE_STATUS = Object.freeze({ type: "complete" });
21
+ const derivePartStatus = (message, partIndex, part) => {
22
+ if (!message.status) return COMPLETE_STATUS;
23
+ return toMessagePartStatus(message, partIndex, part);
24
+ };
25
+ const useMessageClient = (t0) => {
26
+ const $ = c(71);
27
+ const { message, index, parentId, onEdit, onReload, queue, branches, onRespondToToolApproval, onAddToolResult, onResumeToolCall, attachmentAdapter, submittedFeedback, onSubmitFeedback, speech, onSpeak, onStopSpeaking } = t0;
28
+ const [isCopied, setIsCopied] = useState(false);
29
+ const [isHovering, setIsHovering] = useState(false);
30
+ let t1;
31
+ if ($[0] !== message || $[1] !== onAddToolResult || $[2] !== onRespondToToolApproval || $[3] !== onResumeToolCall) {
32
+ t1 = message.content.map((part, idx) => withKey(idx, PartResource({
33
+ part,
34
+ status: derivePartStatus(message, idx, part),
35
+ messageId: message.id,
36
+ onRespondToToolApproval,
37
+ onAddToolResult,
38
+ onResumeToolCall
39
+ })));
40
+ $[0] = message;
41
+ $[1] = onAddToolResult;
42
+ $[2] = onRespondToToolApproval;
43
+ $[3] = onResumeToolCall;
44
+ $[4] = t1;
45
+ } else t1 = $[4];
46
+ const partClients = useClientLookup(t1);
47
+ let t2;
48
+ if ($[5] !== message.attachments) {
49
+ t2 = message.attachments ?? [];
50
+ $[5] = message.attachments;
51
+ $[6] = t2;
52
+ } else t2 = $[6];
53
+ let t3;
54
+ if ($[7] !== t2) {
55
+ t3 = t2.map(_temp2);
56
+ $[7] = t2;
57
+ $[8] = t3;
58
+ } else t3 = $[8];
59
+ const attachmentClients = useClientLookup(t3);
60
+ let t4;
61
+ if ($[9] !== onEdit) {
62
+ t4 = () => {
63
+ if (!onEdit) throw new Error("Runtime does not support editing.");
64
+ };
65
+ $[9] = onEdit;
66
+ $[10] = t4;
67
+ } else t4 = $[10];
68
+ const handleBeginEdit = t4;
69
+ let t5;
70
+ if ($[11] !== message.id || $[12] !== onEdit || $[13] !== parentId) {
71
+ t5 = (msg) => {
72
+ if (!onEdit) throw new Error("Runtime does not support editing.");
73
+ onEdit({
74
+ ...msg,
75
+ parentId,
76
+ sourceId: message.id
77
+ });
78
+ };
79
+ $[11] = message.id;
80
+ $[12] = onEdit;
81
+ $[13] = parentId;
82
+ $[14] = t5;
83
+ } else t5 = $[14];
84
+ const handleSendEdit = t5;
85
+ let t6;
86
+ if ($[15] !== attachmentAdapter || $[16] !== handleBeginEdit || $[17] !== handleSendEdit || $[18] !== message || $[19] !== queue) {
87
+ t6 = ComposerClientResource({
88
+ type: "edit",
89
+ canCancel: true,
90
+ onBeginEdit: handleBeginEdit,
91
+ onSend: handleSendEdit,
92
+ message,
93
+ queue,
94
+ attachmentAdapter
95
+ });
96
+ $[15] = attachmentAdapter;
97
+ $[16] = handleBeginEdit;
98
+ $[17] = handleSendEdit;
99
+ $[18] = message;
100
+ $[19] = queue;
101
+ $[20] = t6;
102
+ } else t6 = $[20];
103
+ const composerClient = useClientResource(t6);
104
+ let branchIds;
105
+ let t7;
106
+ if ($[21] !== branches || $[22] !== message.id) {
107
+ branchIds = branches?.getBranches(message.id) ?? EMPTY_BRANCH_IDS;
108
+ t7 = branchIds.indexOf(message.id);
109
+ $[21] = branches;
110
+ $[22] = message.id;
111
+ $[23] = branchIds;
112
+ $[24] = t7;
113
+ } else {
114
+ branchIds = $[23];
115
+ t7 = $[24];
116
+ }
117
+ const branchIndex = t7;
118
+ const branchNumber = branchIndex === -1 ? 1 : branchIndex + 1;
119
+ const branchCount = branchIndex === -1 ? 1 : branchIds.length;
120
+ let t8;
121
+ if ($[25] !== message || $[26] !== submittedFeedback) {
122
+ t8 = submittedFeedback && message.role === "assistant" ? {
123
+ ...message,
124
+ metadata: {
125
+ ...message.metadata,
126
+ submittedFeedback: { type: submittedFeedback }
127
+ }
128
+ } : message;
129
+ $[25] = message;
130
+ $[26] = submittedFeedback;
131
+ $[27] = t8;
132
+ } else t8 = $[27];
133
+ const messageWithFeedback = t8;
134
+ let t9;
135
+ if ($[28] !== message.attachments) {
136
+ t9 = message.attachments ?? [];
137
+ $[28] = message.attachments;
138
+ $[29] = t9;
139
+ } else t9 = $[29];
140
+ let t10;
141
+ if ($[30] !== branchCount || $[31] !== branchNumber || $[32] !== composerClient.state || $[33] !== index || $[34] !== isCopied || $[35] !== isHovering || $[36] !== messageWithFeedback || $[37] !== parentId || $[38] !== partClients.state || $[39] !== speech || $[40] !== t9) {
142
+ t10 = {
143
+ ...messageWithFeedback,
144
+ attachments: t9,
145
+ parentId,
146
+ isLast: false,
147
+ branchNumber,
148
+ branchCount,
149
+ speech,
150
+ parts: partClients.state,
151
+ isCopied,
152
+ isHovering,
153
+ index,
154
+ composer: composerClient.state
155
+ };
156
+ $[30] = branchCount;
157
+ $[31] = branchNumber;
158
+ $[32] = composerClient.state;
159
+ $[33] = index;
160
+ $[34] = isCopied;
161
+ $[35] = isHovering;
162
+ $[36] = messageWithFeedback;
163
+ $[37] = parentId;
164
+ $[38] = partClients.state;
165
+ $[39] = speech;
166
+ $[40] = t9;
167
+ $[41] = t10;
168
+ } else t10 = $[41];
169
+ const state = t10;
170
+ let t11;
171
+ if ($[42] !== state) {
172
+ t11 = () => state;
173
+ $[42] = state;
174
+ $[43] = t11;
175
+ } else t11 = $[43];
176
+ let t12;
177
+ if ($[44] !== composerClient.methods) {
178
+ t12 = () => composerClient.methods;
179
+ $[44] = composerClient.methods;
180
+ $[45] = t12;
181
+ } else t12 = $[45];
182
+ let t13;
183
+ if ($[46] !== onReload) {
184
+ t13 = () => {
185
+ onReload?.();
186
+ };
187
+ $[46] = onReload;
188
+ $[47] = t13;
189
+ } else t13 = $[47];
190
+ let t14;
191
+ if ($[48] !== branchIds || $[49] !== branchIndex || $[50] !== branches || $[51] !== message.id) {
192
+ t14 = (t15) => {
193
+ const { position, branchId } = t15;
194
+ if (!branches) return;
195
+ const target = branchId ?? (branchIndex === -1 ? void 0 : position === "previous" ? branchIds[branchIndex - 1] : position === "next" ? branchIds[branchIndex + 1] : void 0);
196
+ if (target !== void 0 && target !== message.id) branches.switchToBranch(target);
197
+ };
198
+ $[48] = branchIds;
199
+ $[49] = branchIndex;
200
+ $[50] = branches;
201
+ $[51] = message.id;
202
+ $[52] = t14;
203
+ } else t14 = $[52];
204
+ let t15;
205
+ if ($[53] !== message) {
206
+ t15 = () => getThreadMessageText(message);
207
+ $[53] = message;
208
+ $[54] = t15;
209
+ } else t15 = $[54];
210
+ let t16;
211
+ if ($[55] !== partClients || $[56] !== state) {
212
+ t16 = (selector) => {
213
+ if ("index" in selector) return partClients.get(selector);
214
+ const partIndex = state.parts.findIndex((p) => p.type === "tool-call" && p.toolCallId === selector.toolCallId);
215
+ return partClients.get({ index: partIndex });
216
+ };
217
+ $[55] = partClients;
218
+ $[56] = state;
219
+ $[57] = t16;
220
+ } else t16 = $[57];
221
+ let t17;
222
+ if ($[58] !== attachmentClients) {
223
+ t17 = (selector_0) => {
224
+ if ("id" in selector_0) return attachmentClients.get({ key: selector_0.id });
225
+ return attachmentClients.get(selector_0);
226
+ };
227
+ $[58] = attachmentClients;
228
+ $[59] = t17;
229
+ } else t17 = $[59];
230
+ let t18;
231
+ if ($[60] !== onSpeak || $[61] !== onStopSpeaking || $[62] !== onSubmitFeedback || $[63] !== t11 || $[64] !== t12 || $[65] !== t13 || $[66] !== t14 || $[67] !== t15 || $[68] !== t16 || $[69] !== t17) {
232
+ t18 = {
233
+ getState: t11,
234
+ composer: t12,
235
+ delete: _temp3,
236
+ reload: t13,
237
+ speak: onSpeak,
238
+ stopSpeaking: onStopSpeaking,
239
+ submitFeedback: onSubmitFeedback,
240
+ switchToBranch: t14,
241
+ getCopyText: t15,
242
+ part: t16,
243
+ attachment: t17,
244
+ setIsCopied,
245
+ setIsHovering
246
+ };
247
+ $[60] = onSpeak;
248
+ $[61] = onStopSpeaking;
249
+ $[62] = onSubmitFeedback;
250
+ $[63] = t11;
251
+ $[64] = t12;
252
+ $[65] = t13;
253
+ $[66] = t14;
254
+ $[67] = t15;
255
+ $[68] = t16;
256
+ $[69] = t17;
257
+ $[70] = t18;
258
+ } else t18 = $[70];
259
+ return t18;
260
+ };
261
+ const MessageClient = resource(useMessageClient);
262
+ const usePartResource = (t0) => {
263
+ const $ = c(20);
264
+ const { part, status, messageId, onRespondToToolApproval, onAddToolResult, onResumeToolCall } = t0;
265
+ const t1 = status;
266
+ let t2;
267
+ if ($[0] !== part || $[1] !== t1) {
268
+ t2 = {
269
+ ...part,
270
+ status: t1
271
+ };
272
+ $[0] = part;
273
+ $[1] = t1;
274
+ $[2] = t2;
275
+ } else t2 = $[2];
276
+ const state = t2;
277
+ let t3;
278
+ if ($[3] !== state) {
279
+ t3 = () => state;
280
+ $[3] = state;
281
+ $[4] = t3;
282
+ } else t3 = $[4];
283
+ let t4;
284
+ if ($[5] !== messageId || $[6] !== onAddToolResult || $[7] !== part) {
285
+ t4 = (result) => {
286
+ if (!onAddToolResult) throw new Error("Runtime does not support tool results (onAddToolResult is not set).");
287
+ if (part.type !== "tool-call") throw new Error("Tried to add tool result on non-tool message part");
288
+ const response = ToolResponse.toResponse(result);
289
+ onAddToolResult({
290
+ messageId,
291
+ toolName: part.toolName,
292
+ toolCallId: part.toolCallId,
293
+ result: response.result,
294
+ isError: response.isError,
295
+ ...response.artifact !== void 0 && { artifact: response.artifact },
296
+ ...response.modelContent !== void 0 && { modelContent: response.modelContent }
297
+ });
298
+ };
299
+ $[5] = messageId;
300
+ $[6] = onAddToolResult;
301
+ $[7] = part;
302
+ $[8] = t4;
303
+ } else t4 = $[8];
304
+ let t5;
305
+ if ($[9] !== onResumeToolCall || $[10] !== part) {
306
+ t5 = (payload) => {
307
+ if (!onResumeToolCall) throw new Error("Runtime does not support resuming tool calls (onResumeToolCall is not set).");
308
+ if (part.type !== "tool-call") throw new Error("Tried to resume tool call on non-tool message part");
309
+ onResumeToolCall({
310
+ toolCallId: part.toolCallId,
311
+ payload
312
+ });
313
+ };
314
+ $[9] = onResumeToolCall;
315
+ $[10] = part;
316
+ $[11] = t5;
317
+ } else t5 = $[11];
318
+ let t6;
319
+ if ($[12] !== onRespondToToolApproval || $[13] !== part) {
320
+ t6 = (response_0) => {
321
+ if (!onRespondToToolApproval) throw new Error("Runtime does not support tool approvals.");
322
+ if (part.type !== "tool-call") throw new Error("Tried to respond to tool approval on non-tool message part");
323
+ if (!part.approval || part.approval.approved !== void 0 || part.approval.resolution !== void 0) throw new Error("Tool call has no pending approval");
324
+ onRespondToToolApproval(resolveToolApprovalResponse(part.approval, response_0));
325
+ };
326
+ $[12] = onRespondToToolApproval;
327
+ $[13] = part;
328
+ $[14] = t6;
329
+ } else t6 = $[14];
330
+ let t7;
331
+ if ($[15] !== t3 || $[16] !== t4 || $[17] !== t5 || $[18] !== t6) {
332
+ t7 = {
333
+ getState: t3,
334
+ addToolResult: t4,
335
+ resumeToolCall: t5,
336
+ respondToToolApproval: t6
337
+ };
338
+ $[15] = t3;
339
+ $[16] = t4;
340
+ $[17] = t5;
341
+ $[18] = t6;
342
+ $[19] = t7;
343
+ } else t7 = $[19];
344
+ return t7;
345
+ };
346
+ const PartResource = resource(usePartResource);
347
+ const useAttachmentResource = ({ attachment, onRemove }) => {
348
+ return {
349
+ getState: () => attachment,
350
+ remove: async () => {
351
+ await onRemove?.();
352
+ }
353
+ };
354
+ };
355
+ const AttachmentResource = resource(useAttachmentResource);
356
+ var AttachmentAddOperations = class {
357
+ operations = /* @__PURE__ */ new Set();
358
+ start() {
359
+ const operation = {
360
+ cancelled: false,
361
+ attachmentIds: /* @__PURE__ */ new Set()
362
+ };
363
+ this.operations.add(operation);
364
+ return operation;
365
+ }
366
+ accept(operation, attachmentId) {
367
+ if (operation.cancelled) return false;
368
+ operation.attachmentIds.add(attachmentId);
369
+ return true;
370
+ }
371
+ finish(operation) {
372
+ this.operations.delete(operation);
373
+ }
374
+ isCancelled(operation) {
375
+ return operation.cancelled;
376
+ }
377
+ cancel(attachmentId) {
378
+ for (const operation of [...this.operations]) {
379
+ if (!operation.attachmentIds.has(attachmentId)) continue;
380
+ operation.cancelled = true;
381
+ this.operations.delete(operation);
382
+ }
383
+ }
384
+ cancelAll() {
385
+ for (const operation of this.operations) operation.cancelled = true;
386
+ this.operations.clear();
387
+ }
388
+ };
389
+ const useQueueItemClient = ({ item, onMove, onRemove }) => {
390
+ return {
391
+ getState: () => item,
392
+ steer: () => onMove({
393
+ lane: "steer",
394
+ insertAfter: null
395
+ }),
396
+ move: onMove,
397
+ remove: onRemove
398
+ };
399
+ };
400
+ const QueueItemClient = resource(useQueueItemClient);
401
+ const drainAdapterAdd = async (result, upsert) => {
402
+ if (Symbol.asyncIterator in result) {
403
+ for await (const attachment of result) if (!upsert(attachment)) break;
404
+ } else upsert(await result);
405
+ };
406
+ const useLiveState = (initial) => {
407
+ const $ = c(3);
408
+ const [state, setState] = useState(initial);
409
+ const ref = useRef(state);
410
+ let t0;
411
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
412
+ t0 = (next) => {
413
+ ref.current = typeof next === "function" ? next(ref.current) : next;
414
+ setState(ref.current);
415
+ };
416
+ $[0] = t0;
417
+ } else t0 = $[0];
418
+ const set = t0;
419
+ let t1;
420
+ if ($[1] !== state) {
421
+ t1 = [
422
+ state,
423
+ set,
424
+ ref
425
+ ];
426
+ $[1] = state;
427
+ $[2] = t1;
428
+ } else t1 = $[2];
429
+ return t1;
430
+ };
431
+ const useComposerClientResource = (t0) => {
432
+ const $ = c(105);
433
+ const { type, canCancel, isRunning: t1, isSendDisabled: t2, onCancel, onBeginEdit, onSend, message, queue, attachmentAdapter } = t0;
434
+ const isRunning = t1 === void 0 ? false : t1;
435
+ const isSendDisabled = t2 === void 0 ? false : t2;
436
+ const [isEditing, setIsEditing, isEditingRef] = useLiveState(type === "thread");
437
+ const [text, setText, textRef] = useLiveState("");
438
+ const [role, setRole, roleRef] = useLiveState("user");
439
+ let t3;
440
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
441
+ t3 = {};
442
+ $[0] = t3;
443
+ } else t3 = $[0];
444
+ const [runConfig, setRunConfig, runConfigRef] = useLiveState(t3);
445
+ let t4;
446
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
447
+ t4 = [];
448
+ $[1] = t4;
449
+ } else t4 = $[1];
450
+ const [attachments, setAttachments, attachmentsRef] = useLiveState(t4);
451
+ const [quote, setQuote, quoteRef] = useLiveState(void 0);
452
+ let t5;
453
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
454
+ t5 = new AttachmentAddOperations();
455
+ $[2] = t5;
456
+ } else t5 = $[2];
457
+ const attachmentAddOperations = t5;
458
+ let t6;
459
+ if ($[3] !== message || $[4] !== setAttachments || $[5] !== setRole || $[6] !== setText) {
460
+ t6 = () => {
461
+ if (!message) return;
462
+ const messageText = message.content.filter(_temp4).map(_temp5).join("\n\n");
463
+ setText(messageText);
464
+ setRole(message.role);
465
+ setAttachments(message.attachments ?? []);
466
+ };
467
+ $[3] = message;
468
+ $[4] = setAttachments;
469
+ $[5] = setRole;
470
+ $[6] = setText;
471
+ $[7] = t6;
472
+ } else t6 = $[7];
473
+ const updateFromMessage = t6;
474
+ let t7;
475
+ if ($[8] !== attachmentAdapter || $[9] !== attachments || $[10] !== setAttachments) {
476
+ let t8;
477
+ if ($[12] !== attachmentAdapter || $[13] !== setAttachments) {
478
+ t8 = (attachment) => withKey(attachment.id, AttachmentResource({
479
+ attachment,
480
+ onRemove: async () => {
481
+ attachmentAddOperations.cancel(attachment.id);
482
+ await attachmentAdapter?.remove(attachment);
483
+ setAttachments((prev) => prev.filter((a) => a.id !== attachment.id));
484
+ }
485
+ }));
486
+ $[12] = attachmentAdapter;
487
+ $[13] = setAttachments;
488
+ $[14] = t8;
489
+ } else t8 = $[14];
490
+ t7 = attachments.map(t8);
491
+ $[8] = attachmentAdapter;
492
+ $[9] = attachments;
493
+ $[10] = setAttachments;
494
+ $[11] = t7;
495
+ } else t7 = $[11];
496
+ const attachmentClients = useClientLookup(t7);
497
+ let t8;
498
+ if ($[15] !== attachmentAdapter) {
499
+ t8 = async (removed) => {
500
+ if (!attachmentAdapter) return;
501
+ await Promise.all(removed.filter(_temp6).map((a_1) => attachmentAdapter.remove(a_1)));
502
+ };
503
+ $[15] = attachmentAdapter;
504
+ $[16] = t8;
505
+ } else t8 = $[16];
506
+ const removePendingAttachments = t8;
507
+ let t9;
508
+ if ($[17] !== setAttachments) {
509
+ t9 = (attachment_0) => {
510
+ setAttachments((prev_0) => {
511
+ const idx = prev_0.findIndex((a_2) => a_2.id === attachment_0.id);
512
+ if (idx === -1) return [...prev_0, attachment_0];
513
+ const next = [...prev_0];
514
+ next[idx] = attachment_0;
515
+ return next;
516
+ });
517
+ };
518
+ $[17] = setAttachments;
519
+ $[18] = t9;
520
+ } else t9 = $[18];
521
+ const upsertAttachment = t9;
522
+ const steerItems = queue?.steerItems ?? EMPTY_QUEUE_ITEMS;
523
+ const laneItems = queue?.items ?? EMPTY_QUEUE_ITEMS;
524
+ let t10;
525
+ if ($[19] !== laneItems || $[20] !== steerItems) {
526
+ t10 = steerItems.length === 0 ? laneItems : laneItems.length === 0 ? steerItems : [...steerItems, ...laneItems];
527
+ $[19] = laneItems;
528
+ $[20] = steerItems;
529
+ $[21] = t10;
530
+ } else t10 = $[21];
531
+ const queueItems = t10;
532
+ let t11;
533
+ if ($[22] !== queue || $[23] !== queueItems) {
534
+ let t12;
535
+ if ($[25] !== queue) {
536
+ t12 = (item) => withKey(item.id, QueueItemClient({
537
+ item,
538
+ onMove: (placement) => queue?.move(item.id, placement),
539
+ onRemove: () => queue?.remove(item.id)
540
+ }));
541
+ $[25] = queue;
542
+ $[26] = t12;
543
+ } else t12 = $[26];
544
+ t11 = queueItems.map(t12);
545
+ $[22] = queue;
546
+ $[23] = queueItems;
547
+ $[24] = t11;
548
+ } else t11 = $[24];
549
+ const queueItemClients = useClientLookup(t11);
550
+ let t12;
551
+ if ($[27] !== attachmentAdapter?.accept || $[28] !== attachmentClients.state || $[29] !== attachments.length || $[30] !== canCancel || $[31] !== isEditing || $[32] !== isSendDisabled || $[33] !== queueItems || $[34] !== quote || $[35] !== role || $[36] !== runConfig || $[37] !== text || $[38] !== type) {
552
+ t12 = () => {
553
+ const isEmpty = !text.trim() && !attachments.length;
554
+ return {
555
+ text,
556
+ role,
557
+ attachments: attachmentClients.state,
558
+ runConfig,
559
+ isEditing,
560
+ canCancel,
561
+ canSend: isEditing && !isEmpty && !isSendDisabled,
562
+ attachmentAccept: attachmentAdapter?.accept ?? "*",
563
+ isEmpty,
564
+ type,
565
+ dictation: void 0,
566
+ quote,
567
+ queue: queueItems
568
+ };
569
+ };
570
+ $[27] = attachmentAdapter?.accept;
571
+ $[28] = attachmentClients.state;
572
+ $[29] = attachments.length;
573
+ $[30] = canCancel;
574
+ $[31] = isEditing;
575
+ $[32] = isSendDisabled;
576
+ $[33] = queueItems;
577
+ $[34] = quote;
578
+ $[35] = role;
579
+ $[36] = runConfig;
580
+ $[37] = text;
581
+ $[38] = type;
582
+ $[39] = t12;
583
+ } else t12 = $[39];
584
+ attachmentAdapter?.accept;
585
+ let t13;
586
+ if ($[40] !== t12) {
587
+ t13 = t12();
588
+ $[40] = t12;
589
+ $[41] = t13;
590
+ } else t13 = $[41];
591
+ const state = t13;
592
+ let t14;
593
+ if ($[42] !== state) {
594
+ t14 = () => state;
595
+ $[42] = state;
596
+ $[43] = t14;
597
+ } else t14 = $[43];
598
+ let t15;
599
+ if ($[44] !== attachmentAdapter || $[45] !== setAttachments || $[46] !== upsertAttachment) {
600
+ t15 = async (fileOrAttachment) => {
601
+ if (attachmentAdapter) {
602
+ const file = isCreateAttachment(fileOrAttachment) ? {
603
+ name: fileOrAttachment.name,
604
+ type: fileOrAttachment.contentType ?? ""
605
+ } : {
606
+ name: fileOrAttachment.name,
607
+ type: fileOrAttachment.type
608
+ };
609
+ if (!fileMatchesAccept(file, attachmentAdapter.accept)) throw new Error(`File type ${file.type || "unknown"} is not accepted. Accepted types: ${attachmentAdapter.accept}`);
610
+ }
611
+ if (!isCreateAttachment(fileOrAttachment) && attachmentAdapter) {
612
+ const operation = attachmentAddOperations.start();
613
+ try {
614
+ await drainAdapterAdd(attachmentAdapter.add({ file: fileOrAttachment }), (attachment_1) => {
615
+ if (!attachmentAddOperations.accept(operation, attachment_1.id)) return false;
616
+ upsertAttachment(attachment_1);
617
+ return true;
618
+ });
619
+ attachmentAddOperations.finish(operation);
620
+ } catch (t16) {
621
+ const error = t16;
622
+ attachmentAddOperations.finish(operation);
623
+ if (!attachmentAddOperations.isCancelled(operation)) throw error;
624
+ }
625
+ } else if (!isCreateAttachment(fileOrAttachment)) {
626
+ const newAttachment = {
627
+ id: Math.random().toString(36).substring(7),
628
+ type: "file",
629
+ name: fileOrAttachment.name,
630
+ contentType: fileOrAttachment.type,
631
+ file: fileOrAttachment,
632
+ status: { type: "complete" },
633
+ content: []
634
+ };
635
+ setAttachments((prev_1) => [...prev_1, newAttachment]);
636
+ } else {
637
+ const newAttachment_0 = {
638
+ id: fileOrAttachment.id ?? Math.random().toString(36).substring(7),
639
+ type: fileOrAttachment.type ?? "document",
640
+ name: fileOrAttachment.name,
641
+ contentType: fileOrAttachment.contentType,
642
+ content: fileOrAttachment.content,
643
+ status: { type: "complete" }
644
+ };
645
+ setAttachments((prev_2) => [...prev_2, newAttachment_0]);
646
+ }
647
+ };
648
+ $[44] = attachmentAdapter;
649
+ $[45] = setAttachments;
650
+ $[46] = upsertAttachment;
651
+ $[47] = t15;
652
+ } else t15 = $[47];
653
+ let t16;
654
+ if ($[48] !== attachmentsRef || $[49] !== removePendingAttachments || $[50] !== setAttachments) {
655
+ t16 = async () => {
656
+ attachmentAddOperations.cancelAll();
657
+ const removed_0 = attachmentsRef.current;
658
+ setAttachments([]);
659
+ await removePendingAttachments(removed_0);
660
+ };
661
+ $[48] = attachmentsRef;
662
+ $[49] = removePendingAttachments;
663
+ $[50] = setAttachments;
664
+ $[51] = t16;
665
+ } else t16 = $[51];
666
+ let t17;
667
+ if ($[52] !== attachmentClients) {
668
+ t17 = (selector) => {
669
+ if ("id" in selector) return attachmentClients.get({ key: selector.id });
670
+ return attachmentClients.get(selector);
671
+ };
672
+ $[52] = attachmentClients;
673
+ $[53] = t17;
674
+ } else t17 = $[53];
675
+ let t18;
676
+ if ($[54] !== attachmentsRef || $[55] !== removePendingAttachments || $[56] !== setAttachments || $[57] !== setQuote || $[58] !== setRole || $[59] !== setRunConfig || $[60] !== setText) {
677
+ t18 = async () => {
678
+ attachmentAddOperations.cancelAll();
679
+ const removed_1 = attachmentsRef.current;
680
+ setText("");
681
+ setRole("user");
682
+ setRunConfig({});
683
+ setAttachments([]);
684
+ setQuote(void 0);
685
+ await removePendingAttachments(removed_1);
686
+ };
687
+ $[54] = attachmentsRef;
688
+ $[55] = removePendingAttachments;
689
+ $[56] = setAttachments;
690
+ $[57] = setQuote;
691
+ $[58] = setRole;
692
+ $[59] = setRunConfig;
693
+ $[60] = setText;
694
+ $[61] = t18;
695
+ } else t18 = $[61];
696
+ let t19;
697
+ if ($[62] !== attachmentAdapter || $[63] !== attachmentsRef || $[64] !== isEditingRef || $[65] !== isRunning || $[66] !== isSendDisabled || $[67] !== onSend || $[68] !== queue || $[69] !== quoteRef || $[70] !== roleRef || $[71] !== runConfigRef || $[72] !== setAttachments || $[73] !== setIsEditing || $[74] !== setQuote || $[75] !== setText || $[76] !== textRef || $[77] !== type) {
698
+ t19 = (opts) => {
699
+ const currentQuote = quoteRef.current;
700
+ const currentText = textRef.current;
701
+ const currentRole = roleRef.current;
702
+ const currentRunConfig = runConfigRef.current;
703
+ const currentAttachments = attachmentsRef.current;
704
+ const isEmpty_0 = !currentText.trim() && !currentAttachments.length;
705
+ if (!isEditingRef.current) throw new Error("Composer is not available");
706
+ if (isEmpty_0 || isSendDisabled) return;
707
+ attachmentAddOperations.cancelAll();
708
+ setText("");
709
+ setAttachments([]);
710
+ setQuote(void 0);
711
+ const dispatch = (sendAttachments) => {
712
+ const composedMessage = {
713
+ role: currentRole,
714
+ content: currentText ? [{
715
+ type: "text",
716
+ text: currentText
717
+ }] : [],
718
+ attachments: sendAttachments,
719
+ createdAt: /* @__PURE__ */ new Date(),
720
+ parentId: null,
721
+ sourceId: null,
722
+ runConfig: currentRunConfig,
723
+ startRun: opts?.startRun,
724
+ metadata: { custom: { ...currentQuote ? { quote: currentQuote } : {} } }
725
+ };
726
+ if (queue && type === "thread") {
727
+ if (opts?.steer ?? isRunning) queue.steer(composedMessage);
728
+ else queue.enqueue(composedMessage);
729
+ } else onSend?.(composedMessage);
730
+ if (type === "edit") setIsEditing(false);
731
+ };
732
+ if (attachmentAdapter && currentAttachments.length > 0) Promise.all(currentAttachments.map((attachment_2) => attachment_2.status.type === "complete" ? attachment_2 : attachmentAdapter.send(attachment_2))).then(dispatch, (error_0) => {
733
+ setText((prev_3) => currentText && prev_3 ? currentText + "\n" + prev_3 : currentText || prev_3);
734
+ setQuote((prev_4) => prev_4 ?? currentQuote);
735
+ setAttachments((prev_5) => [...currentAttachments, ...prev_5]);
736
+ console.error("Failed to send attachments", error_0);
737
+ });
738
+ else dispatch(currentAttachments);
739
+ };
740
+ $[62] = attachmentAdapter;
741
+ $[63] = attachmentsRef;
742
+ $[64] = isEditingRef;
743
+ $[65] = isRunning;
744
+ $[66] = isSendDisabled;
745
+ $[67] = onSend;
746
+ $[68] = queue;
747
+ $[69] = quoteRef;
748
+ $[70] = roleRef;
749
+ $[71] = runConfigRef;
750
+ $[72] = setAttachments;
751
+ $[73] = setIsEditing;
752
+ $[74] = setQuote;
753
+ $[75] = setText;
754
+ $[76] = textRef;
755
+ $[77] = type;
756
+ $[78] = t19;
757
+ } else t19 = $[78];
758
+ let t20;
759
+ if ($[79] !== onCancel || $[80] !== setIsEditing || $[81] !== type) {
760
+ t20 = () => {
761
+ onCancel?.();
762
+ if (type === "edit") setIsEditing(false);
763
+ };
764
+ $[79] = onCancel;
765
+ $[80] = setIsEditing;
766
+ $[81] = type;
767
+ $[82] = t20;
768
+ } else t20 = $[82];
769
+ let t21;
770
+ if ($[83] !== isEditingRef || $[84] !== onBeginEdit || $[85] !== setIsEditing || $[86] !== type || $[87] !== updateFromMessage) {
771
+ t21 = () => {
772
+ onBeginEdit?.();
773
+ if (type === "thread") return;
774
+ if (isEditingRef.current) throw new Error("Edit already in progress");
775
+ setIsEditing(true);
776
+ updateFromMessage();
777
+ };
778
+ $[83] = isEditingRef;
779
+ $[84] = onBeginEdit;
780
+ $[85] = setIsEditing;
781
+ $[86] = type;
782
+ $[87] = updateFromMessage;
783
+ $[88] = t21;
784
+ } else t21 = $[88];
785
+ let t22;
786
+ if ($[89] !== queueItemClients) {
787
+ t22 = (selector_0) => {
788
+ if ("id" in selector_0) return queueItemClients.get({ key: selector_0.id });
789
+ return queueItemClients.get(selector_0);
790
+ };
791
+ $[89] = queueItemClients;
792
+ $[90] = t22;
793
+ } else t22 = $[90];
794
+ let t23;
795
+ if ($[91] !== setQuote || $[92] !== setRole || $[93] !== setRunConfig || $[94] !== setText || $[95] !== t14 || $[96] !== t15 || $[97] !== t16 || $[98] !== t17 || $[99] !== t18 || $[100] !== t19 || $[101] !== t20 || $[102] !== t21 || $[103] !== t22) {
796
+ t23 = {
797
+ getState: t14,
798
+ setText,
799
+ setRole,
800
+ setRunConfig,
801
+ addAttachment: t15,
802
+ clearAttachments: t16,
803
+ attachment: t17,
804
+ reset: t18,
805
+ send: t19,
806
+ cancel: t20,
807
+ beginEdit: t21,
808
+ startDictation: _temp7,
809
+ stopDictation: _temp8,
810
+ setQuote,
811
+ queueItem: t22
812
+ };
813
+ $[91] = setQuote;
814
+ $[92] = setRole;
815
+ $[93] = setRunConfig;
816
+ $[94] = setText;
817
+ $[95] = t14;
818
+ $[96] = t15;
819
+ $[97] = t16;
820
+ $[98] = t17;
821
+ $[99] = t18;
822
+ $[100] = t19;
823
+ $[101] = t20;
824
+ $[102] = t21;
825
+ $[103] = t22;
826
+ $[104] = t23;
827
+ } else t23 = $[104];
828
+ return t23;
829
+ };
830
+ const ComposerClientResource = resource(useComposerClientResource);
831
+ const createSpeechController = (notify) => {
832
+ let session;
833
+ const clear = () => {
834
+ if (!session) return;
835
+ session.cancel();
836
+ session = void 0;
837
+ notify(void 0);
838
+ };
839
+ return {
840
+ speak: (adapter, message) => {
841
+ clear();
842
+ const utterance = adapter.speak(getThreadMessageText(message));
843
+ let unsub;
844
+ unsub = utterance.subscribe(() => {
845
+ if (utterance.status.type === "ended") {
846
+ unsub?.();
847
+ session = void 0;
848
+ notify(void 0);
849
+ } else notify({
850
+ messageId: message.id,
851
+ status: utterance.status
852
+ });
853
+ });
854
+ if (utterance.status.type === "ended") {
855
+ unsub();
856
+ notify(void 0);
857
+ return;
858
+ }
859
+ session = {
860
+ messageId: message.id,
861
+ cancel: () => {
862
+ unsub();
863
+ utterance.cancel();
864
+ }
865
+ };
866
+ notify({
867
+ messageId: message.id,
868
+ status: utterance.status
869
+ });
870
+ },
871
+ stop: () => {
872
+ if (!session) throw new Error("No message is being spoken");
873
+ clear();
874
+ },
875
+ stopMessage: (messageId) => {
876
+ if (session?.messageId !== messageId) throw new Error("Message is not being spoken");
877
+ clear();
878
+ },
879
+ dispose: clear
880
+ };
881
+ };
882
+ const dedupeMessagesById = (messages) => {
883
+ const seenIds = /* @__PURE__ */ new Set();
884
+ const deduped = [];
885
+ for (let i = messages.length - 1; i >= 0; i--) {
886
+ const message = messages[i];
887
+ if (seenIds.has(message.id)) {
888
+ console.warn(`ExternalThread: duplicate message id "${message.id}" in the provided messages array; keeping the last occurrence.`);
889
+ continue;
890
+ }
891
+ seenIds.add(message.id);
892
+ deduped.push(message);
893
+ }
894
+ return deduped.length === messages.length ? messages : deduped.reverse();
895
+ };
896
+ const useExternalThread = (t0) => {
897
+ const $ = c(115);
898
+ const { messages: messagesProp, isRunning: t1, isLoading: t2, state: threadState, extras, isSendDisabled: t3, onNew, onEdit, onReload, onStartRun, onCancel, onResume, onRefetchThread, onAddToolResult, onResumeToolCall, onLoadExternalState, attachmentAdapter, feedbackAdapter, speechAdapter, queue, branches, onRespondToToolApproval } = t0;
899
+ const isRunning = t1 === void 0 ? false : t1;
900
+ const isLoading = t2 === void 0 ? false : t2;
901
+ const isSendDisabled = t3 === void 0 ? false : t3;
902
+ let t4;
903
+ if ($[0] !== messagesProp) {
904
+ t4 = dedupeMessagesById(messagesProp);
905
+ $[0] = messagesProp;
906
+ $[1] = t4;
907
+ } else t4 = $[1];
908
+ const messages = t4;
909
+ let t5;
910
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
911
+ t5 = {};
912
+ $[2] = t5;
913
+ } else t5 = $[2];
914
+ const [submittedFeedback, setSubmittedFeedback] = useState(t5);
915
+ let t6;
916
+ if ($[3] !== submittedFeedback) {
917
+ t6 = (msg) => {
918
+ const entry = submittedFeedback[msg.id];
919
+ return entry && msg.metadata.submittedFeedback?.type === entry.external ? entry.type : void 0;
920
+ };
921
+ $[3] = submittedFeedback;
922
+ $[4] = t6;
923
+ } else t6 = $[4];
924
+ const feedbackFor = t6;
925
+ let t7;
926
+ let t8;
927
+ if ($[5] !== messages) {
928
+ t7 = () => {
929
+ setSubmittedFeedback((prev) => {
930
+ const live = Object.entries(prev).filter((t9) => {
931
+ const [id, entry_0] = t9;
932
+ const msg_0 = messages.find((m) => m.id === id);
933
+ return !!msg_0 && msg_0.metadata.submittedFeedback?.type === entry_0.external;
934
+ });
935
+ return live.length === Object.keys(prev).length ? prev : Object.fromEntries(live);
936
+ });
937
+ };
938
+ t8 = [messages];
939
+ $[5] = messages;
940
+ $[6] = t7;
941
+ $[7] = t8;
942
+ } else {
943
+ t7 = $[6];
944
+ t8 = $[7];
945
+ }
946
+ useEffect(t7, t8);
947
+ let t9;
948
+ if ($[8] !== feedbackAdapter) {
949
+ t9 = (message, t10) => {
950
+ const { type } = t10;
951
+ if (!feedbackAdapter) throw new Error("Feedback adapter not configured");
952
+ feedbackAdapter.submit({
953
+ message,
954
+ type
955
+ });
956
+ if (message.role === "assistant") setSubmittedFeedback((prev_0) => ({
957
+ ...prev_0,
958
+ [message.id]: {
959
+ type,
960
+ external: message.metadata.submittedFeedback?.type
961
+ }
962
+ }));
963
+ };
964
+ $[8] = feedbackAdapter;
965
+ $[9] = t9;
966
+ } else t9 = $[9];
967
+ const handleSubmitFeedback = t9;
968
+ const [speechState, setSpeech] = useState(void 0);
969
+ let t10;
970
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
971
+ t10 = () => createSpeechController(setSpeech);
972
+ $[10] = t10;
973
+ } else t10 = $[10];
974
+ const [speechController] = useState(t10);
975
+ const hasSpeechAdapter = !!speechAdapter;
976
+ const speech = hasSpeechAdapter ? speechState : void 0;
977
+ let t11;
978
+ let t12;
979
+ if ($[11] !== hasSpeechAdapter || $[12] !== speechController) {
980
+ t11 = () => {
981
+ if (!hasSpeechAdapter) speechController.dispose();
982
+ };
983
+ t12 = [hasSpeechAdapter, speechController];
984
+ $[11] = hasSpeechAdapter;
985
+ $[12] = speechController;
986
+ $[13] = t11;
987
+ $[14] = t12;
988
+ } else {
989
+ t11 = $[13];
990
+ t12 = $[14];
991
+ }
992
+ useEffect(t11, t12);
993
+ let t13;
994
+ let t14;
995
+ if ($[15] !== speechController) {
996
+ t13 = () => () => speechController.dispose();
997
+ t14 = [speechController];
998
+ $[15] = speechController;
999
+ $[16] = t13;
1000
+ $[17] = t14;
1001
+ } else {
1002
+ t13 = $[16];
1003
+ t14 = $[17];
1004
+ }
1005
+ useEffect(t13, t14);
1006
+ let t15;
1007
+ if ($[18] !== speechAdapter || $[19] !== speechController) {
1008
+ t15 = (message_0) => {
1009
+ if (!speechAdapter) throw new Error("Speech adapter not configured");
1010
+ speechController.speak(speechAdapter, message_0);
1011
+ };
1012
+ $[18] = speechAdapter;
1013
+ $[19] = speechController;
1014
+ $[20] = t15;
1015
+ } else t15 = $[20];
1016
+ const handleSpeak = t15;
1017
+ let t16;
1018
+ if ($[21] !== messages || $[22] !== onReload) {
1019
+ t16 = (messageId) => {
1020
+ const messageIndex = messages.findIndex((m_0) => m_0.id === messageId);
1021
+ if (messageIndex === -1) return;
1022
+ const parentId = messageIndex > 0 ? messages[messageIndex - 1].id : null;
1023
+ onReload?.(parentId);
1024
+ };
1025
+ $[21] = messages;
1026
+ $[22] = onReload;
1027
+ $[23] = t16;
1028
+ } else t16 = $[23];
1029
+ const handleReload = t16;
1030
+ let t17;
1031
+ if ($[24] !== attachmentAdapter || $[25] !== branches || $[26] !== feedbackFor || $[27] !== handleReload || $[28] !== handleSpeak || $[29] !== handleSubmitFeedback || $[30] !== messages || $[31] !== onAddToolResult || $[32] !== onEdit || $[33] !== onRespondToToolApproval || $[34] !== onResumeToolCall || $[35] !== queue || $[36] !== speech || $[37] !== speechController) {
1032
+ t17 = messages.map((msg_1, index) => {
1033
+ const props = {
1034
+ message: msg_1,
1035
+ index,
1036
+ parentId: index > 0 ? messages[index - 1].id : null,
1037
+ onReload: () => handleReload(msg_1.id),
1038
+ queue,
1039
+ branches,
1040
+ onRespondToToolApproval,
1041
+ onAddToolResult,
1042
+ onResumeToolCall,
1043
+ attachmentAdapter,
1044
+ submittedFeedback: feedbackFor(msg_1),
1045
+ onSubmitFeedback: (feedback) => handleSubmitFeedback(msg_1, feedback),
1046
+ speech: speech?.messageId === msg_1.id ? speech : void 0,
1047
+ onSpeak: () => handleSpeak(msg_1),
1048
+ onStopSpeaking: () => speechController.stopMessage(msg_1.id)
1049
+ };
1050
+ if (onEdit) props.onEdit = onEdit;
1051
+ return withKey(msg_1.id, MessageClient(props));
1052
+ });
1053
+ $[24] = attachmentAdapter;
1054
+ $[25] = branches;
1055
+ $[26] = feedbackFor;
1056
+ $[27] = handleReload;
1057
+ $[28] = handleSpeak;
1058
+ $[29] = handleSubmitFeedback;
1059
+ $[30] = messages;
1060
+ $[31] = onAddToolResult;
1061
+ $[32] = onEdit;
1062
+ $[33] = onRespondToToolApproval;
1063
+ $[34] = onResumeToolCall;
1064
+ $[35] = queue;
1065
+ $[36] = speech;
1066
+ $[37] = speechController;
1067
+ $[38] = t17;
1068
+ } else t17 = $[38];
1069
+ const messageClients = useClientLookup(t17);
1070
+ let t18;
1071
+ if ($[39] !== onCancel || $[40] !== queue) {
1072
+ t18 = () => {
1073
+ if (!onCancel) return;
1074
+ queue?.__internal_notifyCancelled?.();
1075
+ onCancel();
1076
+ };
1077
+ $[39] = onCancel;
1078
+ $[40] = queue;
1079
+ $[41] = t18;
1080
+ } else t18 = $[41];
1081
+ const handleCancelRun = t18;
1082
+ let t19;
1083
+ if ($[42] !== messages || $[43] !== onNew) {
1084
+ t19 = (message_1) => {
1085
+ onNew?.({
1086
+ ...message_1,
1087
+ parentId: messages.at(-1)?.id ?? null
1088
+ });
1089
+ };
1090
+ $[42] = messages;
1091
+ $[43] = onNew;
1092
+ $[44] = t19;
1093
+ } else t19 = $[44];
1094
+ const handleSendNew = t19;
1095
+ let t20;
1096
+ if ($[45] !== messages) {
1097
+ t20 = messages.at(-1)?.id ?? null;
1098
+ $[45] = messages;
1099
+ $[46] = t20;
1100
+ } else t20 = $[46];
1101
+ const headId = t20;
1102
+ const hasCancel = !!onCancel;
1103
+ const hasRefetchThread = !!onRefetchThread;
1104
+ let t21;
1105
+ if ($[47] !== headId || $[48] !== queue) {
1106
+ t21 = queue && {
1107
+ ...queue,
1108
+ enqueue: (message_2) => queue.enqueue({
1109
+ ...message_2,
1110
+ parentId: message_2.parentId ?? headId
1111
+ }),
1112
+ steer: (message_3) => queue.steer({
1113
+ ...message_3,
1114
+ parentId: message_3.parentId ?? headId
1115
+ })
1116
+ };
1117
+ $[47] = headId;
1118
+ $[48] = queue;
1119
+ $[49] = t21;
1120
+ } else t21 = $[49];
1121
+ const composerQueue = t21;
1122
+ const t22 = isRunning && hasCancel;
1123
+ let t23;
1124
+ if ($[50] !== attachmentAdapter || $[51] !== composerQueue || $[52] !== handleCancelRun || $[53] !== handleSendNew || $[54] !== isRunning || $[55] !== isSendDisabled || $[56] !== t22) {
1125
+ t23 = ComposerClientResource({
1126
+ type: "thread",
1127
+ canCancel: t22,
1128
+ isRunning,
1129
+ isSendDisabled,
1130
+ onCancel: handleCancelRun,
1131
+ onSend: handleSendNew,
1132
+ queue: composerQueue,
1133
+ attachmentAdapter
1134
+ });
1135
+ $[50] = attachmentAdapter;
1136
+ $[51] = composerQueue;
1137
+ $[52] = handleCancelRun;
1138
+ $[53] = handleSendNew;
1139
+ $[54] = isRunning;
1140
+ $[55] = isSendDisabled;
1141
+ $[56] = t22;
1142
+ $[57] = t23;
1143
+ } else t23 = $[57];
1144
+ const composerClient = useClientResource(t23);
1145
+ let t24;
1146
+ if ($[58] === Symbol.for("react.memo_cache_sentinel")) {
1147
+ t24 = ThreadSuggestions(EMPTY_SUGGESTIONS);
1148
+ $[58] = t24;
1149
+ } else t24 = $[58];
1150
+ const suggestionsClient = useClientResource(t24);
1151
+ const hasQueue = !!queue;
1152
+ const hasBranches = !!branches;
1153
+ const hasEdit = !!onEdit;
1154
+ const hasReload = !!onReload;
1155
+ const hasAttachments = !!attachmentAdapter;
1156
+ const hasFeedback = !!feedbackAdapter;
1157
+ const hasSpeech = !!speechAdapter;
1158
+ let t25;
1159
+ if ($[59] !== messageClients.state) {
1160
+ t25 = messageClients.state.map(_temp9);
1161
+ $[59] = messageClients.state;
1162
+ $[60] = t25;
1163
+ } else t25 = $[60];
1164
+ const messageStates = t25;
1165
+ const t26 = messages.length === 0;
1166
+ let t27;
1167
+ if ($[61] !== hasAttachments || $[62] !== hasBranches || $[63] !== hasCancel || $[64] !== hasEdit || $[65] !== hasFeedback || $[66] !== hasQueue || $[67] !== hasRefetchThread || $[68] !== hasReload || $[69] !== hasSpeech) {
1168
+ t27 = {
1169
+ edit: hasEdit,
1170
+ delete: false,
1171
+ reload: hasReload,
1172
+ refetchThread: hasRefetchThread,
1173
+ cancel: hasCancel,
1174
+ speech: hasSpeech,
1175
+ attachments: hasAttachments,
1176
+ feedback: hasFeedback,
1177
+ voice: false,
1178
+ switchToBranch: hasBranches,
1179
+ switchBranchDuringRun: false,
1180
+ unstable_copy: false,
1181
+ dictation: false,
1182
+ queue: hasQueue
1183
+ };
1184
+ $[61] = hasAttachments;
1185
+ $[62] = hasBranches;
1186
+ $[63] = hasCancel;
1187
+ $[64] = hasEdit;
1188
+ $[65] = hasFeedback;
1189
+ $[66] = hasQueue;
1190
+ $[67] = hasRefetchThread;
1191
+ $[68] = hasReload;
1192
+ $[69] = hasSpeech;
1193
+ $[70] = t27;
1194
+ } else t27 = $[70];
1195
+ let t28;
1196
+ if ($[71] !== threadState) {
1197
+ t28 = threadState ?? {};
1198
+ $[71] = threadState;
1199
+ $[72] = t28;
1200
+ } else t28 = $[72];
1201
+ let t29;
1202
+ if ($[73] !== composerClient.state || $[74] !== extras || $[75] !== isLoading || $[76] !== isRunning || $[77] !== messageStates || $[78] !== speech || $[79] !== t26 || $[80] !== t27 || $[81] !== t28) {
1203
+ t29 = {
1204
+ isEmpty: t26,
1205
+ isDisabled: false,
1206
+ isLoading,
1207
+ isRunning,
1208
+ capabilities: t27,
1209
+ messages: messageStates,
1210
+ state: t28,
1211
+ suggestions: EMPTY_SUGGESTIONS,
1212
+ extras,
1213
+ speech,
1214
+ voice: void 0,
1215
+ composer: composerClient.state
1216
+ };
1217
+ $[73] = composerClient.state;
1218
+ $[74] = extras;
1219
+ $[75] = isLoading;
1220
+ $[76] = isRunning;
1221
+ $[77] = messageStates;
1222
+ $[78] = speech;
1223
+ $[79] = t26;
1224
+ $[80] = t27;
1225
+ $[81] = t28;
1226
+ $[82] = t29;
1227
+ } else t29 = $[82];
1228
+ const state = t29;
1229
+ let t30;
1230
+ if ($[83] !== state) {
1231
+ t30 = () => state;
1232
+ $[83] = state;
1233
+ $[84] = t30;
1234
+ } else t30 = $[84];
1235
+ let t31;
1236
+ if ($[85] !== composerClient.methods) {
1237
+ t31 = () => composerClient.methods;
1238
+ $[85] = composerClient.methods;
1239
+ $[86] = t31;
1240
+ } else t31 = $[86];
1241
+ let t32;
1242
+ if ($[87] !== suggestionsClient) {
1243
+ t32 = () => suggestionsClient.methods;
1244
+ $[87] = suggestionsClient;
1245
+ $[88] = t32;
1246
+ } else t32 = $[88];
1247
+ let t33;
1248
+ if ($[89] !== messages || $[90] !== onNew || $[91] !== queue) {
1249
+ t33 = (message_4) => {
1250
+ const appendMessage = typeof message_4 === "string" ? {
1251
+ createdAt: /* @__PURE__ */ new Date(),
1252
+ parentId: messages.at(-1)?.id ?? null,
1253
+ sourceId: null,
1254
+ runConfig: {},
1255
+ role: "user",
1256
+ content: [{
1257
+ type: "text",
1258
+ text: message_4
1259
+ }],
1260
+ attachments: [],
1261
+ metadata: { custom: {} }
1262
+ } : {
1263
+ createdAt: message_4.createdAt ?? /* @__PURE__ */ new Date(),
1264
+ parentId: message_4.parentId ?? messages.at(-1)?.id ?? null,
1265
+ sourceId: message_4.sourceId ?? null,
1266
+ role: message_4.role ?? "user",
1267
+ content: message_4.content,
1268
+ attachments: message_4.attachments ?? [],
1269
+ metadata: message_4.metadata ?? { custom: {} },
1270
+ runConfig: message_4.runConfig ?? {},
1271
+ startRun: message_4.startRun
1272
+ };
1273
+ if (queue) queue.enqueue(appendMessage);
1274
+ else onNew?.(appendMessage);
1275
+ };
1276
+ $[89] = messages;
1277
+ $[90] = onNew;
1278
+ $[91] = queue;
1279
+ $[92] = t33;
1280
+ } else t33 = $[92];
1281
+ let t34;
1282
+ if ($[93] !== onStartRun) {
1283
+ t34 = () => {
1284
+ onStartRun?.();
1285
+ };
1286
+ $[93] = onStartRun;
1287
+ $[94] = t34;
1288
+ } else t34 = $[94];
1289
+ let t35;
1290
+ if ($[95] !== onResume) {
1291
+ t35 = () => {
1292
+ if (!onResume) throw new Error("Runtime does not support resuming runs (onResume is not set).");
1293
+ onResume();
1294
+ };
1295
+ $[95] = onResume;
1296
+ $[96] = t35;
1297
+ } else t35 = $[96];
1298
+ let t36;
1299
+ if ($[97] !== onRefetchThread) {
1300
+ t36 = onRefetchThread && { unstable_refetchThread: onRefetchThread };
1301
+ $[97] = onRefetchThread;
1302
+ $[98] = t36;
1303
+ } else t36 = $[98];
1304
+ let t37;
1305
+ if ($[99] !== onLoadExternalState) {
1306
+ t37 = (state_0) => {
1307
+ if (!onLoadExternalState) throw new Error("Runtime does not support importing external states (onLoadExternalState is not set).");
1308
+ onLoadExternalState(state_0);
1309
+ };
1310
+ $[99] = onLoadExternalState;
1311
+ $[100] = t37;
1312
+ } else t37 = $[100];
1313
+ let t38;
1314
+ if ($[101] !== messageClients) {
1315
+ t38 = (selector) => {
1316
+ if ("id" in selector) return messageClients.get({ key: selector.id });
1317
+ return messageClients.get(selector);
1318
+ };
1319
+ $[101] = messageClients;
1320
+ $[102] = t38;
1321
+ } else t38 = $[102];
1322
+ let t39;
1323
+ if ($[103] !== handleCancelRun || $[104] !== speechController.stop || $[105] !== t30 || $[106] !== t31 || $[107] !== t32 || $[108] !== t33 || $[109] !== t34 || $[110] !== t35 || $[111] !== t36 || $[112] !== t37 || $[113] !== t38) {
1324
+ t39 = {
1325
+ getState: t30,
1326
+ composer: t31,
1327
+ suggestions: t32,
1328
+ append: t33,
1329
+ deleteMessage: _temp0,
1330
+ startRun: t34,
1331
+ resumeRun: t35,
1332
+ cancelRun: handleCancelRun,
1333
+ ...t36,
1334
+ importExternalState: t37,
1335
+ getModelContext: _temp1,
1336
+ export: _temp10,
1337
+ import: _temp11,
1338
+ reset: _temp12,
1339
+ message: t38,
1340
+ stopSpeaking: speechController.stop,
1341
+ connectVoice: _temp13,
1342
+ disconnectVoice: _temp14,
1343
+ getVoiceVolume: _temp15,
1344
+ subscribeVoiceVolume: _temp17,
1345
+ muteVoice: _temp18,
1346
+ unmuteVoice: _temp19
1347
+ };
1348
+ $[103] = handleCancelRun;
1349
+ $[104] = speechController.stop;
1350
+ $[105] = t30;
1351
+ $[106] = t31;
1352
+ $[107] = t32;
1353
+ $[108] = t33;
1354
+ $[109] = t34;
1355
+ $[110] = t35;
1356
+ $[111] = t36;
1357
+ $[112] = t37;
1358
+ $[113] = t38;
1359
+ $[114] = t39;
1360
+ } else t39 = $[114];
1361
+ return t39;
1362
+ };
1363
+ const ExternalThread = resource(useExternalThread);
1364
+ attachTransformScopes(useExternalThread, (scopes, parent) => {
1365
+ if (!scopes.threads && parent.threads.source === null) {
1366
+ const threadElement = scopes.thread;
1367
+ scopes.threads = SingleThreadList({ thread: threadElement });
1368
+ delete scopes.thread;
1369
+ scopes.thread = Derived({
1370
+ source: "threads",
1371
+ query: { type: "main" },
1372
+ get: (aui) => aui.threads.thread("main")
1373
+ });
1374
+ }
1375
+ if (!scopes.threadListItem && parent.threadListItem.source === null) scopes.threadListItem = Derived({
1376
+ source: "threads",
1377
+ query: { type: "main" },
1378
+ get: (aui) => aui.threads.item("main")
1379
+ });
1380
+ scopes.composer ??= Derived({
1381
+ source: "thread",
1382
+ query: {},
1383
+ get: (aui) => aui.thread.composer()
1384
+ });
1385
+ if (!scopes.modelContext && parent.modelContext.source === null) scopes.modelContext = ModelContext();
1386
+ if (!scopes.tools && parent.tools.source === null) scopes.tools = Tools({});
1387
+ if (!scopes.dataRenderers && parent.dataRenderers.source === null) scopes.dataRenderers = DataRenderers();
1388
+ if (!scopes.suggestions && parent.suggestions.source === null) scopes.suggestions = Derived({
1389
+ source: "thread",
1390
+ query: {},
1391
+ get: (aui) => aui.thread.suggestions()
1392
+ });
1393
+ });
1394
+ function _temp() {}
1395
+ function _temp2(attachment) {
1396
+ return withKey(attachment.id, AttachmentResource({
1397
+ attachment,
1398
+ onRemove: _temp
1399
+ }));
1400
+ }
1401
+ function _temp3() {}
1402
+ function _temp4(part) {
1403
+ return part.type === "text";
1404
+ }
1405
+ function _temp5(part_0) {
1406
+ return part_0.text;
1407
+ }
1408
+ function _temp6(a_0) {
1409
+ return a_0.status.type !== "complete";
1410
+ }
1411
+ function _temp7() {}
1412
+ function _temp8() {}
1413
+ function _temp9(s, idx, arr) {
1414
+ return {
1415
+ ...s,
1416
+ isLast: idx === arr.length - 1
1417
+ };
1418
+ }
1419
+ function _temp0() {}
1420
+ function _temp1() {
1421
+ return {
1422
+ tools: {},
1423
+ config: {}
1424
+ };
1425
+ }
1426
+ function _temp10() {
1427
+ return { messages: [] };
1428
+ }
1429
+ function _temp11() {}
1430
+ function _temp12() {}
1431
+ function _temp13() {}
1432
+ function _temp14() {}
1433
+ function _temp15() {
1434
+ return 0;
1435
+ }
1436
+ function _temp16() {}
1437
+ function _temp17() {
1438
+ return _temp16;
1439
+ }
1440
+ function _temp18() {}
1441
+ function _temp19() {}
1442
+ //#endregion
1443
+ export { ExternalThread };
1444
+
1445
+ //# sourceMappingURL=external-thread.js.map