react-instantsearch-core 7.46.0 → 7.47.0

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.46.0 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
1
+ /*! React InstantSearch Core 7.47.0 | © 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.46.0';
27
+ var version$2 = '7.47.0';
28
28
 
29
29
  function _define_property(obj, key, value) {
30
30
  if (key in obj) {
@@ -6728,23 +6728,33 @@
6728
6728
  }
6729
6729
 
6730
6730
  var nextMicroTask = Promise.resolve();
6731
- function defer(callback) {
6731
+ function defer(callback, // arguments: the first caller of the window decides what the single run
6732
+ // receives. Pass this to fold every later argument into the pending ones
6733
+ // instead.
6734
+ mergeArguments) {
6732
6735
  var progress = null;
6733
6736
  var cancelled = false;
6737
+ var pendingArgs = null;
6734
6738
  var fn = function fn() {
6735
6739
  for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
6736
6740
  args[_key] = arguments[_key];
6737
6741
  }
6738
6742
  if (progress !== null) {
6743
+ if (mergeArguments && pendingArgs !== null) {
6744
+ pendingArgs = mergeArguments(pendingArgs, args);
6745
+ }
6739
6746
  return;
6740
6747
  }
6748
+ pendingArgs = args;
6741
6749
  progress = nextMicroTask.then(function() {
6742
6750
  progress = null;
6751
+ var runArgs = pendingArgs;
6752
+ pendingArgs = null;
6743
6753
  if (cancelled) {
6744
6754
  cancelled = false;
6745
6755
  return;
6746
6756
  }
6747
- callback.apply(void 0, _to_consumable_array(args));
6757
+ callback.apply(void 0, _to_consumable_array(runArgs));
6748
6758
  });
6749
6759
  };
6750
6760
  fn.wait = function() {
@@ -7642,22 +7652,18 @@
7642
7652
  clearTimeout(cleanupTimerRef.current);
7643
7653
  // Warning: if an unstable function prop is provided, `dequal` is not able
7644
7654
  // to keep its reference and therefore will consider that props did change.
7645
- // This could unsollicitely remove/add the widget, therefore forget its state,
7646
- // and could be a source of confusion.
7655
+ // This unintentionally replaces the widget, which is wasteful (it causes
7656
+ // a search), even though `updateWidget` below keeps its state.
7647
7657
  // If users face this issue, we should advise them to provide stable function
7648
7658
  // references.
7649
7659
  var arePropsEqual = dequal(props, prevPropsRef.current);
7650
- // If props did change, then we execute the cleanup function instantly
7651
- // and then add the widget back. This lets us add the widget without
7660
+ // If props did change, then we replace the widget instantly instead of
7652
7661
  // waiting for the scheduled cleanup function to finish (that we canceled
7653
- // above).
7662
+ // above). `updateWidget` hands the previous widget's `uiState` over to the
7663
+ // new one, so that a parameter change doesn't reset the state the widget
7664
+ // still owns — which would otherwise break routing.
7654
7665
  if (!arePropsEqual) {
7655
- parentIndex.removeWidgets([
7656
- previousWidget
7657
- ]);
7658
- parentIndex.addWidgets([
7659
- widget
7660
- ]);
7666
+ parentIndex.updateWidget(previousWidget, widget);
7661
7667
  }
7662
7668
  }
7663
7669
  return function() {
@@ -8014,6 +8020,11 @@
8014
8020
  return undefined;
8015
8021
  }
8016
8022
 
8023
+ function reduceChildrenUiState(widgets, uiState, widgetUiStateOptions) {
8024
+ return widgets.reduce(function(state, widget) {
8025
+ return widget.getWidgetUiState ? widget.getWidgetUiState(state, widgetUiStateOptions) : state;
8026
+ }, uiState);
8027
+ }
8017
8028
  function createFeedContainer(feedID, parentIndex, instantSearchInstance) {
8018
8029
  var localWidgets = [];
8019
8030
  var initialized = false;
@@ -8215,13 +8226,10 @@
8215
8226
  },
8216
8227
  getWidgetUiState: function getWidgetUiState(uiState) {
8217
8228
  var helper = parentIndex.getHelper();
8218
- var widgetUiStateOptions = {
8229
+ return reduceChildrenUiState(localWidgets, uiState, {
8219
8230
  searchParameters: helper.state,
8220
8231
  helper: helper
8221
- };
8222
- return localWidgets.reduce(function(state, widget) {
8223
- return widget.getWidgetUiState ? widget.getWidgetUiState(state, widgetUiStateOptions) : state;
8224
- }, uiState);
8232
+ });
8225
8233
  },
8226
8234
  getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, param) {
8227
8235
  var uiState = param.uiState;
@@ -8231,6 +8239,73 @@
8231
8239
  }) : params;
8232
8240
  }, searchParameters);
8233
8241
  },
8242
+ updateWidget: function updateWidget(previousWidget, nextWidget) {
8243
+ var helper = parentIndex.getHelper();
8244
+ // The `uiState` the children own, read before the previous widget is
8245
+ // detached, so that the state it owns can be handed over to the next one.
8246
+ var previousUiState = helper ? reduceChildrenUiState(localWidgets, {}, {
8247
+ searchParameters: helper.state,
8248
+ helper: helper
8249
+ }) : {};
8250
+ previousWidget.parent = undefined;
8251
+ nextWidget.parent = container;
8252
+ // The next widget takes the place of the previous one, so that the order
8253
+ // in which children contribute to the search parameters is unchanged.
8254
+ var nextWidgets = localWidgets.slice();
8255
+ var position = nextWidgets.indexOf(previousWidget);
8256
+ if (position === -1) {
8257
+ nextWidgets.push(nextWidget);
8258
+ } else {
8259
+ nextWidgets[position] = nextWidget;
8260
+ }
8261
+ localWidgets = nextWidgets;
8262
+ if (!helper || !initialized) {
8263
+ return container;
8264
+ }
8265
+ // We still dispose the previous widget, for its side effects and so that
8266
+ // it drops the search parameters it declared on the parent helper.
8267
+ var cleanedState = helper.state;
8268
+ if (previousWidget.dispose) {
8269
+ var next = previousWidget.dispose({
8270
+ helper: helper,
8271
+ state: cleanedState,
8272
+ recommendState: helper.recommendState,
8273
+ parent: container
8274
+ });
8275
+ if (next && !_instanceof(next, algoliasearchHelper.RecommendParameters)) {
8276
+ cleanedState = next;
8277
+ }
8278
+ }
8279
+ // We hand the previous `uiState` over to the children, then read the
8280
+ // `uiState` back from them, so that state no mounted child claims anymore
8281
+ // is dropped. This mirrors the index widget's `updateWidget`.
8282
+ var narrowedUiState = reduceChildrenUiState(localWidgets, {}, {
8283
+ searchParameters: container.getWidgetSearchParameters(cleanedState, {
8284
+ uiState: previousUiState
8285
+ }),
8286
+ helper: helper
8287
+ });
8288
+ // The search parameters are then computed again from that narrowed
8289
+ // `uiState`, so that they can't hold state the `uiState` doesn't describe.
8290
+ var newState = container.getWidgetSearchParameters(cleanedState, {
8291
+ uiState: narrowedUiState
8292
+ });
8293
+ if (nextWidget.getRenderState) {
8294
+ var renderState = nextWidget.getRenderState(instantSearchInstance.renderState[container.getIndexId()] || {}, createInitArgs(instantSearchInstance, container, instantSearchInstance._initialUiState));
8295
+ storeRenderState({
8296
+ renderState: renderState,
8297
+ instantSearchInstance: instantSearchInstance,
8298
+ parent: container
8299
+ });
8300
+ }
8301
+ if (nextWidget.init) {
8302
+ nextWidget.init(createInitArgs(instantSearchInstance, container, instantSearchInstance._initialUiState));
8303
+ }
8304
+ if (newState !== helper.state) {
8305
+ helper.setState(newState);
8306
+ }
8307
+ return container;
8308
+ },
8234
8309
  refreshUiState: function refreshUiState() {
8235
8310
  // no-op: FeedContainer doesn't own UI state
8236
8311
  },
@@ -8592,6 +8667,11 @@
8592
8667
  var helper = null;
8593
8668
  var derivedHelper = null;
8594
8669
  var lastValidSearchParameters = null;
8670
+ // The error this index has already rolled back for. Renders also happen for
8671
+ // reasons unrelated to a search (a chat panel opening, a recommend result,
8672
+ // the stalled timer), and rolling back on every one of them would discard
8673
+ // state written after the failed search.
8674
+ var restoredForError;
8595
8675
  var recomputeLocalRequestDependencies = function recomputeLocalRequestDependencies() {
8596
8676
  if (localInstantSearchInstance) {
8597
8677
  recomputeInstantSearchRequestDependencies(localInstantSearchInstance);
@@ -8731,6 +8811,92 @@
8731
8811
  }
8732
8812
  return this;
8733
8813
  },
8814
+ updateWidget: function updateWidget(previousWidget, nextWidget) {
8815
+ if (typeof previousWidget.dispose !== 'function') {
8816
+ throw new Error(withUsage$u('The widget definition expects a `dispose` method.'));
8817
+ }
8818
+ if (typeof nextWidget.init !== 'function' && typeof nextWidget.render !== 'function') {
8819
+ throw new Error(withUsage$u('The widget definition expects a `render` and/or an `init` method.'));
8820
+ }
8821
+ // The `uiState` as it is before the previous widget is detached, so that
8822
+ // the state it owns can be handed over to the next widget.
8823
+ var previousUiState = localUiState;
8824
+ previousWidget.parent = undefined;
8825
+ nextWidget.parent = this;
8826
+ if (!isIndexWidget(nextWidget)) {
8827
+ addWidgetId(nextWidget);
8828
+ }
8829
+ // The next widget takes the place of the previous one, so that the order
8830
+ // in which widgets contribute to the search parameters is unchanged.
8831
+ var nextWidgets = localWidgets.slice();
8832
+ var position = nextWidgets.indexOf(previousWidget);
8833
+ if (position === -1) {
8834
+ nextWidgets.push(nextWidget);
8835
+ } else {
8836
+ nextWidgets[position] = nextWidget;
8837
+ }
8838
+ localWidgets = nextWidgets;
8839
+ recomputeLocalRequestDependencies();
8840
+ if (!localInstantSearchInstance) {
8841
+ return this;
8842
+ }
8843
+ // We still dispose the previous widget, for its side effects. The search
8844
+ // state it returns is only used as a base when shared state isn't preserved
8845
+ // on unmount, like in `removeWidgets`.
8846
+ var disposedState = previousWidget.dispose({
8847
+ helper: helper,
8848
+ state: helper.state,
8849
+ recommendState: helper.recommendState,
8850
+ parent: this
8851
+ });
8852
+ var cleanedRecommendState = _instanceof(disposedState, algoliasearchHelper.RecommendParameters) ? disposedState : helper.recommendState;
8853
+ var cleanedSearchState = disposedState && !_instanceof(disposedState, algoliasearchHelper.RecommendParameters) ? disposedState : helper.state;
8854
+ var initialSearchParameters = localInstantSearchInstance.future.preserveSharedStateOnUnmount ? new algoliasearchHelper.SearchParameters({
8855
+ index: this.getIndexName()
8856
+ }) : cleanedSearchState;
8857
+ // We hand the previous `uiState` over to the next widgets, then read the
8858
+ // `uiState` back from them. Widgets only pick up the state they claim, so
8859
+ // this drops state that no mounted widget owns anymore (an attribute that
8860
+ // changed, for instance) instead of seeding it with `previousUiState`.
8861
+ localUiState = getLocalWidgetsUiState(localWidgets, {
8862
+ searchParameters: getLocalWidgetsSearchParameters(localWidgets, {
8863
+ uiState: previousUiState,
8864
+ initialSearchParameters: initialSearchParameters
8865
+ }),
8866
+ helper: helper
8867
+ });
8868
+ // The search parameters are then computed again from that narrowed
8869
+ // `uiState`, so that they can't hold state the `uiState` doesn't describe.
8870
+ var newState = getLocalWidgetsSearchParameters(localWidgets, {
8871
+ uiState: localUiState,
8872
+ initialSearchParameters: initialSearchParameters
8873
+ });
8874
+ privateHelperSetState(helper, {
8875
+ state: newState,
8876
+ recommendState: getLocalWidgetsRecommendParameters(localWidgets, {
8877
+ uiState: localUiState,
8878
+ initialRecommendParameters: cleanedRecommendState
8879
+ }),
8880
+ _uiState: localUiState
8881
+ });
8882
+ if (nextWidget.getRenderState) {
8883
+ var renderState = nextWidget.getRenderState(localInstantSearchInstance.renderState[this.getIndexId()] || {}, createInitArgs(localInstantSearchInstance, this, localInstantSearchInstance._initialUiState));
8884
+ storeRenderState({
8885
+ renderState: renderState,
8886
+ instantSearchInstance: localInstantSearchInstance,
8887
+ parent: this
8888
+ });
8889
+ }
8890
+ if (nextWidget.init) {
8891
+ nextWidget.init(createInitArgs(localInstantSearchInstance, this, localInstantSearchInstance._initialUiState));
8892
+ }
8893
+ if (isolated) {
8894
+ this.scheduleLocalSearch();
8895
+ } else {
8896
+ localInstantSearchInstance.scheduleSearch();
8897
+ }
8898
+ return this;
8899
+ },
8734
8900
  removeWidgets: function removeWidgets(widgets) {
8735
8901
  var _this = this;
8736
8902
  if (!Array.isArray(widgets)) {
@@ -8982,7 +9148,10 @@
8982
9148
  var instantSearchInstance = param.instantSearchInstance;
8983
9149
  // we can't attach a listener to the error event of search, as the error
8984
9150
  // then would no longer be thrown for global handlers.
8985
- if (instantSearchInstance.status === 'error' && !instantSearchInstance.mainHelper.hasPendingRequests() && lastValidSearchParameters) {
9151
+ if (instantSearchInstance.status !== 'error') {
9152
+ restoredForError = undefined;
9153
+ } else if (instantSearchInstance.error !== restoredForError && !instantSearchInstance.mainHelper.hasPendingRequests() && lastValidSearchParameters) {
9154
+ restoredForError = instantSearchInstance.error;
8986
9155
  helper.setState(lastValidSearchParameters);
8987
9156
  }
8988
9157
  // We only render index widgets if there are no results.
@@ -9249,7 +9418,7 @@
9249
9418
  });
9250
9419
  }
9251
9420
 
9252
- var version = '4.113.0';
9421
+ var version = '4.114.0';
9253
9422
 
9254
9423
  var ANONYMOUS_TOKEN_COOKIE_KEY = '_ALGOLIA';
9255
9424
  function getCookie(name) {
@@ -11161,6 +11330,14 @@
11161
11330
  instantSearchInstance: _this
11162
11331
  });
11163
11332
  _this.emit('render');
11333
+ }, // status reset accumulates instead of letting the first caller decide: a
11334
+ // render scheduled for a reason unrelated to the search must not cancel the
11335
+ // one a search result asks for, or it would strand the status on `loading`.
11336
+ function(param, param1) {
11337
+ var _param = _sliced_to_array(param, 1), tmp = _param[0], shouldResetStatus = tmp === void 0 ? true : tmp, _param1 = _sliced_to_array(param1, 1), tmp1 = _param1[0], nextShouldResetStatus = tmp1 === void 0 ? true : tmp1;
11338
+ return [
11339
+ shouldResetStatus || nextShouldResetStatus
11340
+ ];
11164
11341
  })), _define_property(_this, "onInternalStateChange", defer(function() {
11165
11342
  var nextUiState = _this.mainIndex.getWidgetUiState({});
11166
11343
  _this.middleware.forEach(function(param) {
@@ -12456,25 +12633,31 @@
12456
12633
  * Resolves the tool a message part belongs to, from either a part type
12457
12634
  * (`tool-algolia_search_index`) or a bare tool name.
12458
12635
  *
12459
- * Generic over the tool shape so the renderer, the loader and the connector —
12460
- * which hold different subsets of the tool contract all resolve names the same
12461
- * way.
12636
+ * An exact registration wins. Otherwise only tools whose `matchesToolName`
12637
+ * claims the name are considered, most specific first, for servers that name a
12638
+ * call after the registered tool: the Algolia MCP Server appends the index name
12639
+ * (`algolia_search_index_products`).
12640
+ *
12641
+ * Generic over the tool shape: the renderer, the loader, the widget and the
12642
+ * connector hold different subsets of the tool contract.
12462
12643
  */ var findTool = function findTool(partType, tools) {
12463
12644
  var toolName = startsWith(partType, TOOL_PART_PREFIX) ? partType.slice(TOOL_PART_PREFIX.length) : partType;
12464
12645
  if (tools[toolName]) {
12465
12646
  return tools[toolName];
12466
12647
  }
12467
- // Compatibility shim for tool names suffixed by the index name, as the Algolia
12468
- // MCP Server does (`algolia_search_index_products`). The longest matching key
12469
- // wins, so registering both `foo` and `foo_bar` resolves `foo_bar_products` to
12470
- // `foo_bar` — otherwise the winner would depend on registration order.
12471
- var match;
12472
- Object.keys(tools).forEach(function(key) {
12473
- if (startsWith(toolName, "".concat(key, "_")) && (match === undefined || key.length > match.length)) {
12474
- match = key;
12475
- }
12648
+ var claimants = Object.keys(tools).filter(function(key) {
12649
+ var _tools_key_matchesToolName, _tools_key;
12650
+ return Boolean((_tools_key = tools[key]) === null || _tools_key === void 0 ? void 0 : (_tools_key_matchesToolName = _tools_key.matchesToolName) === null || _tools_key_matchesToolName === void 0 ? void 0 : _tools_key_matchesToolName.call(_tools_key, toolName));
12651
+ });
12652
+ if (claimants.length === 0) {
12653
+ return undefined;
12654
+ }
12655
+ // Most specific claim wins, ties by name, so the winner doesn't depend on
12656
+ // registration order.
12657
+ claimants.sort(function(a, b) {
12658
+ return b.length - a.length || (a < b ? -1 : 1);
12476
12659
  });
12477
- return match === undefined ? undefined : tools[match];
12660
+ return tools[claimants[0]];
12478
12661
  };
12479
12662
 
12480
12663
  var createRecords = function createRecords() {
@@ -12531,11 +12714,75 @@
12531
12714
  return store;
12532
12715
  }
12533
12716
 
12534
- function flat(arr) {
12535
- return arr.reduce(function(acc, array) {
12536
- return acc.concat(array);
12537
- }, []);
12538
- }
12717
+ var tryParseJson = function tryParseJson(value) {
12718
+ try {
12719
+ return JSON.parse(value);
12720
+ } catch (unused) {
12721
+ return undefined;
12722
+ }
12723
+ };
12724
+ var repairPartialJson = function repairPartialJson(value) {
12725
+ var repaired = value.trim();
12726
+ if (!repaired) {
12727
+ return repaired;
12728
+ }
12729
+ var inString = false;
12730
+ var isEscaped = false;
12731
+ var stack = [];
12732
+ for(var index = 0; index < repaired.length; index++){
12733
+ var char = repaired[index];
12734
+ if (inString) {
12735
+ if (isEscaped) {
12736
+ isEscaped = false;
12737
+ } else if (char === '\\') {
12738
+ isEscaped = true;
12739
+ } else if (char === '"') {
12740
+ inString = false;
12741
+ }
12742
+ continue;
12743
+ }
12744
+ if (char === '"') {
12745
+ inString = true;
12746
+ continue;
12747
+ }
12748
+ if (char === '{' || char === '[') {
12749
+ stack.push(char);
12750
+ continue;
12751
+ }
12752
+ if (char === '}' && stack[stack.length - 1] === '{') {
12753
+ stack.pop();
12754
+ continue;
12755
+ }
12756
+ if (char === ']' && stack[stack.length - 1] === '[') {
12757
+ stack.pop();
12758
+ }
12759
+ }
12760
+ if (inString && !isEscaped) {
12761
+ repaired += '"';
12762
+ }
12763
+ repaired = repaired.replace(RegExp(",\\s*$", "u"), '');
12764
+ if (stack.length > 0) {
12765
+ repaired += stack.reverse().map(function(opening) {
12766
+ return opening === '{' ? '}' : ']';
12767
+ }).join('');
12768
+ }
12769
+ return repaired.replace(RegExp(",\\s*([}\\]])", "gu"), '$1');
12770
+ };
12771
+ var parsePartialJson = function parsePartialJson(accumulatedRawJson, fallbackValue) {
12772
+ var normalized = accumulatedRawJson.trim();
12773
+ if (!normalized) {
12774
+ return fallbackValue;
12775
+ }
12776
+ var directParsed = tryParseJson(normalized);
12777
+ if (directParsed !== undefined) {
12778
+ return directParsed;
12779
+ }
12780
+ var repairedParsed = tryParseJson(repairPartialJson(normalized));
12781
+ if (repairedParsed !== undefined) {
12782
+ return repairedParsed;
12783
+ }
12784
+ return fallbackValue;
12785
+ };
12539
12786
 
12540
12787
  /**
12541
12788
  * Stream parser for parsing SSE (Server-Sent Events) streams.
@@ -12827,301 +13074,41 @@
12827
13074
  return undefined;
12828
13075
  }
12829
13076
 
12830
- /**
12831
- * Reads a human-readable message from a failed HTTP response body when the
12832
- * server returns JSON such as `{ "message": "..." }` (the shared
12833
- * `ErrorResponse` shape used by every status code), falling back to the HTTP
12834
- * status line when the body is empty or not parseable.
12835
- */ function getHttpErrorMessage(response) {
12836
- var fallback = "HTTP error: ".concat(response.status, " ").concat(response.statusText);
12837
- return response.text().then(function(text) {
12838
- var _tryParseErrorMessage;
12839
- return (_tryParseErrorMessage = tryParseErrorMessage(text)) !== null && _tryParseErrorMessage !== void 0 ? _tryParseErrorMessage : fallback;
12840
- }).catch(function() {
12841
- return fallback;
12842
- });
13077
+ var _computedKey$1;
13078
+ var defaultGuardrailFallbackResponse = 'Sorry, we are not able to generate a response at the moment.';
13079
+ var TOOL_CALL_CANCELLED_ERROR_TEXT = 'The tool call was cancelled: the conversation moved on before a result was provided.';
13080
+ function getToolName(part) {
13081
+ if (part.type === 'dynamic-tool') {
13082
+ var _part_toolName;
13083
+ return (_part_toolName = part.toolName) !== null && _part_toolName !== void 0 ? _part_toolName : part.type;
13084
+ }
13085
+ return part.type.slice('tool-'.length);
13086
+ }
13087
+ function warnInvalidGlobalToolResult(toolCallId) {}
13088
+ // A tool call awaiting an output that the client owns. Provider-executed calls
13089
+ // are resolved server-side, so they are left alone.
13090
+ function isPendingToolPart(part) {
13091
+ var candidate = part;
13092
+ return typeof candidate.type === 'string' && typeof candidate.toolCallId === 'string' && (candidate.state === 'input-streaming' || candidate.state === 'input-available') && candidate.providerExecuted !== true;
13093
+ }
13094
+ // Drops the fields that only belong to the state being left behind:
13095
+ // `output-error` forbids `output`, and a committed output is not `preliminary`.
13096
+ function withTerminalToolState(part, terminalState) {
13097
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13098
+ part.preliminary; // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13099
+ part.rawOutput; // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13100
+ part.output; // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13101
+ part.errorText;
13102
+ var retainedPart = _object_without_properties(part, [
13103
+ "preliminary",
13104
+ "rawOutput",
13105
+ "output",
13106
+ "errorText"
13107
+ ]);
13108
+ return _object_spread({}, retainedPart, terminalState);
12843
13109
  }
12844
- /**
12845
- * Abstract base class for HTTP-based chat transports.
12846
- */ var HttpChatTransport = /*#__PURE__*/ function() {
12847
- function HttpChatTransport(param) {
12848
- var _param_api = param.api, api = _param_api === void 0 ? '/api/chat' : _param_api, credentials = param.credentials, headers = param.headers, body = param.body, customFetch = param.fetch, prepareSendMessagesRequest = param.prepareSendMessagesRequest, prepareReconnectToStreamRequest = param.prepareReconnectToStreamRequest;
12849
- _class_call_check(this, HttpChatTransport);
12850
- _define_property(this, "api", void 0);
12851
- _define_property(this, "credentials", void 0);
12852
- _define_property(this, "headers", void 0);
12853
- _define_property(this, "body", void 0);
12854
- _define_property(this, "fetch", void 0);
12855
- _define_property(this, "prepareSendMessagesRequest", void 0);
12856
- _define_property(this, "prepareReconnectToStreamRequest", void 0);
12857
- this.api = api;
12858
- this.credentials = credentials;
12859
- this.headers = headers;
12860
- this.body = body;
12861
- this.fetch = customFetch;
12862
- this.prepareSendMessagesRequest = prepareSendMessagesRequest;
12863
- this.prepareReconnectToStreamRequest = prepareReconnectToStreamRequest;
12864
- }
12865
- _create_class(HttpChatTransport, [
12866
- {
12867
- key: "sendMessages",
12868
- value: function sendMessages(param) {
12869
- var _this = this;
12870
- var abortSignal = param.abortSignal, chatId = param.chatId, messages = param.messages, requestMetadata = param.requestMetadata, trigger = param.trigger, messageId = param.messageId, requestHeaders = param.headers, requestBody = param.body;
12871
- var _this_fetch;
12872
- var fetchFn = (_this_fetch = this.fetch) !== null && _this_fetch !== void 0 ? _this_fetch : fetch;
12873
- // Resolve configurable values
12874
- return Promise.all([
12875
- resolveValue(this.credentials),
12876
- resolveValue(this.headers),
12877
- resolveValue(this.body)
12878
- ]).then(function(param) {
12879
- var _param = _sliced_to_array(param, 3), resolvedCredentials = _param[0], resolvedHeaders = _param[1], resolvedBody = _param[2];
12880
- // Build default request options
12881
- var api = _this.api;
12882
- var body = _object_spread({
12883
- id: chatId,
12884
- messages: messages
12885
- }, resolvedBody, requestBody);
12886
- var headers = _object_spread({
12887
- 'Content-Type': 'application/json'
12888
- }, _instanceof(resolvedHeaders, Headers) ? Object.fromEntries(resolvedHeaders.entries()) : resolvedHeaders, _instanceof(requestHeaders, Headers) ? Object.fromEntries(requestHeaders.entries()) : requestHeaders);
12889
- var credentials = resolvedCredentials;
12890
- // Apply custom preparation if provided
12891
- var prepareRequestBody = _object_spread({}, resolvedBody, requestBody);
12892
- var preparePromise = _this.prepareSendMessagesRequest ? Promise.resolve(_this.prepareSendMessagesRequest({
12893
- id: chatId,
12894
- messages: messages,
12895
- requestMetadata: requestMetadata,
12896
- body: prepareRequestBody,
12897
- credentials: resolvedCredentials,
12898
- headers: resolvedHeaders,
12899
- api: _this.api,
12900
- trigger: trigger,
12901
- messageId: messageId
12902
- })) : Promise.resolve(null);
12903
- return preparePromise.then(function(prepared) {
12904
- if (prepared) {
12905
- body = prepared.body;
12906
- if (prepared.api) api = prepared.api;
12907
- if (prepared.headers) {
12908
- headers = _object_spread({
12909
- 'Content-Type': 'application/json'
12910
- }, _instanceof(prepared.headers, Headers) ? Object.fromEntries(prepared.headers.entries()) : prepared.headers);
12911
- }
12912
- if (prepared.credentials) credentials = prepared.credentials;
12913
- }
12914
- return fetchFn(api, {
12915
- method: 'POST',
12916
- headers: headers,
12917
- body: JSON.stringify(body),
12918
- signal: abortSignal,
12919
- credentials: credentials
12920
- }).then(function(response) {
12921
- if (!response.ok) {
12922
- return getHttpErrorMessage(response).then(function(message) {
12923
- throw new Error(message);
12924
- });
12925
- }
12926
- if (!response.body) {
12927
- throw new Error('Response body is empty');
12928
- }
12929
- return _this.processResponseStream(response.body);
12930
- });
12931
- });
12932
- });
12933
- }
12934
- },
12935
- {
12936
- key: "reconnectToStream",
12937
- value: function reconnectToStream(param) {
12938
- var _this = this;
12939
- var chatId = param.chatId, requestHeaders = param.headers, requestBody = param.body;
12940
- var _this_fetch;
12941
- var fetchFn = (_this_fetch = this.fetch) !== null && _this_fetch !== void 0 ? _this_fetch : fetch;
12942
- // Resolve configurable values
12943
- return Promise.all([
12944
- resolveValue(this.credentials),
12945
- resolveValue(this.headers),
12946
- resolveValue(this.body)
12947
- ]).then(function(param) {
12948
- var _param = _sliced_to_array(param, 3), resolvedCredentials = _param[0], resolvedHeaders = _param[1], resolvedBody = _param[2];
12949
- // Build default request options
12950
- var api = _this.api;
12951
- var headers = _object_spread({}, _instanceof(resolvedHeaders, Headers) ? Object.fromEntries(resolvedHeaders.entries()) : resolvedHeaders, _instanceof(requestHeaders, Headers) ? Object.fromEntries(requestHeaders.entries()) : requestHeaders);
12952
- var credentials = resolvedCredentials;
12953
- // Apply custom preparation if provided
12954
- var prepareRequestBody = _object_spread({}, resolvedBody, requestBody);
12955
- var preparePromise = _this.prepareReconnectToStreamRequest ? Promise.resolve(_this.prepareReconnectToStreamRequest({
12956
- id: chatId,
12957
- requestMetadata: undefined,
12958
- body: prepareRequestBody,
12959
- credentials: resolvedCredentials,
12960
- headers: resolvedHeaders,
12961
- api: _this.api
12962
- })) : Promise.resolve(null);
12963
- return preparePromise.then(function(prepared) {
12964
- if (prepared) {
12965
- if (prepared.api) api = prepared.api;
12966
- if (prepared.headers) {
12967
- headers = _instanceof(prepared.headers, Headers) ? Object.fromEntries(prepared.headers.entries()) : prepared.headers;
12968
- }
12969
- if (prepared.credentials) credentials = prepared.credentials;
12970
- }
12971
- // GET request for reconnection
12972
- return fetchFn("".concat(api, "?chatId=").concat(chatId), {
12973
- method: 'GET',
12974
- headers: headers,
12975
- credentials: credentials
12976
- }).then(function(response) {
12977
- if (!response.ok) {
12978
- // 404 means no stream to reconnect to, which is not an error
12979
- if (response.status === 404) {
12980
- return null;
12981
- }
12982
- return getHttpErrorMessage(response).then(function(message) {
12983
- throw new Error(message);
12984
- });
12985
- }
12986
- if (!response.body) {
12987
- return null;
12988
- }
12989
- return _this.processResponseStream(response.body);
12990
- });
12991
- });
12992
- });
12993
- }
12994
- }
12995
- ]);
12996
- return HttpChatTransport;
12997
- }();
12998
- /**
12999
- * Default chat transport implementation using NDJSON streaming.
13000
- */ var DefaultChatTransport = /*#__PURE__*/ function(HttpChatTransport) {
13001
- _inherits(DefaultChatTransport, HttpChatTransport);
13002
- function DefaultChatTransport() {
13003
- var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
13004
- _class_call_check(this, DefaultChatTransport);
13005
- return _call_super(this, DefaultChatTransport, [
13006
- options
13007
- ]);
13008
- }
13009
- _create_class(DefaultChatTransport, [
13010
- {
13011
- key: "processResponseStream",
13012
- value: function processResponseStream(stream) {
13013
- return parseJsonEventStream(stream);
13014
- }
13015
- }
13016
- ]);
13017
- return DefaultChatTransport;
13018
- }(HttpChatTransport);
13019
-
13020
- var tryParseJson = function tryParseJson(value) {
13021
- try {
13022
- return JSON.parse(value);
13023
- } catch (unused) {
13024
- return undefined;
13025
- }
13026
- };
13027
- var repairPartialJson = function repairPartialJson(value) {
13028
- var repaired = value.trim();
13029
- if (!repaired) {
13030
- return repaired;
13031
- }
13032
- var inString = false;
13033
- var isEscaped = false;
13034
- var stack = [];
13035
- for(var index = 0; index < repaired.length; index++){
13036
- var char = repaired[index];
13037
- if (inString) {
13038
- if (isEscaped) {
13039
- isEscaped = false;
13040
- } else if (char === '\\') {
13041
- isEscaped = true;
13042
- } else if (char === '"') {
13043
- inString = false;
13044
- }
13045
- continue;
13046
- }
13047
- if (char === '"') {
13048
- inString = true;
13049
- continue;
13050
- }
13051
- if (char === '{' || char === '[') {
13052
- stack.push(char);
13053
- continue;
13054
- }
13055
- if (char === '}' && stack[stack.length - 1] === '{') {
13056
- stack.pop();
13057
- continue;
13058
- }
13059
- if (char === ']' && stack[stack.length - 1] === '[') {
13060
- stack.pop();
13061
- }
13062
- }
13063
- if (inString && !isEscaped) {
13064
- repaired += '"';
13065
- }
13066
- repaired = repaired.replace(RegExp(",\\s*$", "u"), '');
13067
- if (stack.length > 0) {
13068
- repaired += stack.reverse().map(function(opening) {
13069
- return opening === '{' ? '}' : ']';
13070
- }).join('');
13071
- }
13072
- return repaired.replace(RegExp(",\\s*([}\\]])", "gu"), '$1');
13073
- };
13074
- var parsePartialJson = function parsePartialJson(accumulatedRawJson, fallbackValue) {
13075
- var normalized = accumulatedRawJson.trim();
13076
- if (!normalized) {
13077
- return fallbackValue;
13078
- }
13079
- var directParsed = tryParseJson(normalized);
13080
- if (directParsed !== undefined) {
13081
- return directParsed;
13082
- }
13083
- var repairedParsed = tryParseJson(repairPartialJson(normalized));
13084
- if (repairedParsed !== undefined) {
13085
- return repairedParsed;
13086
- }
13087
- return fallbackValue;
13088
- };
13089
-
13090
- var _computedKey$1;
13091
- var defaultGuardrailFallbackResponse = 'Sorry, we are not able to generate a response at the moment.';
13092
- var TOOL_CALL_CANCELLED_ERROR_TEXT = 'The tool call was cancelled: the conversation moved on before a result was provided.';
13093
- function getToolName(part) {
13094
- if (part.type === 'dynamic-tool') {
13095
- var _part_toolName;
13096
- return (_part_toolName = part.toolName) !== null && _part_toolName !== void 0 ? _part_toolName : part.type;
13097
- }
13098
- return part.type.slice('tool-'.length);
13099
- }
13100
- function warnInvalidGlobalToolResult(toolCallId) {}
13101
- // A tool call awaiting an output that the client owns. Provider-executed calls
13102
- // are resolved server-side, so they are left alone.
13103
- function isPendingToolPart(part) {
13104
- var candidate = part;
13105
- return typeof candidate.type === 'string' && typeof candidate.toolCallId === 'string' && (candidate.state === 'input-streaming' || candidate.state === 'input-available') && candidate.providerExecuted !== true;
13106
- }
13107
- // Drops the fields that only belong to the state being left behind:
13108
- // `output-error` forbids `output`, and a committed output is not `preliminary`.
13109
- function withTerminalToolState(part, terminalState) {
13110
- // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13111
- part.preliminary; // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13112
- part.rawOutput; // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13113
- part.output; // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
13114
- part.errorText;
13115
- var retainedPart = _object_without_properties(part, [
13116
- "preliminary",
13117
- "rawOutput",
13118
- "output",
13119
- "errorText"
13120
- ]);
13121
- return _object_spread({}, retainedPart, terminalState);
13122
- }
13123
- _computedKey$1 = /** @internal */ '~addToolResultForMessage';
13124
- var _computedKey1$1 = _computedKey$1;
13110
+ _computedKey$1 = /** @internal */ '~addToolResultForMessage';
13111
+ var _computedKey1$1 = _computedKey$1;
13125
13112
  /**
13126
13113
  * Abstract base class for chat implementations.
13127
13114
  */ var AbstractChat = /*#__PURE__*/ function() {
@@ -14587,29 +14574,277 @@
14587
14574
  return Chat;
14588
14575
  }(AbstractChat);
14589
14576
 
14590
- var withUsage$q = createDocumentationMessageGenerator({
14591
- name: 'chat',
14592
- connector: true
14593
- });
14594
- var OPEN_STATE_CACHE_KEY = 'instantsearch-chat-open-state';
14595
- function normalizePersistence(persistence, hasCustomChat) {
14596
- if (hasCustomChat) {
14597
- return {
14598
- messages: false,
14599
- open: persistence === undefined || (typeof persistence === "undefined" ? "undefined" : _type_of(persistence)) === 'object' && persistence.open === true
14600
- };
14601
- }
14602
- if (persistence === undefined || persistence === true) {
14603
- return {
14604
- messages: true,
14605
- open: true
14606
- };
14577
+ // Centralizes the "open the chat from an entry point" behavior shared by the
14578
+ // SearchBox AI button, the Autocomplete AI button, prompt suggestions, and any
14579
+ // future entry point. The chat is always opened; the message is only sent when
14580
+ // it is non-empty and the chat is not already processing a message.
14581
+ // Returns true when a message was submitted, so callers can clear their input.
14582
+ function openChat(chatRenderState) {
14583
+ var _ref = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}, message = _ref.message, referer = _ref.referer, turnContext = _ref.turnContext;
14584
+ var _ref1;
14585
+ var _chatRenderState_setOpen;
14586
+ if (!chatRenderState) {
14587
+ return false;
14607
14588
  }
14608
- if (persistence === false) {
14609
- return {
14610
- messages: false,
14611
- open: false
14612
- };
14589
+ var trimmed = (_ref1 = message === null || message === void 0 ? void 0 : message.trim()) !== null && _ref1 !== void 0 ? _ref1 : '';
14590
+ if (!trimmed) {
14591
+ if (chatRenderState.focusInput) {
14592
+ chatRenderState.focusInput();
14593
+ } else {
14594
+ var _chatRenderState_setOpen1;
14595
+ (_chatRenderState_setOpen1 = chatRenderState.setOpen) === null || _chatRenderState_setOpen1 === void 0 ? void 0 : _chatRenderState_setOpen1.call(chatRenderState, true);
14596
+ }
14597
+ return false;
14598
+ }
14599
+ (_chatRenderState_setOpen = chatRenderState.setOpen) === null || _chatRenderState_setOpen === void 0 ? void 0 : _chatRenderState_setOpen.call(chatRenderState, true);
14600
+ if (isChatBusy(chatRenderState) || !chatRenderState.sendMessage) {
14601
+ return false;
14602
+ }
14603
+ chatRenderState.sendMessage(_object_spread({
14604
+ text: trimmed
14605
+ }, turnContext ? {
14606
+ metadata: {
14607
+ turnContext: turnContext
14608
+ }
14609
+ } : {}), referer ? {
14610
+ headers: {
14611
+ 'x-algolia-referer': referer
14612
+ }
14613
+ } : undefined);
14614
+ return true;
14615
+ }
14616
+ function isChatBusy(chatRenderState) {
14617
+ return (chatRenderState === null || chatRenderState === void 0 ? void 0 : chatRenderState.status) === 'submitted' || (chatRenderState === null || chatRenderState === void 0 ? void 0 : chatRenderState.status) === 'streaming';
14618
+ }
14619
+
14620
+ var SearchIndexToolType = 'algolia_search_index';
14621
+ /**
14622
+ * Whether `toolName` is the search tool as the Algolia MCP Server exposes it:
14623
+ * one tool per index, named after the index it searches
14624
+ * (`algolia_search_index_products`).
14625
+ */ var matchesSearchIndexToolName = function matchesSearchIndexToolName(toolName) {
14626
+ return toolName.startsWith("".concat(SearchIndexToolType, "_"));
14627
+ };
14628
+
14629
+ function flat(arr) {
14630
+ return arr.reduce(function(acc, array) {
14631
+ return acc.concat(array);
14632
+ }, []);
14633
+ }
14634
+
14635
+ /**
14636
+ * Reads a human-readable message from a failed HTTP response body when the
14637
+ * server returns JSON such as `{ "message": "..." }` (the shared
14638
+ * `ErrorResponse` shape used by every status code), falling back to the HTTP
14639
+ * status line when the body is empty or not parseable.
14640
+ */ function getHttpErrorMessage(response) {
14641
+ var fallback = "HTTP error: ".concat(response.status, " ").concat(response.statusText);
14642
+ return response.text().then(function(text) {
14643
+ var _tryParseErrorMessage;
14644
+ return (_tryParseErrorMessage = tryParseErrorMessage(text)) !== null && _tryParseErrorMessage !== void 0 ? _tryParseErrorMessage : fallback;
14645
+ }).catch(function() {
14646
+ return fallback;
14647
+ });
14648
+ }
14649
+ /**
14650
+ * Abstract base class for HTTP-based chat transports.
14651
+ */ var HttpChatTransport = /*#__PURE__*/ function() {
14652
+ function HttpChatTransport(param) {
14653
+ var _param_api = param.api, api = _param_api === void 0 ? '/api/chat' : _param_api, credentials = param.credentials, headers = param.headers, body = param.body, customFetch = param.fetch, prepareSendMessagesRequest = param.prepareSendMessagesRequest, prepareReconnectToStreamRequest = param.prepareReconnectToStreamRequest;
14654
+ _class_call_check(this, HttpChatTransport);
14655
+ _define_property(this, "api", void 0);
14656
+ _define_property(this, "credentials", void 0);
14657
+ _define_property(this, "headers", void 0);
14658
+ _define_property(this, "body", void 0);
14659
+ _define_property(this, "fetch", void 0);
14660
+ _define_property(this, "prepareSendMessagesRequest", void 0);
14661
+ _define_property(this, "prepareReconnectToStreamRequest", void 0);
14662
+ this.api = api;
14663
+ this.credentials = credentials;
14664
+ this.headers = headers;
14665
+ this.body = body;
14666
+ this.fetch = customFetch;
14667
+ this.prepareSendMessagesRequest = prepareSendMessagesRequest;
14668
+ this.prepareReconnectToStreamRequest = prepareReconnectToStreamRequest;
14669
+ }
14670
+ _create_class(HttpChatTransport, [
14671
+ {
14672
+ key: "sendMessages",
14673
+ value: function sendMessages(param) {
14674
+ var _this = this;
14675
+ var abortSignal = param.abortSignal, chatId = param.chatId, messages = param.messages, requestMetadata = param.requestMetadata, trigger = param.trigger, messageId = param.messageId, requestHeaders = param.headers, requestBody = param.body;
14676
+ var _this_fetch;
14677
+ var fetchFn = (_this_fetch = this.fetch) !== null && _this_fetch !== void 0 ? _this_fetch : fetch;
14678
+ // Resolve configurable values
14679
+ return Promise.all([
14680
+ resolveValue(this.credentials),
14681
+ resolveValue(this.headers),
14682
+ resolveValue(this.body)
14683
+ ]).then(function(param) {
14684
+ var _param = _sliced_to_array(param, 3), resolvedCredentials = _param[0], resolvedHeaders = _param[1], resolvedBody = _param[2];
14685
+ // Build default request options
14686
+ var api = _this.api;
14687
+ var body = _object_spread({
14688
+ id: chatId,
14689
+ messages: messages
14690
+ }, resolvedBody, requestBody);
14691
+ var headers = _object_spread({
14692
+ 'Content-Type': 'application/json'
14693
+ }, _instanceof(resolvedHeaders, Headers) ? Object.fromEntries(resolvedHeaders.entries()) : resolvedHeaders, _instanceof(requestHeaders, Headers) ? Object.fromEntries(requestHeaders.entries()) : requestHeaders);
14694
+ var credentials = resolvedCredentials;
14695
+ // Apply custom preparation if provided
14696
+ var prepareRequestBody = _object_spread({}, resolvedBody, requestBody);
14697
+ var preparePromise = _this.prepareSendMessagesRequest ? Promise.resolve(_this.prepareSendMessagesRequest({
14698
+ id: chatId,
14699
+ messages: messages,
14700
+ requestMetadata: requestMetadata,
14701
+ body: prepareRequestBody,
14702
+ credentials: resolvedCredentials,
14703
+ headers: resolvedHeaders,
14704
+ api: _this.api,
14705
+ trigger: trigger,
14706
+ messageId: messageId
14707
+ })) : Promise.resolve(null);
14708
+ return preparePromise.then(function(prepared) {
14709
+ if (prepared) {
14710
+ body = prepared.body;
14711
+ if (prepared.api) api = prepared.api;
14712
+ if (prepared.headers) {
14713
+ headers = _object_spread({
14714
+ 'Content-Type': 'application/json'
14715
+ }, _instanceof(prepared.headers, Headers) ? Object.fromEntries(prepared.headers.entries()) : prepared.headers);
14716
+ }
14717
+ if (prepared.credentials) credentials = prepared.credentials;
14718
+ }
14719
+ return fetchFn(api, {
14720
+ method: 'POST',
14721
+ headers: headers,
14722
+ body: JSON.stringify(body),
14723
+ signal: abortSignal,
14724
+ credentials: credentials
14725
+ }).then(function(response) {
14726
+ if (!response.ok) {
14727
+ return getHttpErrorMessage(response).then(function(message) {
14728
+ throw new Error(message);
14729
+ });
14730
+ }
14731
+ if (!response.body) {
14732
+ throw new Error('Response body is empty');
14733
+ }
14734
+ return _this.processResponseStream(response.body);
14735
+ });
14736
+ });
14737
+ });
14738
+ }
14739
+ },
14740
+ {
14741
+ key: "reconnectToStream",
14742
+ value: function reconnectToStream(param) {
14743
+ var _this = this;
14744
+ var chatId = param.chatId, requestHeaders = param.headers, requestBody = param.body;
14745
+ var _this_fetch;
14746
+ var fetchFn = (_this_fetch = this.fetch) !== null && _this_fetch !== void 0 ? _this_fetch : fetch;
14747
+ // Resolve configurable values
14748
+ return Promise.all([
14749
+ resolveValue(this.credentials),
14750
+ resolveValue(this.headers),
14751
+ resolveValue(this.body)
14752
+ ]).then(function(param) {
14753
+ var _param = _sliced_to_array(param, 3), resolvedCredentials = _param[0], resolvedHeaders = _param[1], resolvedBody = _param[2];
14754
+ // Build default request options
14755
+ var api = _this.api;
14756
+ var headers = _object_spread({}, _instanceof(resolvedHeaders, Headers) ? Object.fromEntries(resolvedHeaders.entries()) : resolvedHeaders, _instanceof(requestHeaders, Headers) ? Object.fromEntries(requestHeaders.entries()) : requestHeaders);
14757
+ var credentials = resolvedCredentials;
14758
+ // Apply custom preparation if provided
14759
+ var prepareRequestBody = _object_spread({}, resolvedBody, requestBody);
14760
+ var preparePromise = _this.prepareReconnectToStreamRequest ? Promise.resolve(_this.prepareReconnectToStreamRequest({
14761
+ id: chatId,
14762
+ requestMetadata: undefined,
14763
+ body: prepareRequestBody,
14764
+ credentials: resolvedCredentials,
14765
+ headers: resolvedHeaders,
14766
+ api: _this.api
14767
+ })) : Promise.resolve(null);
14768
+ return preparePromise.then(function(prepared) {
14769
+ if (prepared) {
14770
+ if (prepared.api) api = prepared.api;
14771
+ if (prepared.headers) {
14772
+ headers = _instanceof(prepared.headers, Headers) ? Object.fromEntries(prepared.headers.entries()) : prepared.headers;
14773
+ }
14774
+ if (prepared.credentials) credentials = prepared.credentials;
14775
+ }
14776
+ // GET request for reconnection
14777
+ return fetchFn("".concat(api, "?chatId=").concat(chatId), {
14778
+ method: 'GET',
14779
+ headers: headers,
14780
+ credentials: credentials
14781
+ }).then(function(response) {
14782
+ if (!response.ok) {
14783
+ // 404 means no stream to reconnect to, which is not an error
14784
+ if (response.status === 404) {
14785
+ return null;
14786
+ }
14787
+ return getHttpErrorMessage(response).then(function(message) {
14788
+ throw new Error(message);
14789
+ });
14790
+ }
14791
+ if (!response.body) {
14792
+ return null;
14793
+ }
14794
+ return _this.processResponseStream(response.body);
14795
+ });
14796
+ });
14797
+ });
14798
+ }
14799
+ }
14800
+ ]);
14801
+ return HttpChatTransport;
14802
+ }();
14803
+ /**
14804
+ * Default chat transport implementation using NDJSON streaming.
14805
+ */ var DefaultChatTransport = /*#__PURE__*/ function(HttpChatTransport) {
14806
+ _inherits(DefaultChatTransport, HttpChatTransport);
14807
+ function DefaultChatTransport() {
14808
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
14809
+ _class_call_check(this, DefaultChatTransport);
14810
+ return _call_super(this, DefaultChatTransport, [
14811
+ options
14812
+ ]);
14813
+ }
14814
+ _create_class(DefaultChatTransport, [
14815
+ {
14816
+ key: "processResponseStream",
14817
+ value: function processResponseStream(stream) {
14818
+ return parseJsonEventStream(stream);
14819
+ }
14820
+ }
14821
+ ]);
14822
+ return DefaultChatTransport;
14823
+ }(HttpChatTransport);
14824
+
14825
+ var withUsage$q = createDocumentationMessageGenerator({
14826
+ name: 'chat',
14827
+ connector: true
14828
+ });
14829
+ var OPEN_STATE_CACHE_KEY$1 = 'instantsearch-chat-open-state';
14830
+ function normalizePersistence(persistence, hasCustomChat) {
14831
+ if (hasCustomChat) {
14832
+ return {
14833
+ messages: false,
14834
+ open: persistence === undefined || (typeof persistence === "undefined" ? "undefined" : _type_of(persistence)) === 'object' && persistence.open === true
14835
+ };
14836
+ }
14837
+ if (persistence === undefined || persistence === true) {
14838
+ return {
14839
+ messages: true,
14840
+ open: true
14841
+ };
14842
+ }
14843
+ if (persistence === false) {
14844
+ return {
14845
+ messages: false,
14846
+ open: false
14847
+ };
14613
14848
  }
14614
14849
  return {
14615
14850
  messages: persistence.messages === true,
@@ -14617,7 +14852,7 @@
14617
14852
  };
14618
14853
  }
14619
14854
  function getOpenStateCacheKey(type) {
14620
- return "".concat(OPEN_STATE_CACHE_KEY, "-").concat(type);
14855
+ return "".concat(OPEN_STATE_CACHE_KEY$1, "-").concat(type);
14621
14856
  }
14622
14857
  function readPersistedOpen(type) {
14623
14858
  try {
@@ -14649,6 +14884,11 @@
14649
14884
  return refinement.attribute;
14650
14885
  }));
14651
14886
  }
14887
+ /**
14888
+ * One Algolia `numericFilters` entry: `'price <= 1500'`. The operators are
14889
+ * exactly the set `helper.addNumericRefinement` accepts, and exactly the set
14890
+ * the Algolia MCP Server emits.
14891
+ */ var NUMERIC_FILTER = /^(.+?)\s*(<=|>=|!=|=|<|>)\s*(-?\d+(?:\.\d+)?)$/;
14652
14892
  function updateStateFromSearchToolInput(params, helper) {
14653
14893
  // clear all filters first
14654
14894
  var attributesToClear = getAttributesToClear$1({
@@ -14692,6 +14932,16 @@
14692
14932
  helper.toggleFacetRefinement(name, value);
14693
14933
  });
14694
14934
  }
14935
+ if (params.numericFilters) {
14936
+ params.numericFilters.forEach(function(filter) {
14937
+ var match = filter.match(NUMERIC_FILTER);
14938
+ if (!match) {
14939
+ return;
14940
+ }
14941
+ var _match = _sliced_to_array(match, 4), attribute = _match[1], operator = _match[2], value = _match[3];
14942
+ helper.addNumericRefinement(attribute, operator, Number(value));
14943
+ });
14944
+ }
14695
14945
  if (params.query) {
14696
14946
  helper.setQuery(params.query);
14697
14947
  }
@@ -14702,7 +14952,7 @@
14702
14952
  var unmountFn = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : noop;
14703
14953
  checkRendering(renderFn, withUsage$q());
14704
14954
  return function(widgetParams) {
14705
- var _ref = widgetParams || {}, _ref_resume = _ref.resume, resume = _ref_resume === void 0 ? false : _ref_resume, _ref_tools = _ref.tools, tools = _ref_tools === void 0 ? {} : _ref_tools, _ref_type = _ref.type, type = _ref_type === void 0 ? 'chat' : _ref_type, persistence = _ref.persistence, context = _ref.context, initialUserMessage = _ref.initialUserMessage, initialMessages = _ref.initialMessages, _ref_disableTriggerValidation = _ref.disableTriggerValidation, disableTriggerValidation = _ref_disableTriggerValidation === void 0 ? false : _ref_disableTriggerValidation, _ref_sendAutomaticallyWhen = _ref.sendAutomaticallyWhen, sendAutomaticallyWhen = _ref_sendAutomaticallyWhen === void 0 ? lastAssistantMessageIsCompleteWithToolCalls : _ref_sendAutomaticallyWhen, _ref_requiresSearch = _ref.requiresSearch, requiresSearch = _ref_requiresSearch === void 0 ? true : _ref_requiresSearch, options = _object_without_properties(_ref, [
14955
+ var _ref = widgetParams || {}, _ref_resume = _ref.resume, resume = _ref_resume === void 0 ? false : _ref_resume, tmp = _ref.tools, tools_ = tmp === void 0 ? {} : tmp, _ref_type = _ref.type, type = _ref_type === void 0 ? 'chat' : _ref_type, persistence = _ref.persistence, context = _ref.context, initialUserMessage = _ref.initialUserMessage, initialMessages = _ref.initialMessages, _ref_disableTriggerValidation = _ref.disableTriggerValidation, disableTriggerValidation = _ref_disableTriggerValidation === void 0 ? false : _ref_disableTriggerValidation, _ref_sendAutomaticallyWhen = _ref.sendAutomaticallyWhen, sendAutomaticallyWhen = _ref_sendAutomaticallyWhen === void 0 ? lastAssistantMessageIsCompleteWithToolCalls : _ref_sendAutomaticallyWhen, _ref_requiresSearch = _ref.requiresSearch, requiresSearch = _ref_requiresSearch === void 0 ? true : _ref_requiresSearch, options = _object_without_properties(_ref, [
14706
14956
  "resume",
14707
14957
  "tools",
14708
14958
  "type",
@@ -14715,6 +14965,12 @@
14715
14965
  "requiresSearch"
14716
14966
  ]);
14717
14967
  var normalizedPersistence = normalizePersistence(persistence, 'chat' in options);
14968
+ // The Algolia MCP Server exposes the search tool once per index and names
14969
+ // it after the index (`algolia_search_index_products`). A `matchesToolName`
14970
+ // set by the user wins, as does a tool registered under the derived name.
14971
+ var tools = tools_[SearchIndexToolType] && tools_[SearchIndexToolType].matchesToolName === undefined ? _object_spread_props(_object_spread({}, tools_), _define_property({}, SearchIndexToolType, _object_spread_props(_object_spread({}, tools_[SearchIndexToolType]), {
14972
+ matchesToolName: matchesSearchIndexToolName
14973
+ }))) : tools_;
14718
14974
  var _chatInstance;
14719
14975
  var input = '';
14720
14976
  var open = false;
@@ -14996,7 +15252,8 @@
14996
15252
  // `open` is read by sibling widgets (e.g. `chatTrigger`) via the
14997
15253
  // shared `renderState`. Schedule a full re-render so they pick up
14998
15254
  // the new value instead of staying frozen on their initial state.
14999
- initOptions.instantSearchInstance.scheduleRender();
15255
+ // No search runs here, so it must not settle the main search.
15256
+ initOptions.instantSearchInstance.scheduleRender(false);
15000
15257
  };
15001
15258
  setOpen = function setOpen(nextOpen) {
15002
15259
  updateOpen(nextOpen, nextOpen && !open);
@@ -15049,14 +15306,15 @@
15049
15306
  // disable themselves, so a transition has to escape this widget's own
15050
15307
  // render. Message deltas deliberately don't: they stay local to keep
15051
15308
  // streaming cheap. The `status` setter notifies on every write, hence
15052
- // the comparison.
15309
+ // the comparison. A chat turn is not a search, so the render it
15310
+ // schedules must not settle the main search.
15053
15311
  var lastStatus = _chatInstance.status;
15054
15312
  var renderOnStatusChange = function renderOnStatusChange() {
15055
15313
  var statusChanged = _chatInstance.status !== lastStatus;
15056
15314
  lastStatus = _chatInstance.status;
15057
15315
  render();
15058
15316
  if (statusChanged) {
15059
- initOptions.instantSearchInstance.scheduleRender();
15317
+ initOptions.instantSearchInstance.scheduleRender(false);
15060
15318
  }
15061
15319
  };
15062
15320
  safelyRunOnBrowser(function() {
@@ -15086,8 +15344,10 @@
15086
15344
  renderFn(_object_spread_props(_object_spread({}, this.getWidgetRenderState(initOptions)), {
15087
15345
  instantSearchInstance: instantSearchInstance
15088
15346
  }), true);
15347
+ // A restored open panel is new to the sibling entry points, but it is
15348
+ // not a search result.
15089
15349
  if (open) {
15090
- instantSearchInstance.scheduleRender();
15350
+ instantSearchInstance.scheduleRender(false);
15091
15351
  }
15092
15352
  },
15093
15353
  render: function render(renderOptions) {
@@ -15252,9 +15512,48 @@
15252
15512
  * @internal
15253
15513
  */ var useIsHydrated = typeof React__namespace.useSyncExternalStore === 'function' ? useNativeIsHydrated : useLegacyIsHydrated;
15254
15514
 
15515
+ var OPEN_STATE_CACHE_KEY = 'instantsearch-chat-open-state';
15516
+ function isOpenStatePersistenceEnabled(props) {
15517
+ return props.persistence === undefined || props.persistence === true || _type_of(props.persistence) === 'object' && props.persistence.open === true;
15518
+ }
15519
+ function isMessagePersistenceEnabled(props) {
15520
+ return props.persistence === undefined || props.persistence === true || _type_of(props.persistence) === 'object' && props.persistence.messages === true;
15521
+ }
15522
+ function getMessagePersistenceKeySuffix(props) {
15523
+ return props.agentId ? "-".concat(props.agentId) : '';
15524
+ }
15525
+ function hasPersistedOpenState(type) {
15526
+ try {
15527
+ return sessionStorage.getItem("".concat(OPEN_STATE_CACHE_KEY, "-").concat(type)) === 'true';
15528
+ } catch (unused) {
15529
+ return false;
15530
+ }
15531
+ }
15255
15532
  function useChat(props, additionalWidgetProperties) {
15256
15533
  var isHydrated = useIsHydrated();
15534
+ var previousPropsRef = React.useRef(props);
15535
+ var previousChatStateRef = React.useRef(null);
15536
+ useIsomorphicLayoutEffect(function() {
15537
+ {
15538
+ var previousProps = previousPropsRef.current;
15539
+ var previousChatState = previousChatStateRef.current;
15540
+ if (previousChatState && !dequal(previousProps, props) && !('chat' in previousProps)) {
15541
+ var _props_type;
15542
+ var nextType = (_props_type = props.type) !== null && _props_type !== void 0 ? _props_type : 'chat';
15543
+ var losesOpenState = previousChatState.open && (!isOpenStatePersistenceEnabled(props) || !hasPersistedOpenState(nextType));
15544
+ var canRestoreMessages = isMessagePersistenceEnabled(previousProps) && isMessagePersistenceEnabled(props) && getMessagePersistenceKeySuffix(previousProps) === getMessagePersistenceKeySuffix(props);
15545
+ var losesMessages = previousChatState.messages.length > 0 && !canRestoreMessages;
15546
+ { warn(!losesOpenState && !losesMessages, 'Changing the props of the React <Chat> widget replaces its internal Chat instance and clears open state or non-persisted messages. Use stable prop references or provide your own Chat instance to preserve the conversation.'); }
15547
+ }
15548
+ previousPropsRef.current = props;
15549
+ }
15550
+ });
15257
15551
  var chatState = useConnector(connectChat, props, additionalWidgetProperties);
15552
+ useIsomorphicLayoutEffect(function() {
15553
+ {
15554
+ previousChatStateRef.current = chatState;
15555
+ }
15556
+ });
15258
15557
  if (isHydrated) {
15259
15558
  return chatState;
15260
15559
  }
@@ -15308,9 +15607,6 @@
15308
15607
  function withStreamParam(url) {
15309
15608
  return url.includes('?') ? "".concat(url, "&stream=true") : "".concat(url, "?stream=true");
15310
15609
  }
15311
- function resolveStreamedOutput(data, previous) {
15312
- return typeof data === 'string' ? parsePartialJson(data, previous) : data;
15313
- }
15314
15610
  function createTaskPreparationContext(context) {
15315
15611
  function hideProperty(key) {
15316
15612
  var value = context[key];
@@ -15345,27 +15641,56 @@
15345
15641
  }
15346
15642
  return undefined;
15347
15643
  }
15348
- function consumeTaskStream(body, onData) {
15644
+ function consumeTaskTextStream(body, onData) {
15349
15645
  return new Promise(function(resolve, reject) {
15350
- var chunkStream = parseJsonEventStream(body);
15646
+ var decoder = new TextDecoder();
15647
+ var reader = body.getReader();
15648
+ var accumulatedText = '';
15351
15649
  var latest;
15352
- processStream(chunkStream, function(chunk) {
15353
- if (!chunk) {
15354
- return;
15355
- }
15356
- if (chunk.type === 'error') {
15357
- throw new Error(chunk.errorText || 'Task stream error');
15358
- }
15359
- if (chunk.type !== 'data-task-output') {
15360
- return;
15361
- }
15362
- latest = resolveStreamedOutput(chunk.data, latest);
15363
- if (onData) {
15364
- onData(latest);
15650
+ var publish = function publish(output) {
15651
+ if (!isEqual(output, latest)) {
15652
+ latest = output;
15653
+ onData === null || onData === void 0 ? void 0 : onData({
15654
+ output: output
15655
+ });
15365
15656
  }
15366
- }, function() {
15367
- return resolve(latest);
15368
- }, reject);
15657
+ };
15658
+ var read = function read1() {
15659
+ reader.read().then(function(param) {
15660
+ var done = param.done, value = param.value;
15661
+ if (done) {
15662
+ accumulatedText += decoder.decode();
15663
+ reader.releaseLock();
15664
+ try {
15665
+ var output = JSON.parse(accumulatedText);
15666
+ publish(output);
15667
+ resolve({
15668
+ output: output
15669
+ });
15670
+ } catch (error) {
15671
+ reject(error);
15672
+ }
15673
+ return;
15674
+ }
15675
+ try {
15676
+ accumulatedText += decoder.decode(value, {
15677
+ stream: true
15678
+ });
15679
+ var partial = parsePartialJson(accumulatedText, latest);
15680
+ if (partial !== undefined) {
15681
+ publish(partial);
15682
+ }
15683
+ read();
15684
+ } catch (error) {
15685
+ reader.releaseLock();
15686
+ reject(error);
15687
+ }
15688
+ }, function(error) {
15689
+ reader.releaseLock();
15690
+ reject(error);
15691
+ });
15692
+ };
15693
+ read();
15369
15694
  });
15370
15695
  }
15371
15696
  /** Default HTTP transport for named Tasks requests and task-output streams. */ var DefaultTaskTransport = /*#__PURE__*/ function() {
@@ -15389,9 +15714,10 @@
15389
15714
  {
15390
15715
  key: "sendTask",
15391
15716
  value: function sendTask(param) {
15392
- var task = param.task, input = param.input, stream = param.stream, onData = param.onData;
15717
+ var task = param.task, kind = param.kind, input = param.input, stream = param.stream, onData = param.onData;
15393
15718
  return this.sendTaskRequest({
15394
15719
  task: task,
15720
+ kind: kind,
15395
15721
  input: input,
15396
15722
  stream: stream,
15397
15723
  onData: onData ? function(data) {
@@ -15404,7 +15730,7 @@
15404
15730
  /** @internal */ key: "sendTaskRequest",
15405
15731
  value: function sendTaskRequest(param) {
15406
15732
  var _this = this;
15407
- var task = param.task, input = param.input, stream = param.stream, onData = param.onData;
15733
+ var task = param.task, kind = param.kind, input = param.input, stream = param.stream, onData = param.onData;
15408
15734
  var _this_fetch;
15409
15735
  var fetchFn = (_this_fetch = this.fetch) !== null && _this_fetch !== void 0 ? _this_fetch : fetch;
15410
15736
  return Promise.all([
@@ -15416,13 +15742,17 @@
15416
15742
  var api = _this.api;
15417
15743
  var credentials = resolvedCredentials;
15418
15744
  var headers = withJsonContentType(resolvedHeaders);
15419
- var body = _object_spread({
15420
- task: task,
15745
+ var body = _object_spread(_object_spread_props(_object_spread({}, task === undefined ? {} : {
15746
+ task: task
15747
+ }, kind === undefined ? {} : {
15748
+ kind: kind
15749
+ }), {
15421
15750
  input: input
15422
- }, resolvedBody);
15751
+ }), resolvedBody);
15423
15752
  var preparedBody = resolvedBody ? _object_spread({}, resolvedBody) : undefined;
15424
15753
  var preparePromise = _this.prepareSendMessagesRequest ? Promise.resolve(_this.prepareSendMessagesRequest(createTaskPreparationContext({
15425
15754
  task: task,
15755
+ kind: kind,
15426
15756
  input: input,
15427
15757
  stream: stream,
15428
15758
  body: preparedBody,
@@ -15457,8 +15787,11 @@
15457
15787
  throw new Error("HTTP error ".concat(response.status));
15458
15788
  }
15459
15789
  var contentType = ((_response_headers = response.headers) === null || _response_headers === void 0 ? void 0 : (_response_headers_get = _response_headers.get) === null || _response_headers_get === void 0 ? void 0 : _response_headers_get.call(_response_headers, 'content-type')) || '';
15460
- if (stream && response.body && contentType.includes('text/event-stream')) {
15461
- return consumeTaskStream(response.body, onData);
15790
+ if (stream && contentType.includes('text/plain')) {
15791
+ if (!response.body) {
15792
+ throw new Error('Response body is empty');
15793
+ }
15794
+ return consumeTaskTextStream(response.body, onData);
15462
15795
  }
15463
15796
  return response.json();
15464
15797
  });
@@ -15541,7 +15874,7 @@
15541
15874
  }
15542
15875
 
15543
15876
  function createTaskRunner(options) {
15544
- var task = options.task, _options_stream = options.stream, stream = _options_stream === void 0 ? true : _options_stream;
15877
+ var task = options.task, kind = options.kind, _options_stream = options.stream, stream = _options_stream === void 0 ? true : _options_stream;
15545
15878
  var transport;
15546
15879
  if (options.transport !== undefined) {
15547
15880
  transport = options.transport;
@@ -15552,11 +15885,14 @@
15552
15885
  headers: options.headers,
15553
15886
  fetch: options.fetch,
15554
15887
  prepareSendMessagesRequest: prepareRequest ? function(param) {
15555
- var requestTask = param.task, input = param.input;
15556
- return prepareRequest({
15557
- task: requestTask,
15888
+ var requestTask = param.task, requestKind = param.kind, input = param.input;
15889
+ return prepareRequest(_object_spread_props(_object_spread({}, requestTask === undefined ? {} : {
15890
+ task: requestTask
15891
+ }, requestKind === undefined ? {} : {
15892
+ kind: requestKind
15893
+ }), {
15558
15894
  input: input
15559
- });
15895
+ }));
15560
15896
  } : undefined
15561
15897
  });
15562
15898
  }
@@ -15565,6 +15901,7 @@
15565
15901
  var onData = (arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}).onData;
15566
15902
  return transport.sendTask({
15567
15903
  task: task,
15904
+ kind: kind,
15568
15905
  input: input,
15569
15906
  stream: stream,
15570
15907
  onData: onData
@@ -15581,12 +15918,12 @@
15581
15918
  var unmountFn = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : noop;
15582
15919
  checkRendering(renderFn, withUsage$p());
15583
15920
  return function(widgetParams) {
15584
- var agentId = widgetParams.agentId, transport = widgetParams.transport, task = widgetParams.task, _widgetParams_stream = widgetParams.stream, stream = _widgetParams_stream === void 0 ? true : _widgetParams_stream;
15921
+ var agentId = widgetParams.agentId, transport = widgetParams.transport, task = widgetParams.task, kind = widgetParams.kind, _widgetParams_stream = widgetParams.stream, stream = _widgetParams_stream === void 0 ? true : _widgetParams_stream;
15585
15922
  if (!agentId && !transport) {
15586
15923
  throw new Error(withUsage$p('The `agentId` option is required unless a custom `transport` is provided.'));
15587
15924
  }
15588
- if (!task) {
15589
- throw new Error(withUsage$p('The `task` option is required.'));
15925
+ if (!task && !kind) {
15926
+ throw new Error(withUsage$p('Either the `task` or `kind` option is required.'));
15590
15927
  }
15591
15928
  var runner;
15592
15929
  var output;
@@ -15638,6 +15975,8 @@
15638
15975
  // Bump the request id so any in-flight request's callbacks see
15639
15976
  // `isStale()` and are ignored. The fetch itself is left to complete.
15640
15977
  requestId += 1;
15978
+ output = undefined;
15979
+ error = undefined;
15641
15980
  isLoading = false;
15642
15981
  triggerRender();
15643
15982
  };
@@ -15670,6 +16009,7 @@
15670
16009
  runner = createTaskRunner({
15671
16010
  transport: taskTransport,
15672
16011
  task: task,
16012
+ kind: kind,
15673
16013
  stream: stream
15674
16014
  });
15675
16015
  } else {
@@ -15678,6 +16018,7 @@
15678
16018
  transport: transport
15679
16019
  }),
15680
16020
  task: task,
16021
+ kind: kind,
15681
16022
  stream: stream
15682
16023
  });
15683
16024
  }
@@ -15703,55 +16044,13 @@
15703
16044
  };
15704
16045
  };
15705
16046
 
15706
- // Centralizes the "open the chat from an entry point" behavior shared by the
15707
- // SearchBox AI button, the Autocomplete AI button, prompt suggestions, and any
15708
- // future entry point. The chat is always opened; the message is only sent when
15709
- // it is non-empty and the chat is not already processing a message.
15710
- // Returns true when a message was submitted, so callers can clear their input.
15711
- function openChat(chatRenderState) {
15712
- var _ref = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}, message = _ref.message, referer = _ref.referer, turnContext = _ref.turnContext;
15713
- var _ref1;
15714
- var _chatRenderState_setOpen;
15715
- if (!chatRenderState) {
15716
- return false;
15717
- }
15718
- var trimmed = (_ref1 = message === null || message === void 0 ? void 0 : message.trim()) !== null && _ref1 !== void 0 ? _ref1 : '';
15719
- if (!trimmed) {
15720
- if (chatRenderState.focusInput) {
15721
- chatRenderState.focusInput();
15722
- } else {
15723
- var _chatRenderState_setOpen1;
15724
- (_chatRenderState_setOpen1 = chatRenderState.setOpen) === null || _chatRenderState_setOpen1 === void 0 ? void 0 : _chatRenderState_setOpen1.call(chatRenderState, true);
15725
- }
15726
- return false;
15727
- }
15728
- (_chatRenderState_setOpen = chatRenderState.setOpen) === null || _chatRenderState_setOpen === void 0 ? void 0 : _chatRenderState_setOpen.call(chatRenderState, true);
15729
- if (isChatBusy(chatRenderState) || !chatRenderState.sendMessage) {
15730
- return false;
15731
- }
15732
- chatRenderState.sendMessage(_object_spread({
15733
- text: trimmed
15734
- }, turnContext ? {
15735
- metadata: {
15736
- turnContext: turnContext
15737
- }
15738
- } : {}), referer ? {
15739
- headers: {
15740
- 'x-algolia-referer': referer
15741
- }
15742
- } : undefined);
15743
- return true;
15744
- }
15745
- function isChatBusy(chatRenderState) {
15746
- return (chatRenderState === null || chatRenderState === void 0 ? void 0 : chatRenderState.status) === 'submitted' || (chatRenderState === null || chatRenderState === void 0 ? void 0 : chatRenderState.status) === 'streaming';
15747
- }
15748
-
15749
16047
  var withUsage$o = createDocumentationMessageGenerator({
15750
16048
  name: 'prompt-suggestions',
15751
16049
  connector: true
15752
16050
  });
15753
16051
  var RENDER_STATE_KEY = 'promptSuggestions';
15754
16052
  var CHAT_RENDER_STATE_KEY = 'chat';
16053
+ var PROMPT_SUGGESTIONS_TASK_KIND = 'prompt_suggestions';
15755
16054
  var DEBOUNCE_MS = 300;
15756
16055
  function parseSuggestions(data) {
15757
16056
  var suggestions = data === null || data === void 0 ? void 0 : data.suggestions;
@@ -15823,12 +16122,10 @@
15823
16122
  if (!agentId && !transport) {
15824
16123
  throw new Error(withUsage$o('The `agentId` option is required unless a custom `transport` is provided.'));
15825
16124
  }
15826
- if (!configurationId) {
15827
- throw new Error(withUsage$o('The `configurationId` option is required.'));
15828
- }
15829
16125
  var tasksState;
15830
16126
  var suggestions = [];
15831
16127
  var isLoading = false;
16128
+ var error;
15832
16129
  var debounceTimer;
15833
16130
  var lastStateSignature = null;
15834
16131
  var latestRenderOptions = null;
@@ -15961,6 +16258,7 @@
15961
16258
  return {
15962
16259
  suggestions: transformed,
15963
16260
  isLoading: isLoading,
16261
+ error: error,
15964
16262
  onSuggestionClick: send,
15965
16263
  sendToChat: send,
15966
16264
  refresh: refresh,
@@ -15973,10 +16271,10 @@
15973
16271
  var handleInnerRender = function handleInnerRender(renderState) {
15974
16272
  tasksState = renderState;
15975
16273
  if (refetchPending) return;
16274
+ error = renderState.error;
15976
16275
  if (renderState.error) {
15977
16276
  // A failed task (including a mid-stream `error` event) must not leave
15978
- // any streamed partial visible. There's no error UI for now, so fall
15979
- // back to a blank suggestions state.
16277
+ // any streamed partial visible.
15980
16278
  suggestions = [];
15981
16279
  } else if (renderState.isLoading || renderState.output !== undefined) {
15982
16280
  // Only adopt the inner output once a request is loading or has
@@ -15993,12 +16291,14 @@
15993
16291
  agentId: agentId,
15994
16292
  transport: transport,
15995
16293
  task: configurationId,
16294
+ kind: PROMPT_SUGGESTIONS_TASK_KIND,
15996
16295
  stream: true
15997
16296
  };
15998
16297
  } else if (transport) {
15999
16298
  tasksParams = {
16000
16299
  transport: transport,
16001
16300
  task: configurationId,
16301
+ kind: PROMPT_SUGGESTIONS_TASK_KIND,
16002
16302
  stream: true
16003
16303
  };
16004
16304
  } else {
@@ -16027,6 +16327,7 @@
16027
16327
  if (stateSignature !== lastStateSignature) {
16028
16328
  lastStateSignature = stateSignature;
16029
16329
  refetchPending = true;
16330
+ error = undefined;
16030
16331
  clearTimeout(debounceTimer);
16031
16332
  debounceTimer = setTimeout(function() {
16032
16333
  if (latestRenderOptions === null || latestRenderOptions === void 0 ? void 0 : latestRenderOptions.results) {