react-instantsearch-core 7.48.0 → 7.49.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.
@@ -1,4 +1,4 @@
1
- /*! React InstantSearch Core 7.48.0 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
1
+ /*! React InstantSearch Core 7.49.1 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
4
4
  typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
@@ -24,7 +24,7 @@
24
24
 
25
25
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
26
26
 
27
- var version$2 = '7.48.0';
27
+ var version$2 = '7.49.1';
28
28
 
29
29
  function _define_property(obj, key, value) {
30
30
  if (key in obj) {
@@ -9418,7 +9418,7 @@
9418
9418
  });
9419
9419
  }
9420
9420
 
9421
- var version = '4.115.0';
9421
+ var version = '4.117.0';
9422
9422
 
9423
9423
  var ANONYMOUS_TOKEN_COOKIE_KEY = '_ALGOLIA';
9424
9424
  function getCookie(name) {
@@ -13077,6 +13077,26 @@
13077
13077
  var _computedKey$1;
13078
13078
  var defaultGuardrailFallbackResponse = 'Sorry, we are not able to generate a response at the moment.';
13079
13079
  var TOOL_CALL_CANCELLED_ERROR_TEXT = 'The tool call was cancelled: the conversation moved on before a result was provided.';
13080
+ var RESTORED_TOOL_CALL_ERROR_TEXT = 'The page was reloaded before a tool result was received. The operation may have completed.';
13081
+ var RESTORED_TOOL_INPUT_ERROR_TEXT = 'The page was reloaded before the tool input was complete. The operation was not started.';
13082
+ function getTerminalToolState(options) {
13083
+ if (options.state === 'output-error') {
13084
+ return {
13085
+ state: 'output-error',
13086
+ errorText: options.errorText || 'Tool call failed.'
13087
+ };
13088
+ }
13089
+ if (options.state === undefined && 'errorText' in options && typeof options.errorText === 'string') {
13090
+ return {
13091
+ state: 'output-error',
13092
+ errorText: options.errorText || 'Tool call failed.'
13093
+ };
13094
+ }
13095
+ return {
13096
+ state: 'output-available',
13097
+ output: options.output
13098
+ };
13099
+ }
13080
13100
  function getToolName(part) {
13081
13101
  if (part.type === 'dynamic-tool') {
13082
13102
  var _part_toolName;
@@ -13114,7 +13134,7 @@
13114
13134
  */ var AbstractChat = /*#__PURE__*/ function() {
13115
13135
  function AbstractChat(param) {
13116
13136
  var _this = this;
13117
- var _param_generateId = param.generateId, generateId$1 = _param_generateId === void 0 ? generateId : _param_generateId, _param_id = param.id, id = _param_id === void 0 ? generateId$1() : _param_id, transport = param.transport, state = param.state, onError = param.onError, onToolCall = param.onToolCall, onFinish = param.onFinish, onData = param.onData, sendAutomaticallyWhen = param.sendAutomaticallyWhen, shouldRepairToolInput = param.shouldRepairToolInput, resolveCancelledToolOutput = param.resolveCancelledToolOutput;
13137
+ var _param_generateId = param.generateId, generateId$1 = _param_generateId === void 0 ? generateId : _param_generateId, _param_id = param.id, id = _param_id === void 0 ? generateId$1() : _param_id, transport = param.transport, state = param.state, onError = param.onError, onToolCall = param.onToolCall, onFinish = param.onFinish, onData = param.onData, sendAutomaticallyWhen = param.sendAutomaticallyWhen, shouldRepairToolInput = param.shouldRepairToolInput, shouldRepairRestoredPendingToolPart = param.shouldRepairRestoredPendingToolPart, resolveCancelledToolOutput = param.resolveCancelledToolOutput;
13118
13138
  var _this1 = this;
13119
13139
  _class_call_check(this, AbstractChat);
13120
13140
  _define_property(this, "conversationId", void 0);
@@ -13127,11 +13147,13 @@
13127
13147
  _define_property(this, "onData", void 0);
13128
13148
  _define_property(this, "sendAutomaticallyWhen", void 0);
13129
13149
  _define_property(this, "shouldRepairToolInput", void 0);
13150
+ _define_property(this, "shouldRepairRestoredPendingToolPart", void 0);
13130
13151
  _define_property(this, "resolveCancelledToolOutput", void 0);
13131
13152
  _define_property(this, "activeResponse", null);
13132
13153
  _define_property(this, "latestResponse", null);
13133
13154
  _define_property(this, "responsesByToolCallId", new Map());
13134
13155
  _define_property(this, "responseByMessage", new WeakMap());
13156
+ _define_property(this, "restoredToolCalls", void 0);
13135
13157
  // Once tool ownership is discarded, an identifier-only result cannot prove
13136
13158
  // which response generation submitted it. Scoped submissions remain safe.
13137
13159
  _define_property(this, "acceptsIdentifierOnlyToolResults", true);
@@ -13299,7 +13321,7 @@
13299
13321
  warnInvalidGlobalToolResult(options.toolCallId);
13300
13322
  return Promise.resolve();
13301
13323
  }
13302
- if (!_this.commit(options.toolCallId, options.output, message.id, undefined, message)) {
13324
+ if (!_this.commit(options.toolCallId, getTerminalToolState(options), message.id, undefined, message)) {
13303
13325
  return Promise.resolve();
13304
13326
  }
13305
13327
  return _this.continueResponse();
@@ -13346,6 +13368,7 @@
13346
13368
  this.onData = onData;
13347
13369
  this.sendAutomaticallyWhen = sendAutomaticallyWhen;
13348
13370
  this.shouldRepairToolInput = shouldRepairToolInput;
13371
+ this.shouldRepairRestoredPendingToolPart = shouldRepairRestoredPendingToolPart;
13349
13372
  this.resolveCancelledToolOutput = resolveCancelledToolOutput;
13350
13373
  }
13351
13374
  _create_class(AbstractChat, [
@@ -13518,7 +13541,7 @@
13518
13541
  },
13519
13542
  {
13520
13543
  key: "commit",
13521
- value: function commit(toolCallId, output, messageId, response, expectedMessage) {
13544
+ value: function commit(toolCallId, terminalState, messageId, response, expectedMessage) {
13522
13545
  var isTargetPart = function isTargetPart(part) {
13523
13546
  return 'toolCallId' in part && part.toolCallId === toolCallId;
13524
13547
  };
@@ -13533,10 +13556,7 @@
13533
13556
  return false;
13534
13557
  }
13535
13558
  var updatedParts = _to_consumable_array(message.parts);
13536
- updatedParts[partIndex] = withTerminalToolState(part, {
13537
- state: 'output-available',
13538
- output: output
13539
- });
13559
+ updatedParts[partIndex] = withTerminalToolState(part, terminalState);
13540
13560
  var updatedMessage = _object_spread_props(_object_spread({}, message), {
13541
13561
  parts: updatedParts
13542
13562
  });
@@ -13544,6 +13564,60 @@
13544
13564
  return true;
13545
13565
  }
13546
13566
  },
13567
+ {
13568
+ key: "captureRestoredToolCalls",
13569
+ value: function captureRestoredToolCalls() {
13570
+ var restoredToolCalls = new Map();
13571
+ this.messages.forEach(function(message) {
13572
+ message.parts.forEach(function(part) {
13573
+ var _restoredToolCalls_get;
13574
+ if (!isPendingToolPart(part)) return;
13575
+ var toolCallIds = (_restoredToolCalls_get = restoredToolCalls.get(message.id)) !== null && _restoredToolCalls_get !== void 0 ? _restoredToolCalls_get : new Set();
13576
+ toolCallIds.add(part.toolCallId);
13577
+ restoredToolCalls.set(message.id, toolCallIds);
13578
+ });
13579
+ });
13580
+ this.restoredToolCalls = restoredToolCalls;
13581
+ }
13582
+ },
13583
+ {
13584
+ key: "clearRestoredToolCalls",
13585
+ value: function clearRestoredToolCalls() {
13586
+ this.restoredToolCalls = undefined;
13587
+ }
13588
+ },
13589
+ {
13590
+ key: "repairRestoredPendingToolParts",
13591
+ value: function repairRestoredPendingToolParts() {
13592
+ var _this = this;
13593
+ var shouldRepairRestoredPendingToolPart = this.shouldRepairRestoredPendingToolPart;
13594
+ if (!shouldRepairRestoredPendingToolPart) return;
13595
+ this.messages.forEach(function(message, messageIndex) {
13596
+ message.parts.forEach(function(part) {
13597
+ var _this_restoredToolCalls_get;
13598
+ if (!isPendingToolPart(part)) return;
13599
+ if (_this.restoredToolCalls && !((_this_restoredToolCalls_get = _this.restoredToolCalls.get(message.id)) === null || _this_restoredToolCalls_get === void 0 ? void 0 : _this_restoredToolCalls_get.has(part.toolCallId))) {
13600
+ return;
13601
+ }
13602
+ var shouldRepair = false;
13603
+ try {
13604
+ shouldRepair = shouldRepairRestoredPendingToolPart({
13605
+ toolName: getToolName(part),
13606
+ toolCallId: part.toolCallId,
13607
+ input: 'input' in part ? part.input : undefined
13608
+ });
13609
+ } catch (unused) {
13610
+ return;
13611
+ }
13612
+ if (!shouldRepair) return;
13613
+ _this.commit(part.toolCallId, {
13614
+ state: 'output-error',
13615
+ errorText: part.state === 'input-streaming' ? RESTORED_TOOL_INPUT_ERROR_TEXT : RESTORED_TOOL_CALL_ERROR_TEXT
13616
+ }, message.id, undefined, _this.messages[messageIndex]);
13617
+ });
13618
+ });
13619
+ }
13620
+ },
13547
13621
  {
13548
13622
  key: "getOutboundMessages",
13549
13623
  value: /**
@@ -13678,18 +13752,18 @@
13678
13752
  },
13679
13753
  {
13680
13754
  key: "submitToolResult",
13681
- value: function submitToolResult(response, param) {
13755
+ value: function submitToolResult(response, options) {
13682
13756
  var _this = this;
13683
- var toolCallId = param.toolCallId, output = param.output, messageId = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : response === null || response === void 0 ? void 0 : response.messageId, expectedMessage = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : messageId ? this.messages.find(function(message) {
13757
+ var messageId = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : response === null || response === void 0 ? void 0 : response.messageId, expectedMessage = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : messageId ? this.messages.find(function(message) {
13684
13758
  return message.id === messageId;
13685
13759
  }) : undefined;
13686
13760
  if (response === null || response === void 0 ? void 0 : response.isRetired) return Promise.resolve();
13687
13761
  var commitResult = function commitResult() {
13688
- if (!_this.commit(toolCallId, output, messageId, response, expectedMessage)) {
13762
+ if (!_this.commit(options.toolCallId, getTerminalToolState(options), messageId, response, expectedMessage)) {
13689
13763
  return Promise.resolve();
13690
13764
  }
13691
- if (response === null || response === void 0 ? void 0 : response.requiredToolCallIds.has(toolCallId)) {
13692
- response.resolvedToolCallIds.add(toolCallId);
13765
+ if (response === null || response === void 0 ? void 0 : response.requiredToolCallIds.has(options.toolCallId)) {
13766
+ response.resolvedToolCallIds.add(options.toolCallId);
13693
13767
  }
13694
13768
  return _this.continueResponse(response);
13695
13769
  };
@@ -14073,13 +14147,16 @@
14073
14147
  _this.responsesByToolCallId.set(chunk.toolCallId, owners);
14074
14148
  response.pendingToolCallbacks++;
14075
14149
  try {
14150
+ var _this_restoredToolCalls_get, _this_restoredToolCalls;
14151
+ (_this_restoredToolCalls = _this.restoredToolCalls) === null || _this_restoredToolCalls === void 0 ? void 0 : (_this_restoredToolCalls_get = _this_restoredToolCalls.get(currentMessage.id)) === null || _this_restoredToolCalls_get === void 0 ? void 0 : _this_restoredToolCalls_get.delete(chunk.toolCallId);
14076
14152
  var result = _this.onToolCall({
14077
14153
  toolCall: {
14078
14154
  toolName: chunk.toolName,
14079
14155
  toolCallId: chunk.toolCallId,
14080
14156
  input: chunk.input,
14081
14157
  dynamic: 'dynamic' in chunk ? chunk.dynamic : undefined
14082
- }
14158
+ },
14159
+ signal: response.abortController.signal
14083
14160
  }, function(options) {
14084
14161
  return response.isRetired ? Promise.resolve() : _this.submitToolResult(response, options);
14085
14162
  });
@@ -14399,7 +14476,7 @@
14399
14476
  return AbstractChat;
14400
14477
  }();
14401
14478
 
14402
- var _computedKey, _computedKey1, _computedKey2, _computedKey3, _computedKey4, _computedKey5;
14479
+ var _computedKey, _computedKey1, _computedKey2, _computedKey3, _computedKey4, _computedKey5, _computedKey6, _computedKey7;
14403
14480
  var CACHE_KEY = 'instantsearch-chat-initial-messages';
14404
14481
  // Message history is a browser concern, and a server render constructs a Chat
14405
14482
  // too. Reading storage there throws during rendering; the write below only
@@ -14421,8 +14498,8 @@
14421
14498
  }
14422
14499
  });
14423
14500
  }
14424
- _computedKey = '~registerMessagesCallback', _computedKey1 = '~registerStatusCallback', _computedKey2 = '~registerErrorCallback';
14425
- var _computedKey6 = _computedKey, _computedKey7 = _computedKey1, _computedKey8 = _computedKey2;
14501
+ _computedKey = '~persistMessages', _computedKey1 = '~registerMessagesCallback', _computedKey2 = '~registerStatusCallback', _computedKey3 = '~registerErrorCallback';
14502
+ var _computedKey8 = _computedKey, _computedKey9 = _computedKey1, _computedKey10 = _computedKey2, _computedKey11 = _computedKey3;
14426
14503
  var ChatState = /*#__PURE__*/ function() {
14427
14504
  function ChatState() {
14428
14505
  var _this = this;
@@ -14434,6 +14511,7 @@
14434
14511
  _define_property(this, "_messagesCallbacks", new Set());
14435
14512
  _define_property(this, "_statusCallbacks", new Set());
14436
14513
  _define_property(this, "_errorCallbacks", new Set());
14514
+ _define_property(this, "persistenceKey", void 0);
14437
14515
  _define_property(this, "pushMessage", function(message) {
14438
14516
  _this._messages = _this._messages.concat(message);
14439
14517
  _this._callMessagesCallbacks();
@@ -14452,20 +14530,31 @@
14452
14530
  _define_property(this, "snapshot", function(thing) {
14453
14531
  return JSON.parse(JSON.stringify(thing));
14454
14532
  });
14455
- _define_property(this, _computedKey6, function(onChange) {
14533
+ _define_property(this, _computedKey8, function() {
14534
+ var persistenceKey = _this.persistenceKey;
14535
+ if (!persistenceKey) return;
14536
+ safelyRunOnBrowser(function() {
14537
+ try {
14538
+ sessionStorage.setItem(persistenceKey, JSON.stringify(_this.messages));
14539
+ } catch (e) {
14540
+ // Do nothing if sessionStorage is not available or full
14541
+ }
14542
+ });
14543
+ });
14544
+ _define_property(this, _computedKey9, function(onChange) {
14456
14545
  var callback = onChange;
14457
14546
  _this._messagesCallbacks.add(callback);
14458
14547
  return function() {
14459
14548
  _this._messagesCallbacks.delete(callback);
14460
14549
  };
14461
14550
  });
14462
- _define_property(this, _computedKey7, function(onChange) {
14551
+ _define_property(this, _computedKey10, function(onChange) {
14463
14552
  _this._statusCallbacks.add(onChange);
14464
14553
  return function() {
14465
14554
  _this._statusCallbacks.delete(onChange);
14466
14555
  };
14467
14556
  });
14468
- _define_property(this, _computedKey8, function(onChange) {
14557
+ _define_property(this, _computedKey11, function(onChange) {
14469
14558
  _this._errorCallbacks.add(onChange);
14470
14559
  return function() {
14471
14560
  _this._errorCallbacks.delete(onChange);
@@ -14496,19 +14585,14 @@
14496
14585
  if (!persistence) {
14497
14586
  return;
14498
14587
  }
14499
- var saveMessagesInLocalStorage = function saveMessagesInLocalStorage() {
14588
+ this.persistenceKey = CACHE_KEY + (id ? "-".concat(id) : '');
14589
+ var saveMessagesInSessionStorage = function saveMessagesInSessionStorage() {
14500
14590
  if (_this.status === 'ready') {
14501
- safelyRunOnBrowser(function() {
14502
- try {
14503
- sessionStorage.setItem(CACHE_KEY + (id ? "-".concat(id) : ''), JSON.stringify(_this.messages));
14504
- } catch (e) {
14505
- // Do nothing if sessionStorage is not available or full
14506
- }
14507
- });
14591
+ _this['~persistMessages']();
14508
14592
  }
14509
14593
  };
14510
- this['~registerMessagesCallback'](saveMessagesInLocalStorage);
14511
- this['~registerStatusCallback'](saveMessagesInLocalStorage);
14594
+ this['~registerMessagesCallback'](saveMessagesInSessionStorage);
14595
+ this['~registerStatusCallback'](saveMessagesInSessionStorage);
14512
14596
  }
14513
14597
  _create_class(ChatState, [
14514
14598
  {
@@ -14544,8 +14628,8 @@
14544
14628
  ]);
14545
14629
  return ChatState;
14546
14630
  }();
14547
- _computedKey3 = '~registerMessagesCallback', _computedKey4 = '~registerStatusCallback', _computedKey5 = '~registerErrorCallback';
14548
- var _computedKey9 = _computedKey3, _computedKey10 = _computedKey4, _computedKey11 = _computedKey5;
14631
+ _computedKey4 = '~repairRestoredPendingToolParts', _computedKey5 = '~registerMessagesCallback', _computedKey6 = '~registerStatusCallback', _computedKey7 = '~registerErrorCallback';
14632
+ var _computedKey12 = _computedKey4, _computedKey13 = _computedKey5, _computedKey14 = _computedKey6, _computedKey15 = _computedKey7;
14549
14633
  var Chat = /*#__PURE__*/ function(AbstractChat) {
14550
14634
  _inherits(Chat, AbstractChat);
14551
14635
  function Chat(_0) {
@@ -14561,14 +14645,25 @@
14561
14645
  _object_spread_props(_object_spread({}, init), {
14562
14646
  state: state
14563
14647
  })
14564
- ]), _define_property(_this, "_state", void 0), _define_property(_this, _computedKey9, function(onChange) {
14648
+ ]), _define_property(_this, "_state", void 0), _define_property(_this, "hasRestoredMessages", false), _define_property(_this, _computedKey12, function() {
14649
+ if (!_this.hasRestoredMessages) return;
14650
+ _this.hasRestoredMessages = false;
14651
+ _this.repairRestoredPendingToolParts();
14652
+ _this.clearRestoredToolCalls();
14653
+ _this._state['~persistMessages']();
14654
+ }), _define_property(_this, _computedKey13, function(onChange) {
14565
14655
  return _this._state['~registerMessagesCallback'](onChange);
14566
- }), _define_property(_this, _computedKey10, function(onChange) {
14656
+ }), _define_property(_this, _computedKey14, function(onChange) {
14567
14657
  return _this._state['~registerStatusCallback'](onChange);
14568
- }), _define_property(_this, _computedKey11, function(onChange) {
14658
+ }), _define_property(_this, _computedKey15, function(onChange) {
14569
14659
  return _this._state['~registerErrorCallback'](onChange);
14570
14660
  });
14571
14661
  _this._state = state;
14662
+ if (messages === undefined && persistence) {
14663
+ _this.hasRestoredMessages = true;
14664
+ _this.captureRestoredToolCalls();
14665
+ _this.repairRestoredPendingToolParts();
14666
+ }
14572
14667
  return _this;
14573
14668
  }
14574
14669
  return Chat;
@@ -14826,6 +14921,9 @@
14826
14921
  name: 'chat',
14827
14922
  connector: true
14828
14923
  });
14924
+ var DEFAULT_TOOL_TIMEOUT = 20000;
14925
+ var TOOL_TIMEOUT_ERROR_TEXT = 'The tool call timed out before a result was received. The operation may have completed.';
14926
+ var TOOL_ABORTED_ERROR_TEXT = 'The tool call was cancelled before a result was received.';
14829
14927
  var OPEN_STATE_CACHE_KEY$1 = 'instantsearch-chat-open-state';
14830
14928
  function normalizePersistence(persistence, hasCustomChat) {
14831
14929
  if (hasCustomChat) {
@@ -14983,7 +15081,7 @@
14983
15081
  var hasValidatedEntryPoints = false;
14984
15082
  var agentId = 'agentId' in options ? options.agentId : undefined;
14985
15083
  // Collected here rather than by the tool that searched: that tool renders
14986
- // nothing while display-results presents its records, and a record has to
15084
+ // nothing while Grouped Results presents its records, and a record has to
14987
15085
  // outlive the render that produced it.
14988
15086
  var records = createChatRecordsStore();
14989
15087
  var collectRecords = function collectRecords() {
@@ -15015,28 +15113,6 @@
15015
15113
  var _findSuggestionsPart;
15016
15114
  return (_findSuggestionsPart = findSuggestionsPart(findLastAssistantMessage(messages))) === null || _findSuggestionsPart === void 0 ? void 0 : _findSuggestionsPart.data.suggestions;
15017
15115
  };
15018
- // "Still coming" has to be inferred: the turn is running and has no
15019
- // `data-suggestions` part yet. Expecting any at all needs evidence, or an
15020
- // agent that never sends them would sit under a placeholder forever.
15021
- var getSuggestionsStatus = function getSuggestionsStatus(messages) {
15022
- var _lastAssistantMessage_metadata;
15023
- var status = _chatInstance.status;
15024
- if (status !== 'submitted' && status !== 'streaming') {
15025
- return 'idle';
15026
- }
15027
- var lastAssistantMessage = findLastAssistantMessage(messages);
15028
- if (findSuggestionsPart(lastAssistantMessage)) {
15029
- return 'idle';
15030
- }
15031
- var declaresSuggestions = (lastAssistantMessage === null || lastAssistantMessage === void 0 ? void 0 : (_lastAssistantMessage_metadata = lastAssistantMessage.metadata) === null || _lastAssistantMessage_metadata === void 0 ? void 0 : _lastAssistantMessage_metadata.suggestionsEnabled) === true;
15032
- if (declaresSuggestions) {
15033
- return 'loading';
15034
- }
15035
- var hasSuggestionsHistory = messages.some(function(message) {
15036
- return message !== lastAssistantMessage && message.role === 'assistant' && Boolean(findSuggestionsPart(message));
15037
- });
15038
- return hasSuggestionsHistory ? 'loading' : 'idle';
15039
- };
15040
15116
  var setMessages = function setMessages(messagesParam) {
15041
15117
  if (typeof messagesParam === 'function') {
15042
15118
  messagesParam = messagesParam(_chatInstance.messages);
@@ -15173,7 +15249,8 @@
15173
15249
  if (!transport) {
15174
15250
  throw new Error(withUsage$q('You need to provide either an `agentId` or a `transport`.'));
15175
15251
  }
15176
- return new Chat(_object_spread_props(_object_spread({}, options), {
15252
+ var canRepairRestoredPendingToolParts = !resume;
15253
+ var chat = new Chat(_object_spread_props(_object_spread({}, options), {
15177
15254
  persistence: normalizedPersistence.messages,
15178
15255
  sendAutomaticallyWhen: sendAutomaticallyWhen,
15179
15256
  transport: transport,
@@ -15182,6 +15259,11 @@
15182
15259
  if (!tool) return true;
15183
15260
  return Boolean(tool.streamInput);
15184
15261
  },
15262
+ shouldRepairRestoredPendingToolPart: function shouldRepairRestoredPendingToolPart(param) {
15263
+ var toolName = param.toolName;
15264
+ var tool = findTool(toolName, tools);
15265
+ return Boolean(canRepairRestoredPendingToolParts && (tool === null || tool === void 0 ? void 0 : tool.onToolCall) && tool.timeout !== false);
15266
+ },
15185
15267
  resolveCancelledToolOutput: function resolveCancelledToolOutput(param) {
15186
15268
  var toolName = param.toolName, toolCallId = param.toolCallId, input = param.input;
15187
15269
  var _findTool;
@@ -15201,7 +15283,7 @@
15201
15283
  }
15202
15284
  },
15203
15285
  onToolCall: function onToolCall(param, submitToolResult) {
15204
- var toolCall = param.toolCall;
15286
+ var toolCall = param.toolCall, signal = param.signal;
15205
15287
  var tool = findTool(toolCall.toolName, tools);
15206
15288
  if (!tool) {
15207
15289
  return submitToolResult({
@@ -15211,21 +15293,103 @@
15211
15293
  });
15212
15294
  }
15213
15295
  if (tool.onToolCall) {
15214
- var addToolResult = function addToolResult(param) {
15215
- var output = param.output;
15216
- return submitToolResult({
15217
- output: output,
15296
+ var toolAbortController = new AbortController();
15297
+ var timeoutId;
15298
+ var settled = false;
15299
+ var resolveExecution;
15300
+ var rejectExecution;
15301
+ var execution = new Promise(function(resolve, reject) {
15302
+ resolveExecution = resolve;
15303
+ rejectExecution = reject;
15304
+ });
15305
+ var cleanup = function cleanup() {
15306
+ if (timeoutId !== undefined) {
15307
+ clearTimeout(timeoutId);
15308
+ }
15309
+ signal.removeEventListener('abort', abortToolCall);
15310
+ };
15311
+ var addToolResult = function addToolResult(options) {
15312
+ if (settled) return Promise.resolve();
15313
+ settled = true;
15314
+ cleanup();
15315
+ var submission = submitToolResult(_object_spread_props(_object_spread({}, options), {
15218
15316
  tool: toolCall.toolName,
15219
15317
  toolCallId: toolCall.toolCallId
15318
+ }));
15319
+ submission.then(resolveExecution, rejectExecution);
15320
+ return submission;
15321
+ };
15322
+ var addToolError = function addToolError(error) {
15323
+ var errorText = _instanceof(error, Error) ? error.message : String(error !== null && error !== void 0 ? error : '');
15324
+ return addToolResult({
15325
+ state: 'output-error',
15326
+ errorText: errorText || 'Tool call failed.'
15220
15327
  });
15221
15328
  };
15222
- return tool.onToolCall(_object_spread_props(_object_spread({}, toolCall), {
15223
- addToolResult: addToolResult
15224
- }));
15329
+ function abortToolCall() {
15330
+ var submission = addToolResult({
15331
+ state: 'output-error',
15332
+ errorText: TOOL_ABORTED_ERROR_TEXT
15333
+ });
15334
+ toolAbortController.abort();
15335
+ void submission.catch(function() {
15336
+ return undefined;
15337
+ });
15338
+ }
15339
+ if (signal.aborted) {
15340
+ abortToolCall();
15341
+ return execution;
15342
+ }
15343
+ signal.addEventListener('abort', abortToolCall, {
15344
+ once: true
15345
+ });
15346
+ if (tool.timeout !== false) {
15347
+ var _tool_timeout;
15348
+ timeoutId = setTimeout(function() {
15349
+ var submission = addToolResult({
15350
+ state: 'output-error',
15351
+ errorText: TOOL_TIMEOUT_ERROR_TEXT
15352
+ });
15353
+ toolAbortController.abort();
15354
+ void submission.catch(function() {
15355
+ return undefined;
15356
+ });
15357
+ }, (_tool_timeout = tool.timeout) !== null && _tool_timeout !== void 0 ? _tool_timeout : DEFAULT_TOOL_TIMEOUT);
15358
+ }
15359
+ var toolExecution;
15360
+ try {
15361
+ toolExecution = tool.onToolCall(_object_spread_props(_object_spread({}, toolCall), {
15362
+ addToolResult: addToolResult,
15363
+ signal: toolAbortController.signal
15364
+ }));
15365
+ } catch (error) {
15366
+ return addToolError(error);
15367
+ }
15368
+ var returnedExecution = Promise.resolve(toolExecution).catch(addToolError);
15369
+ if (tool.timeout === false) {
15370
+ return Promise.race([
15371
+ returnedExecution.then(cleanup),
15372
+ execution
15373
+ ]);
15374
+ }
15375
+ void returnedExecution.catch(function() {
15376
+ return undefined;
15377
+ });
15378
+ return execution;
15225
15379
  }
15226
15380
  return Promise.resolve();
15227
15381
  }
15228
15382
  }));
15383
+ if (resume) {
15384
+ var resumeStream = chat.resumeStream;
15385
+ chat.resumeStream = function(requestOptions) {
15386
+ return resumeStream(requestOptions).finally(function() {
15387
+ canRepairRestoredPendingToolParts = true;
15388
+ chat['~repairRestoredPendingToolParts']();
15389
+ });
15390
+ };
15391
+ }
15392
+ return chat;
15229
15393
  };
15230
15394
  return {
15231
15395
  $$type: 'ais.chat',
@@ -15436,7 +15600,6 @@
15436
15600
  '~isOpenStatePersistenceEnabled': normalizedPersistence.open,
15437
15601
  setMessages: setMessages,
15438
15602
  suggestions: getSuggestionsFromMessages(_chatInstance.messages),
15439
- suggestionsStatus: getSuggestionsStatus(_chatInstance.messages),
15440
15603
  clearMessages: clearMessages,
15441
15604
  tools: toolsWithAddToolResult,
15442
15605
  records: records,
@@ -16091,9 +16254,6 @@
16091
16254
  return null;
16092
16255
  }
16093
16256
  }
16094
- function buildSuggestionMessage(suggestion) {
16095
- return "The user clicked this on-page suggestion. Use the current page context first, then search only if needed.\n\nSuggestion: ".concat(suggestion);
16096
- }
16097
16257
  function stripInternalHitMetadata(hit) {
16098
16258
  var clean = {};
16099
16259
  Object.keys(hit).forEach(function(key) {
@@ -16167,6 +16327,9 @@
16167
16327
  // the widget is unmounted; this guard stops those late callbacks from
16168
16328
  // calling `renderFn` into a torn-down container.
16169
16329
  var disposed = false;
16330
+ // Whether the "is a chat widget mounted on this index?" question has been
16331
+ // settled — see `validateChat`.
16332
+ var hasValidatedChat = false;
16170
16333
  // True between a state-signature change and the debounced refetch that
16171
16334
  // follows it. While pending, the search state has already moved on, so a
16172
16335
  // still-in-flight request from the previous state must not paint its
@@ -16199,21 +16362,26 @@
16199
16362
  };
16200
16363
  var sendToChat = function sendToChat(renderOptions) {
16201
16364
  return function(prompt) {
16202
- var _ref, _ref1;
16365
+ var _ref, _getLatestResults;
16203
16366
  var chatRenderState = getChatRenderState(renderOptions);
16204
16367
  if (!chatRenderState || !chatRenderState.sendMessage) {
16205
16368
  return false;
16206
16369
  }
16207
- var results = (_ref = (_ref1 = latestRenderOptions === null || latestRenderOptions === void 0 ? void 0 : latestRenderOptions.results) !== null && _ref1 !== void 0 ? _ref1 : 'results' in renderOptions ? renderOptions.results : null) !== null && _ref !== void 0 ? _ref : null;
16370
+ var results = (_ref = (_getLatestResults = getLatestResults()) !== null && _getLatestResults !== void 0 ? _getLatestResults : 'results' in renderOptions ? renderOptions.results : null) !== null && _ref !== void 0 ? _ref : null;
16208
16371
  return openChat(chatRenderState, {
16209
- message: buildSuggestionMessage(prompt),
16372
+ message: prompt,
16210
16373
  referer: 'prompt-suggestions-widget',
16211
16374
  turnContext: buildTurnContext(results)
16212
16375
  });
16213
16376
  };
16214
16377
  };
16215
- var resolvePageContext = function resolvePageContext(results) {
16216
- var resolvedContext = typeof context === 'function' ? context() : context;
16378
+ // `context` may be a function, so the option alone says nothing about what
16379
+ // a given fetch actually has to send. Resolve it once per fetch and let
16380
+ // callers read the value rather than the option.
16381
+ var resolveContext = function resolveContext() {
16382
+ return typeof context === 'function' ? context() : context;
16383
+ };
16384
+ var buildPageContext = function buildPageContext(resolvedContext, results) {
16217
16385
  // Explicit context replaces auto-extraction; otherwise derive it from
16218
16386
  // the current search state. The task's server-owned instructions decide
16219
16387
  // how to interpret the shape — the client doesn't label it.
@@ -16232,15 +16400,11 @@
16232
16400
  hitsSample: transformHits(results.hits)
16233
16401
  });
16234
16402
  };
16235
- var buildInput = function buildInput(results) {
16236
- var _resolvePageContext;
16237
- return (_resolvePageContext = resolvePageContext(results)) !== null && _resolvePageContext !== void 0 ? _resolvePageContext : {};
16238
- };
16239
16403
  // The same page context, flattened for the chat handoff: `turnContext` is
16240
16404
  // a flat `Record<string, string>` per the Agent Studio contract, so
16241
16405
  // non-string values (e.g. `hitsSample`) are serialized.
16242
16406
  var buildTurnContext = function buildTurnContext(results) {
16243
- var pageContext = resolvePageContext(results);
16407
+ var pageContext = buildPageContext(resolveContext(), results);
16244
16408
  if (!pageContext) {
16245
16409
  return undefined;
16246
16410
  }
@@ -16256,6 +16420,16 @@
16256
16420
  });
16257
16421
  return entries.length > 0 ? Object.fromEntries(entries) : undefined;
16258
16422
  };
16423
+ // `latestRenderOptions` may be the `init()` options, which carry no
16424
+ // `results` key at all, so the read has to be narrowed rather than
16425
+ // optional-chained.
16426
+ var getLatestResults = function getLatestResults() {
16427
+ var _latestRenderOptions_results;
16428
+ if (!latestRenderOptions || !('results' in latestRenderOptions)) {
16429
+ return null;
16430
+ }
16431
+ return (_latestRenderOptions_results = latestRenderOptions.results) !== null && _latestRenderOptions_results !== void 0 ? _latestRenderOptions_results : null;
16432
+ };
16259
16433
  var renderOutward = function renderOutward(renderOptions) {
16260
16434
  if (disposed) return;
16261
16435
  renderFn(_object_spread_props(_object_spread({}, getWidgetRenderState(renderOptions)), {
@@ -16281,13 +16455,20 @@
16281
16455
  };
16282
16456
  var fetchAndRender = function fetchAndRender(results, renderOptions) {
16283
16457
  var _ref = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, _ref_force = _ref.force, force = _ref_force === void 0 ? false : _ref_force;
16458
+ var _buildPageContext;
16284
16459
  var _results_hits;
16285
16460
  if (disposed || !tasksState) return;
16286
16461
  var hadDroppedInnerRender = droppedInnerRender;
16287
16462
  refetchPending = false;
16288
16463
  droppedInnerRender = false;
16289
- var hasContext = context !== undefined;
16290
- if (!hasContext && !(results === null || results === void 0 ? void 0 : (_results_hits = results.hits) === null || _results_hits === void 0 ? void 0 : _results_hits.length)) {
16464
+ var resolvedContext = resolveContext();
16465
+ var input = (_buildPageContext = buildPageContext(resolvedContext, results)) !== null && _buildPageContext !== void 0 ? _buildPageContext : {};
16466
+ // Two ways there is nothing worth sending: no context for this fetch and
16467
+ // no hits to derive one from, or a context that resolved to something
16468
+ // empty. The first reads the resolved value rather than the option, so
16469
+ // `context: () => undefined` is gated exactly like an omitted `context`.
16470
+ // Sending an empty input spends a model call on no information.
16471
+ if (resolvedContext === undefined && !(results === null || results === void 0 ? void 0 : (_results_hits = results.hits) === null || _results_hits === void 0 ? void 0 : _results_hits.length) || Object.keys(input).length === 0) {
16291
16472
  tasksState.invalidate();
16292
16473
  suggestions = [];
16293
16474
  isLoading = false;
@@ -16296,7 +16477,6 @@
16296
16477
  renderOutward(renderOptions);
16297
16478
  return;
16298
16479
  }
16299
- var input = buildInput(results);
16300
16480
  var payload = taskPayloadKey(input);
16301
16481
  // A moved search state does not always mean a different question: with an
16302
16482
  // explicit `context` the payload ignores the results entirely, so a new
@@ -16321,10 +16501,14 @@
16321
16501
  };
16322
16502
  var refresh = function refresh() {
16323
16503
  if (isLoading) return;
16324
- var results = latestRenderOptions === null || latestRenderOptions === void 0 ? void 0 : latestRenderOptions.results;
16325
- if (!results || !latestRenderOptions) return;
16504
+ if (!latestRenderOptions) return;
16505
+ var results = getLatestResults();
16326
16506
  clearTimeout(debounceTimer);
16327
- lastStateSignature = getStateSignature(results);
16507
+ // Only meaningful with results: without them there is no signature for a
16508
+ // later automatic fetch to compare against.
16509
+ if (results) {
16510
+ lastStateSignature = getStateSignature(results);
16511
+ }
16328
16512
  fetchAndRender(results, latestRenderOptions, {
16329
16513
  force: true
16330
16514
  });
@@ -16338,12 +16522,17 @@
16338
16522
  var chatRenderState = getChatRenderState(renderOptions);
16339
16523
  var isChatBusy$1 = chatRenderState ? !chatRenderState.sendMessage || isChatBusy(chatRenderState) : false;
16340
16524
  var send = sendToChat(renderOptions);
16525
+ // `sendToChat` is withheld only once the mount window has closed: a chat
16526
+ // widget further down a React tree is added after this widget's `init`,
16527
+ // so until `validateChat` runs its absence is not yet conclusive and
16528
+ // withholding the handler would make a valid setup look broken.
16529
+ var canSendToChat = Boolean(chatRenderState === null || chatRenderState === void 0 ? void 0 : chatRenderState.sendMessage) || !hasValidatedChat;
16341
16530
  return {
16342
16531
  suggestions: transformed,
16343
16532
  isLoading: isLoading,
16344
16533
  error: error,
16345
- onSuggestionClick: send,
16346
- sendToChat: send,
16534
+ onSuggestionClick: canSendToChat ? send : noop,
16535
+ sendToChat: canSendToChat ? send : undefined,
16347
16536
  refresh: refresh,
16348
16537
  isChatBusy: isChatBusy$1,
16349
16538
  widgetParams: widgetParams
@@ -16366,6 +16555,24 @@
16366
16555
  }
16367
16556
  adoptInnerState(renderState);
16368
16557
  };
16558
+ // Deferred because a chat widget can be registered after this one: React
16559
+ // adds widgets in mount order, so a `chat` further down the tree only
16560
+ // lands after this widget's `init` has run. Until this closes the window,
16561
+ // `sendToChat` is handed out optimistically.
16562
+ var validateChat = defer(function(renderOptions) {
16563
+ var _getChatRenderState;
16564
+ if (hasValidatedChat) return;
16565
+ hasValidatedChat = true;
16566
+ if ((_getChatRenderState = getChatRenderState(renderOptions)) === null || _getChatRenderState === void 0 ? void 0 : _getChatRenderState.sendMessage) return;
16567
+ // A render may already have gone out with the optimistic `sendToChat`;
16568
+ // re-render so the widget layer sees the settled answer. The `init()`
16569
+ // options don't count: nothing has painted yet, so the next render
16570
+ // carries it — and a mount that never renders results shows no pills
16571
+ // to mislead anyone.
16572
+ if (latestRenderOptions && 'results' in latestRenderOptions) {
16573
+ renderOutward(latestRenderOptions);
16574
+ }
16575
+ });
16369
16576
  var tasksParams;
16370
16577
  if (agentId) {
16371
16578
  tasksParams = {
@@ -16388,12 +16595,37 @@
16388
16595
  var tasksWidget = connectTasks(handleInnerRender, noop)(tasksParams);
16389
16596
  return {
16390
16597
  $$type: 'ais.promptSuggestions',
16598
+ // Clicking a suggestion opens the chat, so this widget counts as an
16599
+ // entry point for `connectChat`'s trigger validation.
16600
+ opensChat: true,
16391
16601
  init: function init(initOptions) {
16392
16602
  var instantSearchInstance = initOptions.instantSearchInstance;
16393
16603
  tasksWidget.init(initOptions);
16604
+ // Set after the inner init so its initial no-op render is still
16605
+ // ignored, and before the first outward render so `refresh()` has a
16606
+ // render target even on a mount where `render()` never sees results.
16607
+ latestRenderOptions = initOptions;
16608
+ validateChat(initOptions);
16394
16609
  renderFn(_object_spread_props(_object_spread({}, getWidgetRenderState(initOptions)), {
16395
16610
  instantSearchInstance: instantSearchInstance
16396
16611
  }), true);
16612
+ // With an explicit `context` the payload never reads the results, so
16613
+ // waiting for a search is waiting on something the request does not
16614
+ // use — and a page that triggers no search (a `searchFunction` query
16615
+ // gate, or a mount made only for the widgets) would wait forever.
16616
+ // Fetch here instead, after the first render so the `isFirstRender`
16617
+ // one still arrives first.
16618
+ //
16619
+ // There are no results yet by definition, so "is there anything to
16620
+ // send" reduces to "did the context resolve to something". Checking it
16621
+ // here rather than letting `fetchAndRender` reject the call keeps init
16622
+ // out of the "nothing to send" branch, whose `invalidate()` would add
16623
+ // two outward renders to every mount that has no context — leaving the
16624
+ // auto-extracted path, the one that does need results, untouched.
16625
+ var initialContext = resolveContext();
16626
+ if (initialContext && Object.keys(initialContext).length > 0) {
16627
+ fetchAndRender(null, initOptions);
16628
+ }
16397
16629
  },
16398
16630
  render: function render(renderOptions) {
16399
16631
  var results = renderOptions.results, instantSearchInstance = renderOptions.instantSearchInstance;
@@ -16411,8 +16643,9 @@
16411
16643
  error = undefined;
16412
16644
  clearTimeout(debounceTimer);
16413
16645
  debounceTimer = setTimeout(function() {
16414
- if (latestRenderOptions === null || latestRenderOptions === void 0 ? void 0 : latestRenderOptions.results) {
16415
- fetchAndRender(latestRenderOptions.results, latestRenderOptions);
16646
+ var latestResults = getLatestResults();
16647
+ if (latestResults && latestRenderOptions) {
16648
+ fetchAndRender(latestResults, latestRenderOptions);
16416
16649
  }
16417
16650
  }, DEBOUNCE_MS);
16418
16651
  }
@@ -16423,6 +16656,7 @@
16423
16656
  dispose: function dispose(disposeOptions) {
16424
16657
  disposed = true;
16425
16658
  clearTimeout(debounceTimer);
16659
+ validateChat.cancel();
16426
16660
  tasksWidget.dispose(disposeOptions);
16427
16661
  unmountFn();
16428
16662
  },