instantsearch.js 4.87.0 → 4.87.1

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 (54) hide show
  1. package/cjs/connectors/chat/connectChat.js +4 -4
  2. package/cjs/index.js +2 -2
  3. package/cjs/lib/ai-lite/abstract-chat.js +823 -0
  4. package/cjs/lib/ai-lite/index.js +57 -0
  5. package/cjs/lib/ai-lite/stream-parser.js +138 -0
  6. package/cjs/lib/ai-lite/transport.js +218 -0
  7. package/cjs/lib/ai-lite/types.js +1 -0
  8. package/cjs/lib/ai-lite/utils.js +85 -0
  9. package/cjs/lib/chat/chat.js +3 -3
  10. package/cjs/lib/version.js +1 -1
  11. package/dist/instantsearch.development.d.ts +1561 -169
  12. package/dist/instantsearch.development.js +9110 -4563
  13. package/dist/instantsearch.development.js.map +1 -1
  14. package/dist/instantsearch.production.d.ts +1561 -169
  15. package/dist/instantsearch.production.min.d.ts +1561 -169
  16. package/dist/instantsearch.production.min.js +2 -2
  17. package/dist/instantsearch.production.min.js.map +1 -1
  18. package/es/connectors/chat/connectChat.d.ts +14 -14
  19. package/es/connectors/chat/connectChat.js +1 -1
  20. package/es/connectors/frequently-bought-together/connectFrequentlyBoughtTogether.d.ts +2 -2
  21. package/es/connectors/geo-search/connectGeoSearch.d.ts +1 -1
  22. package/es/connectors/hits/connectHits.d.ts +1 -1
  23. package/es/connectors/hits/connectHitsWithInsights.d.ts +1 -1
  24. package/es/connectors/infinite-hits/connectInfiniteHits.d.ts +1 -1
  25. package/es/connectors/infinite-hits/connectInfiniteHitsWithInsights.d.ts +1 -1
  26. package/es/connectors/looking-similar/connectLookingSimilar.d.ts +2 -2
  27. package/es/connectors/related-products/connectRelatedProducts.d.ts +2 -2
  28. package/es/connectors/trending-items/connectTrendingItems.d.ts +2 -2
  29. package/es/lib/ai-lite/abstract-chat.d.ts +89 -0
  30. package/es/lib/ai-lite/abstract-chat.js +818 -0
  31. package/es/lib/ai-lite/index.d.ts +11 -0
  32. package/es/lib/ai-lite/index.js +18 -0
  33. package/es/lib/ai-lite/stream-parser.d.ts +18 -0
  34. package/es/lib/ai-lite/stream-parser.js +131 -0
  35. package/es/lib/ai-lite/transport.d.ts +24 -0
  36. package/es/lib/ai-lite/transport.js +214 -0
  37. package/es/lib/ai-lite/types.d.ts +362 -0
  38. package/es/lib/ai-lite/types.js +1 -0
  39. package/es/lib/ai-lite/utils.d.ts +12 -0
  40. package/es/lib/ai-lite/utils.js +76 -0
  41. package/es/lib/chat/chat.d.ts +2 -2
  42. package/es/lib/chat/chat.js +1 -1
  43. package/es/lib/version.d.ts +1 -1
  44. package/es/lib/version.js +1 -1
  45. package/es/widgets/chat/chat.d.ts +14 -14
  46. package/es/widgets/filter-suggestions/filter-suggestions.d.ts +5 -5
  47. package/es/widgets/frequently-bought-together/frequently-bought-together.d.ts +3 -3
  48. package/es/widgets/geo-search/geo-search.d.ts +1 -1
  49. package/es/widgets/hits/hits.d.ts +1 -1
  50. package/es/widgets/infinite-hits/infinite-hits.d.ts +1 -1
  51. package/es/widgets/looking-similar/looking-similar.d.ts +3 -3
  52. package/es/widgets/related-products/related-products.d.ts +3 -3
  53. package/es/widgets/trending-items/trending-items.d.ts +3 -3
  54. package/package.json +6 -7
@@ -0,0 +1,823 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AbstractChat = void 0;
7
+ var _streamParser = require("./stream-parser");
8
+ var _utils = require("./utils");
9
+ var _excluded = ["messageId"];
10
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
11
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
12
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
13
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
14
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
15
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
16
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
17
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
18
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
19
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
20
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
21
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
22
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
23
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
24
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
25
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
26
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* eslint-disable @typescript-eslint/consistent-type-assertions */
27
+ /**
28
+ * Abstract base class for chat implementations.
29
+ */
30
+ var AbstractChat = exports.AbstractChat = /*#__PURE__*/function () {
31
+ function AbstractChat(_ref) {
32
+ var _this = this;
33
+ var _ref$generateId = _ref.generateId,
34
+ generateId = _ref$generateId === void 0 ? _utils.generateId : _ref$generateId,
35
+ _ref$id = _ref.id,
36
+ id = _ref$id === void 0 ? generateId() : _ref$id,
37
+ transport = _ref.transport,
38
+ state = _ref.state,
39
+ onError = _ref.onError,
40
+ onToolCall = _ref.onToolCall,
41
+ onFinish = _ref.onFinish,
42
+ onData = _ref.onData,
43
+ sendAutomaticallyWhen = _ref.sendAutomaticallyWhen;
44
+ _classCallCheck(this, AbstractChat);
45
+ _defineProperty(this, "id", void 0);
46
+ _defineProperty(this, "generateId", void 0);
47
+ _defineProperty(this, "state", void 0);
48
+ _defineProperty(this, "transport", void 0);
49
+ _defineProperty(this, "onError", void 0);
50
+ _defineProperty(this, "onToolCall", void 0);
51
+ _defineProperty(this, "onFinish", void 0);
52
+ _defineProperty(this, "onData", void 0);
53
+ _defineProperty(this, "sendAutomaticallyWhen", void 0);
54
+ _defineProperty(this, "activeResponse", null);
55
+ _defineProperty(this, "jobExecutor", new _utils.SerialJobExecutor());
56
+ /**
57
+ * Appends or replaces a user message to the chat list. This triggers the API call to fetch
58
+ * the assistant's response.
59
+ */
60
+ _defineProperty(this, "sendMessage", function (message, options) {
61
+ return _this.jobExecutor.run(function () {
62
+ // Build the user message
63
+ var userMessagePromise;
64
+ if (message) {
65
+ var messageId = message.messageId || _this.generateId();
66
+ if ('parts' in message && message.parts) {
67
+ // Full message with parts provided
68
+ userMessagePromise = Promise.resolve(_objectSpread({
69
+ id: messageId,
70
+ role: 'user'
71
+ }, message));
72
+ } else if ('text' in message && message.text) {
73
+ // Build from text
74
+ var parts = [{
75
+ type: 'text',
76
+ text: message.text
77
+ }];
78
+
79
+ // Add file parts if provided
80
+ if (message.files) {
81
+ userMessagePromise = _this.convertFilesToParts(message.files).then(function (fileParts) {
82
+ parts.push.apply(parts, _toConsumableArray(fileParts));
83
+ return {
84
+ id: messageId,
85
+ role: 'user',
86
+ parts: parts,
87
+ metadata: message.metadata
88
+ };
89
+ });
90
+ } else {
91
+ userMessagePromise = Promise.resolve({
92
+ id: messageId,
93
+ role: 'user',
94
+ parts: parts,
95
+ metadata: message.metadata
96
+ });
97
+ }
98
+ } else if ('files' in message && message.files) {
99
+ // Files only
100
+ userMessagePromise = _this.convertFilesToParts(message.files).then(function (fileParts) {
101
+ return {
102
+ id: messageId,
103
+ role: 'user',
104
+ parts: fileParts,
105
+ metadata: message.metadata
106
+ };
107
+ });
108
+ } else {
109
+ userMessagePromise = Promise.resolve(undefined);
110
+ }
111
+ } else {
112
+ userMessagePromise = Promise.resolve(undefined);
113
+ }
114
+ return userMessagePromise.then(function (userMessage) {
115
+ if (userMessage) {
116
+ _this.state.pushMessage(userMessage);
117
+ }
118
+ return _this.makeRequest(_objectSpread({
119
+ trigger: 'submit-message',
120
+ messageId: userMessage === null || userMessage === void 0 ? void 0 : userMessage.id
121
+ }, options));
122
+ });
123
+ });
124
+ });
125
+ /**
126
+ * Regenerate the assistant message with the provided message id.
127
+ * If no message id is provided, the last assistant message will be regenerated.
128
+ */
129
+ _defineProperty(this, "regenerate", function () {
130
+ var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
131
+ messageId = _ref2.messageId,
132
+ options = _objectWithoutProperties(_ref2, _excluded);
133
+ return _this.jobExecutor.run(function () {
134
+ // Find the message to regenerate from
135
+ var targetIndex = -1;
136
+ if (messageId) {
137
+ targetIndex = _this.state.messages.findIndex(function (m) {
138
+ return m.id === messageId;
139
+ });
140
+ } else {
141
+ // Find the last assistant message
142
+ for (var i = _this.state.messages.length - 1; i >= 0; i--) {
143
+ if (_this.state.messages[i].role === 'assistant') {
144
+ targetIndex = i;
145
+ break;
146
+ }
147
+ }
148
+ }
149
+ if (targetIndex >= 0) {
150
+ // Remove the assistant message and all messages after it
151
+ _this.state.messages = _this.state.messages.slice(0, targetIndex);
152
+ }
153
+ return _this.makeRequest(_objectSpread({
154
+ trigger: 'regenerate-message',
155
+ messageId: messageId
156
+ }, options));
157
+ });
158
+ });
159
+ /**
160
+ * Attempt to resume an ongoing streaming response.
161
+ */
162
+ _defineProperty(this, "resumeStream", function (options) {
163
+ return _this.jobExecutor.run(function () {
164
+ if (!_this.transport) {
165
+ return Promise.reject(new Error('Transport is required for resuming stream. Please provide a transport when initializing the chat.'));
166
+ }
167
+ _this.setStatus({
168
+ status: 'submitted'
169
+ });
170
+ return _this.transport.reconnectToStream(_objectSpread({
171
+ chatId: _this.id
172
+ }, options)).then(function (stream) {
173
+ if (stream) {
174
+ return _this.processStreamWithCallbacks(stream);
175
+ } else {
176
+ _this.setStatus({
177
+ status: 'ready'
178
+ });
179
+ return Promise.resolve();
180
+ }
181
+ }, function (error) {
182
+ _this.handleError(error);
183
+ return Promise.resolve();
184
+ });
185
+ });
186
+ });
187
+ /**
188
+ * Clear the error state and set the status to ready if the chat is in an error state.
189
+ */
190
+ _defineProperty(this, "clearError", function () {
191
+ if (_this.state.status === 'error') {
192
+ _this.setStatus({
193
+ status: 'ready',
194
+ error: undefined
195
+ });
196
+ }
197
+ });
198
+ /**
199
+ * Add a tool result for a tool call.
200
+ */
201
+ _defineProperty(this, "addToolResult", function (_ref3) {
202
+ var tool = _ref3.tool,
203
+ toolCallId = _ref3.toolCallId,
204
+ output = _ref3.output;
205
+ return _this.jobExecutor.run(function () {
206
+ // Find the message with this tool call
207
+ var messageIndex = _this.state.messages.findIndex(function (m) {
208
+ var _m$parts$some, _m$parts;
209
+ return (_m$parts$some = (_m$parts = m.parts) === null || _m$parts === void 0 ? void 0 : _m$parts.some(function (p) {
210
+ return 'toolCallId' in p && p.toolCallId === toolCallId || 'type' in p && p.type === "tool-".concat(String(tool));
211
+ })) !== null && _m$parts$some !== void 0 ? _m$parts$some : false;
212
+ });
213
+ if (messageIndex === -1) return Promise.resolve();
214
+ var message = _this.state.messages[messageIndex];
215
+ var updatedParts = message.parts.map(function (part) {
216
+ if ('toolCallId' in part && part.toolCallId === toolCallId && 'state' in part) {
217
+ return _objectSpread(_objectSpread({}, part), {}, {
218
+ state: 'output-available',
219
+ output: output
220
+ });
221
+ }
222
+ return part;
223
+ });
224
+ _this.state.replaceMessage(messageIndex, _objectSpread(_objectSpread({}, message), {}, {
225
+ parts: updatedParts
226
+ }));
227
+
228
+ // Check if we should auto-send based on sendAutomaticallyWhen
229
+ if (_this.sendAutomaticallyWhen) {
230
+ return Promise.resolve(_this.sendAutomaticallyWhen({
231
+ messages: _this.state.messages
232
+ })).then(function (shouldSend) {
233
+ if (shouldSend) {
234
+ return _this.makeRequest({
235
+ trigger: 'submit-message'
236
+ });
237
+ }
238
+ return Promise.resolve();
239
+ });
240
+ }
241
+ return Promise.resolve();
242
+ });
243
+ });
244
+ /**
245
+ * Abort the current request immediately, keep the generated tokens if any.
246
+ */
247
+ _defineProperty(this, "stop", function () {
248
+ if (_this.activeResponse) {
249
+ _this.activeResponse.abortController.abort();
250
+ _this.activeResponse = null;
251
+ }
252
+ _this.setStatus({
253
+ status: 'ready'
254
+ });
255
+ return Promise.resolve();
256
+ });
257
+ this.id = id;
258
+ this.generateId = generateId;
259
+ this.state = state;
260
+ this.transport = transport;
261
+ this.onError = onError;
262
+ this.onToolCall = onToolCall;
263
+ this.onFinish = onFinish;
264
+ this.onData = onData;
265
+ this.sendAutomaticallyWhen = sendAutomaticallyWhen;
266
+ }
267
+
268
+ /**
269
+ * Hook status:
270
+ *
271
+ * - `submitted`: The message has been sent to the API and we're awaiting the start of the response stream.
272
+ * - `streaming`: The response is actively streaming in from the API, receiving chunks of data.
273
+ * - `ready`: The full response has been received and processed; a new user message can be submitted.
274
+ * - `error`: An error occurred during the API request, preventing successful completion.
275
+ */
276
+ _createClass(AbstractChat, [{
277
+ key: "status",
278
+ get: function get() {
279
+ return this.state.status;
280
+ }
281
+ }, {
282
+ key: "setStatus",
283
+ value: function setStatus(_ref4) {
284
+ var status = _ref4.status,
285
+ error = _ref4.error;
286
+ this.state.status = status;
287
+ if (error !== undefined) {
288
+ this.state.error = error;
289
+ }
290
+ }
291
+ }, {
292
+ key: "error",
293
+ get: function get() {
294
+ return this.state.error;
295
+ }
296
+ }, {
297
+ key: "messages",
298
+ get: function get() {
299
+ return this.state.messages;
300
+ },
301
+ set: function set(messages) {
302
+ this.state.messages = messages;
303
+ }
304
+ }, {
305
+ key: "lastMessage",
306
+ get: function get() {
307
+ return this.state.messages[this.state.messages.length - 1];
308
+ }
309
+ }, {
310
+ key: "makeRequest",
311
+ value: function makeRequest(options) {
312
+ var _this2 = this;
313
+ if (!this.transport) {
314
+ return Promise.reject(new Error('Transport is required for sending messages. Please provide a transport when initializing the chat.'));
315
+ }
316
+
317
+ // Abort any existing request
318
+ if (this.activeResponse) {
319
+ this.activeResponse.abortController.abort();
320
+ }
321
+ var abortController = new AbortController();
322
+ this.activeResponse = {
323
+ abortController: abortController
324
+ };
325
+ this.setStatus({
326
+ status: 'submitted'
327
+ });
328
+ return this.transport.sendMessages({
329
+ chatId: this.id,
330
+ messages: this.state.messages,
331
+ abortSignal: abortController.signal,
332
+ trigger: options.trigger,
333
+ messageId: options.messageId,
334
+ headers: options.headers,
335
+ body: options.body,
336
+ requestMetadata: options.metadata
337
+ }).then(function (stream) {
338
+ _this2.activeResponse.stream = stream;
339
+ return _this2.processStreamWithCallbacks(stream);
340
+ }, function (error) {
341
+ if (error.name === 'AbortError') {
342
+ // Request was aborted, don't treat as error
343
+ return Promise.resolve();
344
+ }
345
+ _this2.handleError(error);
346
+ return Promise.resolve();
347
+ });
348
+ }
349
+ }, {
350
+ key: "processStreamWithCallbacks",
351
+ value: function processStreamWithCallbacks(stream) {
352
+ var _this3 = this;
353
+ this.setStatus({
354
+ status: 'streaming'
355
+ });
356
+ var currentMessageId;
357
+ var currentMessage;
358
+ var currentMessageIndex = -1;
359
+ var isAbort = false;
360
+ var isDisconnect = false;
361
+ var isError = false;
362
+
363
+ // Track current text/reasoning part state
364
+ var currentTextPartId;
365
+ var currentReasoningPartId;
366
+
367
+ // Promise chain for handling tool calls that return promises
368
+ var pendingToolCall = Promise.resolve();
369
+ return new Promise(function (resolve) {
370
+ (0, _streamParser.processStream)(stream,
371
+ // eslint-disable-next-line complexity
372
+ function (chunk) {
373
+ switch (chunk.type) {
374
+ case 'start':
375
+ {
376
+ currentMessageId = chunk.messageId || _this3.generateId();
377
+
378
+ // Check if we're continuing an existing message or creating a new one
379
+ var lastMessage = _this3.lastMessage;
380
+ if (lastMessage && lastMessage.role === 'assistant' && lastMessage.id === currentMessageId) {
381
+ currentMessage = lastMessage;
382
+ currentMessageIndex = _this3.state.messages.length - 1;
383
+ } else {
384
+ currentMessage = {
385
+ id: currentMessageId,
386
+ role: 'assistant',
387
+ parts: [],
388
+ metadata: chunk.messageMetadata
389
+ };
390
+ _this3.state.pushMessage(currentMessage);
391
+ currentMessageIndex = _this3.state.messages.length - 1;
392
+ }
393
+ break;
394
+ }
395
+ case 'text-start':
396
+ {
397
+ if (!currentMessage) break;
398
+ currentTextPartId = chunk.id;
399
+ var textPart = {
400
+ type: 'text',
401
+ text: '',
402
+ state: 'streaming',
403
+ providerMetadata: chunk.providerMetadata
404
+ };
405
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
406
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [textPart])
407
+ });
408
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
409
+ break;
410
+ }
411
+ case 'text-delta':
412
+ {
413
+ if (!currentMessage || !currentTextPartId) break;
414
+ var partIndex = currentMessage.parts.findIndex(function (p) {
415
+ return p.type === 'text' && p.state === 'streaming';
416
+ });
417
+ if (partIndex === -1) break;
418
+ var updatedParts = _toConsumableArray(currentMessage.parts);
419
+ var _textPart = updatedParts[partIndex];
420
+ updatedParts[partIndex] = _objectSpread(_objectSpread({}, _textPart), {}, {
421
+ text: _textPart.text + chunk.delta
422
+ });
423
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
424
+ parts: updatedParts
425
+ });
426
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
427
+ break;
428
+ }
429
+ case 'text-end':
430
+ {
431
+ if (!currentMessage) break;
432
+ var _partIndex = currentMessage.parts.findIndex(function (p) {
433
+ return p.type === 'text' && p.state === 'streaming';
434
+ });
435
+ if (_partIndex === -1) break;
436
+ var _updatedParts = _toConsumableArray(currentMessage.parts);
437
+ var _textPart2 = _updatedParts[_partIndex];
438
+ _updatedParts[_partIndex] = _objectSpread(_objectSpread({}, _textPart2), {}, {
439
+ state: 'done'
440
+ });
441
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
442
+ parts: _updatedParts
443
+ });
444
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
445
+ currentTextPartId = undefined;
446
+ break;
447
+ }
448
+ case 'reasoning-start':
449
+ {
450
+ if (!currentMessage) break;
451
+ currentReasoningPartId = chunk.id;
452
+ var reasoningPart = {
453
+ type: 'reasoning',
454
+ text: '',
455
+ state: 'streaming',
456
+ providerMetadata: chunk.providerMetadata
457
+ };
458
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
459
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [reasoningPart])
460
+ });
461
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
462
+ break;
463
+ }
464
+ case 'reasoning-delta':
465
+ {
466
+ if (!currentMessage || !currentReasoningPartId) break;
467
+ var _partIndex2 = currentMessage.parts.findIndex(function (p) {
468
+ return p.type === 'reasoning' && p.state === 'streaming';
469
+ });
470
+ if (_partIndex2 === -1) break;
471
+ var _updatedParts2 = _toConsumableArray(currentMessage.parts);
472
+ var _reasoningPart = _updatedParts2[_partIndex2];
473
+ _updatedParts2[_partIndex2] = _objectSpread(_objectSpread({}, _reasoningPart), {}, {
474
+ text: _reasoningPart.text + chunk.delta
475
+ });
476
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
477
+ parts: _updatedParts2
478
+ });
479
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
480
+ break;
481
+ }
482
+ case 'reasoning-end':
483
+ {
484
+ if (!currentMessage) break;
485
+ var _partIndex3 = currentMessage.parts.findIndex(function (p) {
486
+ return p.type === 'reasoning' && p.state === 'streaming';
487
+ });
488
+ if (_partIndex3 === -1) break;
489
+ var _updatedParts3 = _toConsumableArray(currentMessage.parts);
490
+ var _reasoningPart2 = _updatedParts3[_partIndex3];
491
+ _updatedParts3[_partIndex3] = _objectSpread(_objectSpread({}, _reasoningPart2), {}, {
492
+ state: 'done'
493
+ });
494
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
495
+ parts: _updatedParts3
496
+ });
497
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
498
+ currentReasoningPartId = undefined;
499
+ break;
500
+ }
501
+ case 'tool-input-start':
502
+ {
503
+ if (!currentMessage) break;
504
+ var toolPart = {
505
+ type: "tool-".concat(chunk.toolName),
506
+ toolCallId: chunk.toolCallId,
507
+ state: 'input-streaming',
508
+ input: chunk.input,
509
+ providerExecuted: chunk.providerExecuted
510
+ };
511
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
512
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [toolPart])
513
+ });
514
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
515
+ break;
516
+ }
517
+ case 'tool-input-delta':
518
+ {
519
+ // Tool input streaming - we'd need to parse partial JSON
520
+ // For now, we'll wait for tool-input-available
521
+ break;
522
+ }
523
+ case 'tool-input-available':
524
+ {
525
+ if (!currentMessage) break;
526
+
527
+ // Find existing tool part or create new one
528
+ var existingIndex = currentMessage.parts.findIndex(function (p) {
529
+ return 'toolCallId' in p && p.toolCallId === chunk.toolCallId;
530
+ });
531
+ var _toolPart = {
532
+ type: "tool-".concat(chunk.toolName),
533
+ toolCallId: chunk.toolCallId,
534
+ state: 'input-available',
535
+ input: chunk.input,
536
+ callProviderMetadata: chunk.callProviderMetadata,
537
+ providerExecuted: chunk.providerExecuted
538
+ };
539
+ if (existingIndex >= 0) {
540
+ var _updatedParts4 = _toConsumableArray(currentMessage.parts);
541
+ _updatedParts4[existingIndex] = _toolPart;
542
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
543
+ parts: _updatedParts4
544
+ });
545
+ } else {
546
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
547
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [_toolPart])
548
+ });
549
+ }
550
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
551
+
552
+ // Trigger onToolCall callback only for client-executed tools
553
+ // (server-executed tools have providerExecuted: true and don't need client handling)
554
+ if (_this3.onToolCall && !chunk.providerExecuted) {
555
+ var result = _this3.onToolCall({
556
+ toolCall: {
557
+ toolName: chunk.toolName,
558
+ toolCallId: chunk.toolCallId,
559
+ input: chunk.input
560
+ }
561
+ });
562
+ if (result && typeof result.then === 'function') {
563
+ pendingToolCall = pendingToolCall.then(function () {
564
+ return result;
565
+ });
566
+ }
567
+ }
568
+ break;
569
+ }
570
+ case 'tool-output-available':
571
+ {
572
+ if (!currentMessage) break;
573
+ var toolIndex = currentMessage.parts.findIndex(function (p) {
574
+ return 'toolCallId' in p && p.toolCallId === chunk.toolCallId;
575
+ });
576
+ if (toolIndex >= 0) {
577
+ var _updatedParts5 = _toConsumableArray(currentMessage.parts);
578
+ var existingPart = _updatedParts5[toolIndex];
579
+ _updatedParts5[toolIndex] = _objectSpread(_objectSpread({}, existingPart), {}, {
580
+ state: 'output-available',
581
+ output: chunk.output,
582
+ callProviderMetadata: chunk.callProviderMetadata,
583
+ preliminary: chunk.preliminary
584
+ });
585
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
586
+ parts: _updatedParts5
587
+ });
588
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
589
+ }
590
+ break;
591
+ }
592
+ case 'tool-error':
593
+ {
594
+ if (!currentMessage) break;
595
+ var _toolIndex = currentMessage.parts.findIndex(function (p) {
596
+ return 'toolCallId' in p && p.toolCallId === chunk.toolCallId;
597
+ });
598
+ if (_toolIndex >= 0) {
599
+ var _chunk$input;
600
+ var _updatedParts6 = _toConsumableArray(currentMessage.parts);
601
+ var _existingPart = _updatedParts6[_toolIndex];
602
+ _updatedParts6[_toolIndex] = _objectSpread(_objectSpread({}, _existingPart), {}, {
603
+ state: 'output-error',
604
+ errorText: chunk.errorText,
605
+ input: (_chunk$input = chunk.input) !== null && _chunk$input !== void 0 ? _chunk$input : _existingPart.input,
606
+ callProviderMetadata: chunk.callProviderMetadata
607
+ });
608
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
609
+ parts: _updatedParts6
610
+ });
611
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
612
+ }
613
+ break;
614
+ }
615
+ case 'source-url':
616
+ {
617
+ if (!currentMessage) break;
618
+ var sourcePart = {
619
+ type: 'source-url',
620
+ sourceId: chunk.sourceId,
621
+ url: chunk.url,
622
+ title: chunk.title
623
+ };
624
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
625
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [sourcePart])
626
+ });
627
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
628
+ break;
629
+ }
630
+ case 'source-document':
631
+ {
632
+ if (!currentMessage) break;
633
+ var docPart = {
634
+ type: 'source-document',
635
+ sourceId: chunk.sourceId,
636
+ mediaType: chunk.mediaType,
637
+ title: chunk.title,
638
+ filename: chunk.filename,
639
+ providerMetadata: chunk.providerMetadata
640
+ };
641
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
642
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [docPart])
643
+ });
644
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
645
+ break;
646
+ }
647
+ case 'file':
648
+ {
649
+ if (!currentMessage) break;
650
+ var filePart = {
651
+ type: 'file',
652
+ url: chunk.url,
653
+ mediaType: chunk.mediaType
654
+ };
655
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
656
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [filePart])
657
+ });
658
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
659
+ break;
660
+ }
661
+ case 'start-step':
662
+ {
663
+ if (!currentMessage) break;
664
+ var stepPart = {
665
+ type: 'step-start'
666
+ };
667
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
668
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [stepPart])
669
+ });
670
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
671
+ break;
672
+ }
673
+ case 'message-metadata':
674
+ {
675
+ if (!currentMessage) break;
676
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
677
+ metadata: chunk.messageMetadata
678
+ });
679
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
680
+ break;
681
+ }
682
+ case 'error':
683
+ {
684
+ isError = true;
685
+ throw new Error(chunk.errorText);
686
+ }
687
+ case 'abort':
688
+ {
689
+ isAbort = true;
690
+ break;
691
+ }
692
+ case 'finish':
693
+ {
694
+ if (currentMessage && chunk.messageMetadata !== undefined) {
695
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
696
+ metadata: chunk.messageMetadata
697
+ });
698
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
699
+ }
700
+ break;
701
+ }
702
+ default:
703
+ {
704
+ // Handle data parts (data-*)
705
+ var chunkType = chunk.type;
706
+ if (chunkType !== null && chunkType !== void 0 && chunkType.startsWith('data-') && currentMessage) {
707
+ var dataPart = {
708
+ type: chunkType,
709
+ id: chunk.id,
710
+ data: chunk.data
711
+ };
712
+ currentMessage = _objectSpread(_objectSpread({}, currentMessage), {}, {
713
+ parts: [].concat(_toConsumableArray(currentMessage.parts), [dataPart])
714
+ });
715
+ _this3.state.replaceMessage(currentMessageIndex, currentMessage);
716
+
717
+ // Trigger onData callback
718
+ if (_this3.onData) {
719
+ _this3.onData(dataPart);
720
+ }
721
+ }
722
+ }
723
+ }
724
+ }, function () {
725
+ // Wait for any pending tool calls to complete
726
+ pendingToolCall.then(function () {
727
+ // Stream finished successfully
728
+ _this3.setStatus({
729
+ status: 'ready'
730
+ });
731
+ _this3.activeResponse = null;
732
+
733
+ // Trigger onFinish callback
734
+ if (_this3.onFinish && currentMessage) {
735
+ _this3.onFinish({
736
+ message: currentMessage,
737
+ messages: _this3.state.messages,
738
+ isAbort: isAbort,
739
+ isDisconnect: isDisconnect,
740
+ isError: isError
741
+ });
742
+ }
743
+
744
+ // Note: sendAutomaticallyWhen is only checked in addToolResult,
745
+ // not here. For server-executed tools, the server continues the
746
+ // conversation. For client-executed tools, addToolResult handles it.
747
+ resolve();
748
+ });
749
+ }, function (error) {
750
+ if (error.name === 'AbortError') {
751
+ isAbort = true;
752
+ _this3.setStatus({
753
+ status: 'ready'
754
+ });
755
+ } else {
756
+ isDisconnect = true;
757
+ _this3.handleError(error);
758
+ }
759
+
760
+ // Still call onFinish even on error/abort
761
+ if (_this3.onFinish && currentMessage) {
762
+ _this3.onFinish({
763
+ message: currentMessage,
764
+ messages: _this3.state.messages,
765
+ isAbort: isAbort,
766
+ isDisconnect: isDisconnect,
767
+ isError: isError
768
+ });
769
+ }
770
+ resolve();
771
+ });
772
+ });
773
+ }
774
+ }, {
775
+ key: "handleError",
776
+ value: function handleError(error) {
777
+ this.setStatus({
778
+ status: 'error',
779
+ error: error
780
+ });
781
+ if (this.onError) {
782
+ this.onError(error);
783
+ }
784
+ }
785
+ }, {
786
+ key: "convertFilesToParts",
787
+ value: function convertFilesToParts(files) {
788
+ var _this4 = this;
789
+ if (Array.isArray(files)) {
790
+ return Promise.resolve(files);
791
+ }
792
+ var promises = [];
793
+ var _loop = function _loop() {
794
+ var file = files[i];
795
+ promises.push(_this4.fileToDataUrl(file).then(function (dataUrl) {
796
+ return {
797
+ type: 'file',
798
+ mediaType: file.type,
799
+ filename: file.name,
800
+ url: dataUrl
801
+ };
802
+ }));
803
+ };
804
+ for (var i = 0; i < files.length; i++) {
805
+ _loop();
806
+ }
807
+ return Promise.all(promises);
808
+ }
809
+ }, {
810
+ key: "fileToDataUrl",
811
+ value: function fileToDataUrl(file) {
812
+ return new Promise(function (resolve, reject) {
813
+ var reader = new FileReader();
814
+ reader.onload = function () {
815
+ return resolve(reader.result);
816
+ };
817
+ reader.onerror = reject;
818
+ reader.readAsDataURL(file);
819
+ });
820
+ }
821
+ }]);
822
+ return AbstractChat;
823
+ }();