@crystaldesign/diva-backoffice 26.5.0-beta.34 → 26.5.0-beta.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. package/build/esm/index.js +427 -327
  2. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/ChatComposer.d.ts +7 -1
  3. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/ChatComposer.d.ts.map +1 -1
  4. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/gemini.d.ts +14 -32
  5. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/gemini.d.ts.map +1 -1
  6. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/index.d.ts.map +1 -1
  7. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/preservePrompt.d.ts +16 -0
  8. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/preservePrompt.d.ts.map +1 -0
  9. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/pricing.d.ts.map +1 -1
  10. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/conversationsRepo.d.ts +0 -1
  11. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/conversationsRepo.d.ts.map +1 -1
  12. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/db.d.ts +0 -9
  13. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/db.d.ts.map +1 -1
  14. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/imagesRepo.d.ts +1 -3
  15. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/imagesRepo.d.ts.map +1 -1
  16. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/messagesRepo.d.ts +0 -11
  17. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/messagesRepo.d.ts.map +1 -1
  18. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/objectUrlCache.d.ts +0 -2
  19. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/storage/objectUrlCache.d.ts.map +1 -1
  20. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/useAiChat.d.ts +5 -4
  21. package/build/types/backoffice/src/layout/Toolbar/Tools/AiPromptImageTester/useAiChat.d.ts.map +1 -1
  22. package/package.json +9 -9
@@ -53764,25 +53764,23 @@ function _unsupportedIterableToArray$6(r, a) { if (r) { if ("string" == typeof r
53764
53764
  function _arrayLikeToArray$6(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
53765
53765
  function ownKeys$9(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
53766
53766
  function _objectSpread$9(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$9(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$9(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
53767
- function putImageBlob(_x, _x2, _x3, _x4) {
53767
+ function putImageBlob(_x, _x2, _x3) {
53768
53768
  return _putImageBlob.apply(this, arguments);
53769
53769
  }
53770
53770
  function _putImageBlob() {
53771
- _putImageBlob = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(blob, mime, thoughtSignature, costUsd) {
53771
+ _putImageBlob = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(blob, mime, costUsd) {
53772
53772
  var _ref;
53773
53773
  var id, record;
53774
53774
  return _regeneratorRuntime.wrap(function _callee$(_context) {
53775
53775
  while (1) switch (_context.prev = _context.next) {
53776
53776
  case 0:
53777
53777
  id = newId('img');
53778
- record = _objectSpread$9(_objectSpread$9({
53778
+ record = _objectSpread$9({
53779
53779
  id: id,
53780
53780
  blob: blob,
53781
53781
  mime: (_ref = mime !== null && mime !== void 0 ? mime : blob.type) !== null && _ref !== void 0 ? _ref : 'image/png',
53782
53782
  createdAt: Date.now()
53783
- }, thoughtSignature ? {
53784
- thoughtSignature: thoughtSignature
53785
- } : {}), typeof costUsd === 'number' && costUsd > 0 ? {
53783
+ }, typeof costUsd === 'number' && costUsd > 0 ? {
53786
53784
  costUsd: costUsd
53787
53785
  } : {});
53788
53786
  _context.next = 4;
@@ -53799,7 +53797,7 @@ function _putImageBlob() {
53799
53797
  }));
53800
53798
  return _putImageBlob.apply(this, arguments);
53801
53799
  }
53802
- function getImage(_x5) {
53800
+ function getImage(_x4) {
53803
53801
  return _getImage.apply(this, arguments);
53804
53802
  }
53805
53803
  function _getImage() {
@@ -53818,7 +53816,7 @@ function _getImage() {
53818
53816
  }));
53819
53817
  return _getImage.apply(this, arguments);
53820
53818
  }
53821
- function deleteImages(_x6) {
53819
+ function deleteImages(_x5) {
53822
53820
  return _deleteImages.apply(this, arguments);
53823
53821
  }
53824
53822
 
@@ -53953,103 +53951,103 @@ function _createConversation() {
53953
53951
  }));
53954
53952
  return _createConversation.apply(this, arguments);
53955
53953
  }
53956
- function listConversations(_x4) {
53954
+ function listConversations(_x2) {
53957
53955
  return _listConversations.apply(this, arguments);
53958
53956
  }
53959
53957
  function _listConversations() {
53960
- _listConversations = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(fallbackModel) {
53958
+ _listConversations = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(fallbackModel) {
53961
53959
  var all;
53962
- return _regeneratorRuntime.wrap(function _callee3$(_context3) {
53963
- while (1) switch (_context3.prev = _context3.next) {
53960
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
53961
+ while (1) switch (_context2.prev = _context2.next) {
53964
53962
  case 0:
53965
- _context3.next = 2;
53963
+ _context2.next = 2;
53966
53964
  return withTx(STORE_CONVERSATIONS, 'readonly', function (tx) {
53967
53965
  return reqAsPromise(tx.objectStore(STORE_CONVERSATIONS).getAll());
53968
53966
  });
53969
53967
  case 2:
53970
- all = _context3.sent;
53971
- return _context3.abrupt("return", all.map(function (r) {
53968
+ all = _context2.sent;
53969
+ return _context2.abrupt("return", all.map(function (r) {
53972
53970
  return coerceRecord(r, fallbackModel);
53973
53971
  }).sort(function (a, b) {
53974
53972
  return b.updatedAt - a.updatedAt;
53975
53973
  }));
53976
53974
  case 4:
53977
53975
  case "end":
53978
- return _context3.stop();
53976
+ return _context2.stop();
53979
53977
  }
53980
- }, _callee3);
53978
+ }, _callee2);
53981
53979
  }));
53982
53980
  return _listConversations.apply(this, arguments);
53983
53981
  }
53984
- function updateConversation(_x5, _x6) {
53982
+ function updateConversation(_x3, _x4) {
53985
53983
  return _updateConversation.apply(this, arguments);
53986
53984
  }
53987
53985
  function _updateConversation() {
53988
- _updateConversation = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(id, patch) {
53989
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
53990
- while (1) switch (_context5.prev = _context5.next) {
53986
+ _updateConversation = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(id, patch) {
53987
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
53988
+ while (1) switch (_context4.prev = _context4.next) {
53991
53989
  case 0:
53992
- return _context5.abrupt("return", withTx(STORE_CONVERSATIONS, 'readwrite', /*#__PURE__*/function () {
53993
- var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(tx) {
53990
+ return _context4.abrupt("return", withTx(STORE_CONVERSATIONS, 'readwrite', /*#__PURE__*/function () {
53991
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(tx) {
53994
53992
  var _patch$settings;
53995
53993
  var store, existing, next;
53996
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
53997
- while (1) switch (_context4.prev = _context4.next) {
53994
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
53995
+ while (1) switch (_context3.prev = _context3.next) {
53998
53996
  case 0:
53999
53997
  store = tx.objectStore(STORE_CONVERSATIONS);
54000
- _context4.next = 3;
53998
+ _context3.next = 3;
54001
53999
  return reqAsPromise(store.get(id));
54002
54000
  case 3:
54003
- existing = _context4.sent;
54001
+ existing = _context3.sent;
54004
54002
  if (existing) {
54005
- _context4.next = 6;
54003
+ _context3.next = 6;
54006
54004
  break;
54007
54005
  }
54008
- return _context4.abrupt("return", undefined);
54006
+ return _context3.abrupt("return", undefined);
54009
54007
  case 6:
54010
54008
  next = _objectSpread$8(_objectSpread$8(_objectSpread$8({}, existing), patch), {}, {
54011
54009
  settings: (_patch$settings = patch.settings) !== null && _patch$settings !== void 0 ? _patch$settings : existing.settings,
54012
54010
  updatedAt: Date.now()
54013
54011
  });
54014
- _context4.next = 9;
54012
+ _context3.next = 9;
54015
54013
  return reqAsPromise(store.put(next));
54016
54014
  case 9:
54017
- return _context4.abrupt("return", next);
54015
+ return _context3.abrupt("return", next);
54018
54016
  case 10:
54019
54017
  case "end":
54020
- return _context4.stop();
54018
+ return _context3.stop();
54021
54019
  }
54022
- }, _callee4);
54020
+ }, _callee3);
54023
54021
  }));
54024
- return function (_x8) {
54022
+ return function (_x6) {
54025
54023
  return _ref.apply(this, arguments);
54026
54024
  };
54027
54025
  }()));
54028
54026
  case 1:
54029
54027
  case "end":
54030
- return _context5.stop();
54028
+ return _context4.stop();
54031
54029
  }
54032
- }, _callee5);
54030
+ }, _callee4);
54033
54031
  }));
54034
54032
  return _updateConversation.apply(this, arguments);
54035
54033
  }
54036
- function deleteConversation(_x7) {
54034
+ function deleteConversation(_x5) {
54037
54035
  return _deleteConversation.apply(this, arguments);
54038
54036
  }
54039
54037
  function _deleteConversation() {
54040
- _deleteConversation = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6(id) {
54041
- return _regeneratorRuntime.wrap(function _callee6$(_context6) {
54042
- while (1) switch (_context6.prev = _context6.next) {
54038
+ _deleteConversation = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(id) {
54039
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
54040
+ while (1) switch (_context5.prev = _context5.next) {
54043
54041
  case 0:
54044
- _context6.next = 2;
54042
+ _context5.next = 2;
54045
54043
  return withTx(STORE_CONVERSATIONS, 'readwrite', function (tx) {
54046
54044
  return reqAsPromise(tx.objectStore(STORE_CONVERSATIONS)["delete"](id));
54047
54045
  });
54048
54046
  case 2:
54049
54047
  case "end":
54050
- return _context6.stop();
54048
+ return _context5.stop();
54051
54049
  }
54052
- }, _callee6);
54050
+ }, _callee5);
54053
54051
  }));
54054
54052
  return _deleteConversation.apply(this, arguments);
54055
54053
  }
@@ -54064,10 +54062,12 @@ function listMessages(_x) {
54064
54062
  }
54065
54063
  function _listMessages() {
54066
54064
  _listMessages = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(conversationId) {
54065
+ var records;
54067
54066
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
54068
54067
  while (1) switch (_context2.prev = _context2.next) {
54069
54068
  case 0:
54070
- return _context2.abrupt("return", withTx(STORE_MESSAGES, 'readonly', /*#__PURE__*/function () {
54069
+ _context2.next = 2;
54070
+ return withTx(STORE_MESSAGES, 'readonly', /*#__PURE__*/function () {
54071
54071
  var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(tx) {
54072
54072
  var index, range;
54073
54073
  return _regeneratorRuntime.wrap(function _callee$(_context) {
@@ -54085,8 +54085,15 @@ function _listMessages() {
54085
54085
  return function (_x8) {
54086
54086
  return _ref.apply(this, arguments);
54087
54087
  };
54088
- }()));
54089
- case 1:
54088
+ }());
54089
+ case 2:
54090
+ records = _context2.sent;
54091
+ return _context2.abrupt("return", records.sort(function (a, b) {
54092
+ if (a.ts !== b.ts) return a.ts - b.ts;
54093
+ if (a.kind !== b.kind) return a.kind === 'user' ? -1 : 1;
54094
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
54095
+ }));
54096
+ case 4:
54090
54097
  case "end":
54091
54098
  return _context2.stop();
54092
54099
  }
@@ -54136,7 +54143,7 @@ function _putModelMessage() {
54136
54143
  return _regeneratorRuntime.wrap(function _callee4$(_context4) {
54137
54144
  while (1) switch (_context4.prev = _context4.next) {
54138
54145
  case 0:
54139
- record = _objectSpread$7(_objectSpread$7(_objectSpread$7({
54146
+ record = _objectSpread$7({
54140
54147
  kind: 'model',
54141
54148
  id: (_input$id2 = input.id) !== null && _input$id2 !== void 0 ? _input$id2 : newId('msg'),
54142
54149
  conversationId: input.conversationId,
@@ -54147,11 +54154,7 @@ function _putModelMessage() {
54147
54154
  promptText: input.promptText,
54148
54155
  resolutionCaption: input.resolutionCaption,
54149
54156
  temperatureCaption: input.temperatureCaption
54150
- }, input.responseText ? {
54151
- responseText: input.responseText
54152
- } : {}), input.responseThoughtSignature ? {
54153
- responseThoughtSignature: input.responseThoughtSignature
54154
- } : {}), input.errorMessage ? {
54157
+ }, input.errorMessage ? {
54155
54158
  errorMessage: input.errorMessage
54156
54159
  } : {});
54157
54160
  _context4.next = 3;
@@ -54574,8 +54577,6 @@ function _createForOfIteratorHelper$2(r, e) { var t = "undefined" != typeof Symb
54574
54577
  function _unsupportedIterableToArray$2(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$2(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$2(r, a) : void 0; } }
54575
54578
  function _arrayLikeToArray$2(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
54576
54579
 
54577
- /** Per-record blob payload pre-resolved by the caller, keyed by `imageId`. */
54578
-
54579
54580
  /** Aspect ratios supported by Gemini image-capable models (per Google docs). */
54580
54581
  var ASPECT_RATIOS_FULL = ['1:1', '2:3', '3:2', '3:4', '4:3', '4:5', '5:4', '9:16', '16:9', '21:9'];
54581
54582
 
@@ -54610,9 +54611,20 @@ function optionsForModel(model) {
54610
54611
  }
54611
54612
 
54612
54613
  /**
54613
- * Resolve image bytes for an array of `imageId`s into the `inlineData` shape Gemini expects.
54614
- * Missing IndexedDB rows are skipped silently.
54614
+ * Placeholder substituted with the user's typed prompt when wrapping.
54615
+ * Exposed so the settings UI can show the user what token to keep.
54615
54616
  */
54617
+ var PRESERVE_PROMPT_PLACEHOLDER = '{prompt}';
54618
+ var DEFAULT_PRESERVE_PROMPT_TEMPLATE = "Using the provided image, ".concat(PRESERVE_PROMPT_PLACEHOLDER, ". ") + 'Preserve the subject, objects, materials, and scene of the source image. ' + 'Match the source as closely as possible everywhere else; only modify what ' + 'this change directly requires.';
54619
+ function wrapPreservePrompt(userText) {
54620
+ var template = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_PRESERVE_PROMPT_TEMPLATE;
54621
+ var extraReferenceCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
54622
+ var safeTemplate = template.trim().length > 0 ? template : DEFAULT_PRESERVE_PROMPT_TEMPLATE;
54623
+ var main = safeTemplate.includes(PRESERVE_PROMPT_PLACEHOLDER) ? safeTemplate.replace(PRESERVE_PROMPT_PLACEHOLDER, userText) : "".concat(safeTemplate.trim(), " ").concat(userText).trim();
54624
+ if (extraReferenceCount <= 0) return main;
54625
+ var refLabel = extraReferenceCount === 1 ? 'Image 2 is a visual reference for the new element requested below' : "Images 2 through ".concat(1 + extraReferenceCount, " are visual references for the new elements requested below");
54626
+ return "Image 1 is the current scene to edit. ".concat(refLabel, " \u2014 incorporate the ") + "referenced element(s) into Image 1 as described, matching their visual " + "appearance closely while leaving the rest of Image 1 unchanged. ".concat(main);
54627
+ }
54616
54628
  function imageIdsToParts(_x) {
54617
54629
  return _imageIdsToParts.apply(this, arguments);
54618
54630
  }
@@ -54676,20 +54688,13 @@ function imageRecordToPart(_x2) {
54676
54688
  return _imageRecordToPart.apply(this, arguments);
54677
54689
  }
54678
54690
  /**
54679
- * Convert persisted user/model records into the `Content[]` the SDK accepts.
54680
- *
54681
- * - User turn: `text` part (if any) followed by attached reference images.
54682
- * - Model turn: the text the model returned (if any, carrying its thought signature)
54683
- * followed by every generated image part (each with its own signature). Both the
54684
- * text and the images are essential for follow-up prompts like "make it bigger";
54685
- * without the model's own narration the model loses awareness of what it did.
54691
+ * Build the single-turn `Content[]` payload for `models.generateContent`.
54686
54692
  *
54687
- * The current pending model record (no images yet) is skipped — this builds
54688
- * only completed history, the caller appends the new user prompt separately.
54693
+ * The `text` should already be wrapped with `wrapPreservePrompt` for follow-ups.
54689
54694
  */
54690
54695
  function _imageRecordToPart() {
54691
54696
  _imageRecordToPart = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(rec) {
54692
- var dataUrl, base64, part;
54697
+ var dataUrl, base64;
54693
54698
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
54694
54699
  while (1) switch (_context2.prev = _context2.next) {
54695
54700
  case 0:
@@ -54698,15 +54703,13 @@ function _imageRecordToPart() {
54698
54703
  case 2:
54699
54704
  dataUrl = _context2.sent;
54700
54705
  base64 = dataUrl.includes(',') ? dataUrl.slice(dataUrl.indexOf(',') + 1) : '';
54701
- part = {
54706
+ return _context2.abrupt("return", {
54702
54707
  inlineData: {
54703
54708
  data: base64,
54704
54709
  mimeType: rec.mime
54705
54710
  }
54706
- };
54707
- if (rec.thoughtSignature) part.thoughtSignature = rec.thoughtSignature;
54708
- return _context2.abrupt("return", part);
54709
- case 7:
54711
+ });
54712
+ case 5:
54710
54713
  case "end":
54711
54714
  return _context2.stop();
54712
54715
  }
@@ -54714,149 +54717,52 @@ function _imageRecordToPart() {
54714
54717
  }));
54715
54718
  return _imageRecordToPart.apply(this, arguments);
54716
54719
  }
54717
- function buildContents(_x3, _x4, _x5) {
54720
+ function buildContents(_x3) {
54718
54721
  return _buildContents.apply(this, arguments);
54719
54722
  }
54720
54723
  function _buildContents() {
54721
- _buildContents = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(records, currentText, currentRefImageIds) {
54722
- var out, _iterator2, _step2, r, parts, _parts, currentParts;
54724
+ _buildContents = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(opts) {
54725
+ var parts;
54723
54726
  return _regeneratorRuntime.wrap(function _callee3$(_context3) {
54724
54727
  while (1) switch (_context3.prev = _context3.next) {
54725
54728
  case 0:
54726
- out = [];
54727
- _iterator2 = _createForOfIteratorHelper$2(records);
54728
- _context3.prev = 2;
54729
- _iterator2.s();
54730
- case 4:
54731
- if ((_step2 = _iterator2.n()).done) {
54732
- _context3.next = 27;
54733
- break;
54734
- }
54735
- r = _step2.value;
54736
- if (!(r.kind === 'user')) {
54737
- _context3.next = 20;
54738
- break;
54739
- }
54740
54729
  parts = [];
54741
- if (r.text) parts.push({
54742
- text: r.text
54730
+ if (opts.text) parts.push({
54731
+ text: opts.text
54743
54732
  });
54744
54733
  _context3.t0 = parts.push;
54745
54734
  _context3.t1 = parts;
54746
54735
  _context3.t2 = _toConsumableArray;
54747
- _context3.next = 14;
54748
- return imageIdsToParts(r.uploadedImageIds);
54749
- case 14:
54736
+ _context3.next = 7;
54737
+ return imageIdsToParts(opts.referenceImageIds);
54738
+ case 7:
54750
54739
  _context3.t3 = _context3.sent;
54751
54740
  _context3.t4 = (0, _context3.t2)(_context3.t3);
54752
54741
  _context3.t0.apply.call(_context3.t0, _context3.t1, _context3.t4);
54753
- if (parts.length > 0) out.push({
54742
+ return _context3.abrupt("return", parts.length > 0 ? [{
54754
54743
  role: 'user',
54755
54744
  parts: parts
54756
- });
54757
- _context3.next = 25;
54758
- break;
54759
- case 20:
54760
- if (!(r.kind === 'model' && r.status === 'ready')) {
54761
- _context3.next = 25;
54762
- break;
54763
- }
54764
- _context3.next = 23;
54765
- return buildModelTurnParts(r);
54766
- case 23:
54767
- _parts = _context3.sent;
54768
- if (_parts.length > 0) out.push({
54769
- role: 'model',
54770
- parts: _parts
54771
- });
54772
- case 25:
54773
- _context3.next = 4;
54774
- break;
54775
- case 27:
54776
- _context3.next = 32;
54777
- break;
54778
- case 29:
54779
- _context3.prev = 29;
54780
- _context3.t5 = _context3["catch"](2);
54781
- _iterator2.e(_context3.t5);
54782
- case 32:
54783
- _context3.prev = 32;
54784
- _iterator2.f();
54785
- return _context3.finish(32);
54786
- case 35:
54787
- currentParts = [];
54788
- if (currentText) currentParts.push({
54789
- text: currentText
54790
- });
54791
- _context3.t6 = currentParts.push;
54792
- _context3.t7 = currentParts;
54793
- _context3.t8 = _toConsumableArray;
54794
- _context3.next = 42;
54795
- return imageIdsToParts(currentRefImageIds);
54796
- case 42:
54797
- _context3.t9 = _context3.sent;
54798
- _context3.t10 = (0, _context3.t8)(_context3.t9);
54799
- _context3.t6.apply.call(_context3.t6, _context3.t7, _context3.t10);
54800
- if (currentParts.length > 0) out.push({
54801
- role: 'user',
54802
- parts: currentParts
54803
- });
54804
- return _context3.abrupt("return", out);
54805
- case 47:
54745
+ }] : []);
54746
+ case 11:
54806
54747
  case "end":
54807
54748
  return _context3.stop();
54808
54749
  }
54809
- }, _callee3, null, [[2, 29, 32, 35]]);
54750
+ }, _callee3);
54810
54751
  }));
54811
54752
  return _buildContents.apply(this, arguments);
54812
54753
  }
54813
- function buildModelTurnParts(_x6) {
54814
- return _buildModelTurnParts.apply(this, arguments);
54815
- }
54816
- function _buildModelTurnParts() {
54817
- _buildModelTurnParts = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(r) {
54818
- var parts, _r$responseText, textPart;
54819
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
54820
- while (1) switch (_context4.prev = _context4.next) {
54821
- case 0:
54822
- parts = [];
54823
- if (r.responseText || r.responseThoughtSignature) {
54824
- textPart = {
54825
- text: (_r$responseText = r.responseText) !== null && _r$responseText !== void 0 ? _r$responseText : ''
54826
- };
54827
- if (r.responseThoughtSignature) textPart.thoughtSignature = r.responseThoughtSignature;
54828
- parts.push(textPart);
54829
- }
54830
- _context4.t0 = parts.push;
54831
- _context4.t1 = parts;
54832
- _context4.t2 = _toConsumableArray;
54833
- _context4.next = 7;
54834
- return imageIdsToParts(r.imageIds);
54835
- case 7:
54836
- _context4.t3 = _context4.sent;
54837
- _context4.t4 = (0, _context4.t2)(_context4.t3);
54838
- _context4.t0.apply.call(_context4.t0, _context4.t1, _context4.t4);
54839
- return _context4.abrupt("return", parts);
54840
- case 11:
54841
- case "end":
54842
- return _context4.stop();
54843
- }
54844
- }, _callee4);
54845
- }));
54846
- return _buildModelTurnParts.apply(this, arguments);
54847
- }
54848
54754
  /** Call `models.generateContent` and pluck the inline image parts from the response. */
54849
- function generateImage(_x7) {
54755
+ function generateImage(_x4) {
54850
54756
  return _generateImage.apply(this, arguments);
54851
54757
  }
54852
54758
 
54853
54759
  /** Convert a `GeneratedImage` into a `Blob` ready for IndexedDB. */
54854
54760
  function _generateImage() {
54855
- _generateImage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(opts) {
54761
+ _generateImage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(opts) {
54856
54762
  var _response$candidates, _candidate$content$pa, _candidate$content;
54857
- var ai, model, contents, aspectRatio, imageSize, temperature, signal, config, imageConfig, response, images, text, textThoughtSignature, candidate, parts, _iterator3, _step3, _p$inlineData, _p$inlineData$mimeTyp, p, img, result;
54858
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
54859
- while (1) switch (_context5.prev = _context5.next) {
54763
+ var ai, model, contents, aspectRatio, imageSize, temperature, signal, config, imageConfig, response, images, text, candidate, parts, _iterator2, _step2, _p$inlineData, _p$inlineData$mimeTyp, p, result;
54764
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
54765
+ while (1) switch (_context4.prev = _context4.next) {
54860
54766
  case 0:
54861
54767
  ai = opts.ai, model = opts.model, contents = opts.contents, aspectRatio = opts.aspectRatio, imageSize = opts.imageSize, temperature = opts.temperature, signal = opts.signal;
54862
54768
  config = {};
@@ -54866,7 +54772,7 @@ function _generateImage() {
54866
54772
  if (Object.keys(imageConfig).length > 0) config.imageConfig = imageConfig;
54867
54773
  if (typeof temperature === 'number' && Number.isFinite(temperature)) config.temperature = temperature;
54868
54774
  if (signal) config.abortSignal = signal;
54869
- _context5.next = 10;
54775
+ _context4.next = 10;
54870
54776
  return ai.models.generateContent(_objectSpread$5({
54871
54777
  model: model,
54872
54778
  contents: contents
@@ -54874,45 +54780,39 @@ function _generateImage() {
54874
54780
  config: config
54875
54781
  } : {}));
54876
54782
  case 10:
54877
- response = _context5.sent;
54783
+ response = _context4.sent;
54878
54784
  images = [];
54879
54785
  text = '';
54880
54786
  candidate = (_response$candidates = response.candidates) === null || _response$candidates === void 0 ? void 0 : _response$candidates[0];
54881
54787
  parts = (_candidate$content$pa = candidate === null || candidate === void 0 || (_candidate$content = candidate.content) === null || _candidate$content === void 0 ? void 0 : _candidate$content.parts) !== null && _candidate$content$pa !== void 0 ? _candidate$content$pa : [];
54882
- _iterator3 = _createForOfIteratorHelper$2(parts);
54788
+ _iterator2 = _createForOfIteratorHelper$2(parts);
54883
54789
  try {
54884
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
54885
- p = _step3.value;
54790
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
54791
+ p = _step2.value;
54886
54792
  if ((_p$inlineData = p.inlineData) !== null && _p$inlineData !== void 0 && _p$inlineData.data && (_p$inlineData$mimeTyp = p.inlineData.mimeType) !== null && _p$inlineData$mimeTyp !== void 0 && _p$inlineData$mimeTyp.startsWith('image/')) {
54887
- img = {
54793
+ images.push({
54888
54794
  mimeType: p.inlineData.mimeType,
54889
54795
  base64: p.inlineData.data
54890
- };
54891
- if (p.thoughtSignature) img.thoughtSignature = p.thoughtSignature;
54892
- images.push(img);
54893
- } else if (typeof p.text === 'string') {
54894
- // Visible text contributes to `text`; pure `thought` parts only contribute their
54895
- // signature. Either way, capture the FIRST signature so the next turn can replay it.
54896
- if (!p.thought) text += p.text;
54897
- if (!textThoughtSignature && p.thoughtSignature) textThoughtSignature = p.thoughtSignature;
54796
+ });
54797
+ } else if (typeof p.text === 'string' && !p.thought) {
54798
+ text += p.text;
54898
54799
  }
54899
54800
  }
54900
54801
  } catch (err) {
54901
- _iterator3.e(err);
54802
+ _iterator2.e(err);
54902
54803
  } finally {
54903
- _iterator3.f();
54804
+ _iterator2.f();
54904
54805
  }
54905
54806
  result = {
54906
54807
  images: images
54907
54808
  };
54908
54809
  if (text) result.text = text;
54909
- if (textThoughtSignature) result.thoughtSignature = textThoughtSignature;
54910
- return _context5.abrupt("return", result);
54911
- case 21:
54810
+ return _context4.abrupt("return", result);
54811
+ case 20:
54912
54812
  case "end":
54913
- return _context5.stop();
54813
+ return _context4.stop();
54914
54814
  }
54915
- }, _callee5);
54815
+ }, _callee4);
54916
54816
  }));
54917
54817
  return _generateImage.apply(this, arguments);
54918
54818
  }
@@ -54969,6 +54869,7 @@ var apiKeyEmptyDescription = "apiKeyEmptyDescription--gLYv";
54969
54869
  var messageImg = "messageImg-i3Rcg";
54970
54870
  var composer = "composer-dJW7x";
54971
54871
  var composerRefRow = "composerRefRow-XCqFN";
54872
+ var composerFollowUpHint = "composerFollowUpHint-6VH61";
54972
54873
  var composerTextareaRow = "composerTextareaRow-1pKrk";
54973
54874
  var composerToolbarRow = "composerToolbarRow-c05wd";
54974
54875
  var composerSpacer = "composerSpacer-kQKVK";
@@ -54981,7 +54882,7 @@ var refThumbSelected = "refThumbSelected-UnCbx";
54981
54882
  var refThumbRemove = "refThumbRemove-HlsBp";
54982
54883
  var refOrderBadge = "refOrderBadge-r-h2t";
54983
54884
  var fullscreenGallerySwiper = "fullscreenGallerySwiper-y-BWH";
54984
- var css_248z = ".root-faX1F {\n display: flex;\n flex-direction: column;\n gap: 0;\n padding: 0;\n flex: 1 1 0;\n height: 100%;\n min-height: 200px;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n/* ---- Three-pane chat layout ---- */\n.layout-M1UuF {\n display: flex;\n flex-direction: row;\n flex: 1;\n min-height: 0;\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.center-viyyO {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n\n/* ---- Sidebar ---- */\n.sidebar-J4Fpm {\n display: flex;\n flex-direction: column;\n flex: 0 0 220px;\n width: 220px;\n min-width: 200px;\n height: 100%;\n min-height: 0;\n border-right: 1px solid #e8e8e8;\n border-right: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n background: #fafafa;\n background: var(--ant-color-fill-quaternary, #fafafa);\n box-sizing: border-box;\n overflow: hidden;\n transition: flex-basis 0.18s ease, width 0.18s ease, min-width 0.18s ease;\n}\n\n.sidebarCollapsed-7UyPq {\n flex: 0 0 36px;\n width: 36px;\n min-width: 36px;\n}\n\n.sidebarHeader-1mf-N {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 10px;\n border-bottom: 1px solid #e8e8e8;\n border-bottom: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n font-weight: 600;\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.sidebarCollapsed-7UyPq .sidebarHeader-1mf-N {\n padding: 6px 4px;\n justify-content: center;\n}\n\n.sidebarTitle-9f1-a {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebarActions-2aSHR {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.sidebarCollapsedActions-XIntB {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 8px 0;\n}\n\n.sidebarList-hAXzv {\n list-style: none;\n margin: 0;\n padding: 4px 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n min-height: 0;\n}\n\n.sidebarItem-A29X0 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n padding: 6px 10px;\n cursor: pointer;\n font-size: 12px;\n border-left: 2px solid transparent;\n}\n\n.sidebarItem-A29X0:hover {\n background: #f0f0f0;\n background: var(--ant-color-fill-tertiary, #f0f0f0);\n}\n\n.sidebarItemActive-Xro0V {\n background: #e6f4ff;\n background: var(--ant-color-primary-bg, #e6f4ff);\n border-left-color: #1677ff;\n border-left-color: var(--ant-color-primary, #1677ff);\n}\n\n.sidebarItemTitle-8wWaj {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebarItemActions-Nk8K4 {\n display: none;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.sidebarItemRename-ogfZC {\n display: flex;\n align-items: center;\n gap: 2px;\n flex: 1;\n min-width: 0;\n}\n\n.sidebarItemRename-ogfZC .ant-input {\n flex: 1;\n min-width: 0;\n}\n\n.sidebarItem-A29X0:hover .sidebarItemActions-Nk8K4,\n.sidebarItemActive-Xro0V .sidebarItemActions-Nk8K4 {\n display: inline-flex;\n}\n\n.sidebarEmpty-FYvqJ {\n padding: 16px 12px;\n font-size: 12px;\n opacity: 0.65;\n text-align: center;\n}\n\n.sidebarFooter-iQ7Nf {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px;\n border-top: 1px solid #e8e8e8;\n border-top: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.sidebarFooterLabel-vy635 {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n opacity: 0.7;\n}\n\n.sidebarFooterTotal-wl9LE {\n font-weight: 600;\n font-feature-settings: \"tnum\";\n font-variant-numeric: tabular-nums;\n}\n\n.sidebarFooterCollapsed-m16Gv {\n justify-content: center;\n padding: 6px 2px;\n font-weight: 600;\n font-size: 10px;\n font-feature-settings: \"tnum\";\n font-variant-numeric: tabular-nums;\n}\n\n/* ---- Chat thread ---- */\n.thread-8qRwV {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n /* Prevent wheel-scroll chaining into the outer toolbar `.container` (overflow: auto), */\n /* which would otherwise drag the sidebar along when the chat is scrolled. */\n overscroll-behavior: contain;\n box-sizing: border-box;\n}\n\n.bubbleRow-UALRR {\n display: flex;\n width: 100%;\n}\n\n.bubbleRowUser-Aa3PM {\n justify-content: flex-end;\n}\n\n.bubbleRowAssistant-WCc4Y {\n justify-content: flex-start;\n}\n\n.bubble-bavdV {\n display: flex;\n flex-direction: column;\n gap: 6px;\n max-width: 88%;\n border-radius: 10px;\n overflow: hidden;\n box-sizing: border-box;\n}\n\n.bubbleUser-nxEcz {\n background: #e6f4ff;\n background: var(--ant-color-primary-bg, #e6f4ff);\n border: 1px solid #91caff;\n border: 1px solid var(--ant-color-primary-border, #91caff);\n padding: 8px 10px;\n}\n\n.bubbleAssistant-ob-wr {\n background: #fafafa;\n background: var(--ant-color-fill-quaternary, #fafafa);\n border: 1px solid #e8e8e8;\n border: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n padding: 8px 10px;\n}\n\n.bubbleError-5wL8m {\n border-color: #ffccc7;\n border-color: var(--ant-color-error-border, #ffccc7);\n background: #fff2f0;\n background: var(--ant-color-error-bg, #fff2f0);\n}\n\n.bubblePrompt-qn6rA {\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 13px;\n line-height: 1.4;\n}\n\n.bubbleCaption-W79k0 {\n font-size: 11px;\n opacity: 0.78;\n display: flex;\n flex-wrap: wrap;\n gap: 0 2px;\n}\n\n.bubbleImageGrid-UVzXc {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n grid-gap: 6px;\n gap: 6px;\n}\n\n.bubbleImageItem-CGiZz {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.bubbleImageCost-B2PYt {\n font-size: 10.5px;\n line-height: 1.2;\n font-feature-settings: \"tnum\";\n font-variant-numeric: tabular-nums;\n opacity: 0.7;\n text-align: right;\n padding: 0 2px;\n}\n\n/* Pending/error rows use plain flex so spinner + label + cancel stay on one line. */\n.bubblePending-4Q3z9 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 4px 4px;\n min-width: 0;\n}\n\n.bubblePendingLabel-fll-a {\n flex: 1 1 auto;\n min-width: 0;\n font-size: 13px;\n line-height: 1.3;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.bubbleErrorBody-LZG-A {\n padding: 8px 4px;\n font-size: 13px;\n line-height: 1.4;\n word-break: break-word;\n}\n\n.threadActions-fpeBf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0 8px;\n margin-top: 2px;\n}\n\n.emptyState-YK-o7 {\n margin: auto;\n padding: 24px;\n text-align: center;\n font-size: 13px;\n opacity: 0.6;\n}\n\n/* ---- API key empty state ---- */\n.apiKeyEmpty-BcMz1 {\n margin: auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n padding: 24px;\n max-width: 420px;\n text-align: center;\n}\n\n.apiKeyEmptyTitle-oSAhY {\n font-size: 14px;\n font-weight: 600;\n}\n\n.apiKeyEmptyDescription--gLYv {\n font-size: 12px;\n opacity: 0.72;\n line-height: 1.5;\n}\n\n/* ---- Message images ---- */\n.messageImg-i3Rcg {\n display: block;\n width: 100%;\n padding: 0;\n margin: 0;\n border: 0;\n background: transparent;\n cursor: pointer;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.messageImg-i3Rcg img {\n display: block;\n width: 100%;\n height: auto;\n -o-object-fit: cover;\n object-fit: cover;\n}\n\n/* ---- Composer ---- */\n.composer-dJW7x {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 12px 12px;\n border-top: 1px solid #e8e8e8;\n border-top: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n background: #fff;\n background: var(--ant-color-bg-container, #fff);\n position: relative;\n}\n\n.composerRefRow-XCqFN {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.composerTextareaRow-1pKrk {\n display: block;\n width: 100%;\n}\n\n.composerTextareaRow-1pKrk .ant-input,\n.composerTextareaRow-1pKrk textarea {\n width: 100%;\n resize: vertical;\n}\n\n.composerToolbarRow-c05wd {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 6px;\n}\n\n.composerSpacer-kQKVK {\n flex: 1;\n}\n\n.hiddenFileInput-XdLJ3 {\n display: none;\n}\n\n.composerSettings-As0sF {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 280px;\n}\n\n.composerSettingsRow-8v1xx {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n justify-content: space-between;\n}\n\n/* ---- Reference image thumbnails (composer) ---- */\n.refThumbRow-KlFhj {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n flex: 1;\n min-width: 0;\n}\n\n.refThumb-d--qS {\n position: relative;\n width: 44px;\n height: 44px;\n padding: 0;\n border: 2px solid transparent;\n border-radius: 6px;\n overflow: hidden;\n cursor: pointer;\n background: #f5f5f5;\n background: var(--ant-color-fill-secondary, #f5f5f5);\n flex-shrink: 0;\n}\n\n.refThumb-d--qS img {\n width: 100%;\n height: 100%;\n -o-object-fit: cover;\n object-fit: cover;\n display: block;\n}\n\n.refThumb-d--qS:hover {\n border-color: #91caff;\n border-color: var(--ant-color-primary-border-hover, #91caff);\n}\n\n.refThumbSelected-UnCbx {\n border-color: #1677ff;\n border-color: var(--ant-color-primary, #1677ff);\n box-shadow: 0 0 0 1px #1677ff;\n box-shadow: 0 0 0 1px var(--ant-color-primary, #1677ff);\n}\n\n.refThumbRemove-HlsBp {\n position: absolute;\n top: -6px;\n right: -6px;\n width: 16px;\n height: 16px;\n padding: 0;\n border-radius: 50%;\n border: 1px solid #d9d9d9;\n border: 1px solid var(--ant-color-border, #d9d9d9);\n background: #fff;\n background: var(--ant-color-bg-container, #fff);\n color: rgba(0, 0, 0, 0.65);\n color: var(--ant-color-text, rgba(0, 0, 0, 0.65));\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1;\n}\n\n.refThumbRemove-HlsBp:hover {\n border-color: #ff4d4f;\n border-color: var(--ant-color-error, #ff4d4f);\n color: #ff4d4f;\n color: var(--ant-color-error, #ff4d4f);\n}\n\n.refOrderBadge-r-h2t {\n position: absolute;\n top: 2px;\n left: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: #1677ff;\n background: var(--ant-color-primary, #1677ff);\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n pointer-events: none;\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85);\n}\n\n/* ---- Fullscreen gallery (image lightbox) ---- */\n.fullscreenGallerySwiper-y-BWH {\n position: relative;\n width: 100%;\n height: 100%;\n min-height: 220px;\n box-sizing: border-box;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-slide {\n width: 100%;\n box-sizing: border-box;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-prev,\n.fullscreenGallerySwiper-y-BWH .swiper-button-next {\n width: 40px;\n height: 40px;\n margin-top: 0;\n top: 42%;\n color: rgba(255, 255, 255, 0.95);\n background: transparent;\n border-radius: 0;\n box-shadow: none;\n text-shadow: 0 0 8px rgba(0, 0, 0, 0.85), 0 1px 3px rgba(0, 0, 0, 0.9);\n z-index: 2;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-prev::after,\n.fullscreenGallerySwiper-y-BWH .swiper-button-next::after {\n font-size: 13px;\n font-weight: 700;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-prev {\n left: 10px;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-next {\n right: 10px;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-disabled {\n opacity: 0.28;\n pointer-events: none;\n}\n";
54885
+ var css_248z = ".root-faX1F {\n display: flex;\n flex-direction: column;\n gap: 0;\n padding: 0;\n flex: 1 1 0;\n height: 100%;\n min-height: 200px;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n/* ---- Three-pane chat layout ---- */\n.layout-M1UuF {\n display: flex;\n flex-direction: row;\n flex: 1;\n min-height: 0;\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.center-viyyO {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n\n/* ---- Sidebar ---- */\n.sidebar-J4Fpm {\n display: flex;\n flex-direction: column;\n flex: 0 0 220px;\n width: 220px;\n min-width: 200px;\n height: 100%;\n min-height: 0;\n border-right: 1px solid #e8e8e8;\n border-right: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n background: #fafafa;\n background: var(--ant-color-fill-quaternary, #fafafa);\n box-sizing: border-box;\n overflow: hidden;\n transition: flex-basis 0.18s ease, width 0.18s ease, min-width 0.18s ease;\n}\n\n.sidebarCollapsed-7UyPq {\n flex: 0 0 36px;\n width: 36px;\n min-width: 36px;\n}\n\n.sidebarHeader-1mf-N {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 10px;\n border-bottom: 1px solid #e8e8e8;\n border-bottom: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n font-weight: 600;\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.sidebarCollapsed-7UyPq .sidebarHeader-1mf-N {\n padding: 6px 4px;\n justify-content: center;\n}\n\n.sidebarTitle-9f1-a {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebarActions-2aSHR {\n display: flex;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.sidebarCollapsedActions-XIntB {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 8px 0;\n}\n\n.sidebarList-hAXzv {\n list-style: none;\n margin: 0;\n padding: 4px 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n min-height: 0;\n}\n\n.sidebarItem-A29X0 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n padding: 6px 10px;\n cursor: pointer;\n font-size: 12px;\n border-left: 2px solid transparent;\n}\n\n.sidebarItem-A29X0:hover {\n background: #f0f0f0;\n background: var(--ant-color-fill-tertiary, #f0f0f0);\n}\n\n.sidebarItemActive-Xro0V {\n background: #e6f4ff;\n background: var(--ant-color-primary-bg, #e6f4ff);\n border-left-color: #1677ff;\n border-left-color: var(--ant-color-primary, #1677ff);\n}\n\n.sidebarItemTitle-8wWaj {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sidebarItemActions-Nk8K4 {\n display: none;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.sidebarItemRename-ogfZC {\n display: flex;\n align-items: center;\n gap: 2px;\n flex: 1;\n min-width: 0;\n}\n\n.sidebarItemRename-ogfZC .ant-input {\n flex: 1;\n min-width: 0;\n}\n\n.sidebarItem-A29X0:hover .sidebarItemActions-Nk8K4,\n.sidebarItemActive-Xro0V .sidebarItemActions-Nk8K4 {\n display: inline-flex;\n}\n\n.sidebarEmpty-FYvqJ {\n padding: 16px 12px;\n font-size: 12px;\n opacity: 0.65;\n text-align: center;\n}\n\n.sidebarFooter-iQ7Nf {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px;\n border-top: 1px solid #e8e8e8;\n border-top: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.sidebarFooterLabel-vy635 {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n opacity: 0.7;\n}\n\n.sidebarFooterTotal-wl9LE {\n font-weight: 600;\n font-feature-settings: \"tnum\";\n font-variant-numeric: tabular-nums;\n}\n\n.sidebarFooterCollapsed-m16Gv {\n justify-content: center;\n padding: 6px 2px;\n font-weight: 600;\n font-size: 10px;\n font-feature-settings: \"tnum\";\n font-variant-numeric: tabular-nums;\n}\n\n/* ---- Chat thread ---- */\n.thread-8qRwV {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n /* Prevent wheel-scroll chaining into the outer toolbar `.container` (overflow: auto), */\n /* which would otherwise drag the sidebar along when the chat is scrolled. */\n overscroll-behavior: contain;\n box-sizing: border-box;\n}\n\n.bubbleRow-UALRR {\n display: flex;\n width: 100%;\n}\n\n.bubbleRowUser-Aa3PM {\n justify-content: flex-end;\n}\n\n.bubbleRowAssistant-WCc4Y {\n justify-content: flex-start;\n}\n\n.bubble-bavdV {\n display: flex;\n flex-direction: column;\n gap: 6px;\n max-width: 88%;\n border-radius: 10px;\n overflow: hidden;\n box-sizing: border-box;\n}\n\n.bubbleUser-nxEcz {\n background: #e6f4ff;\n background: var(--ant-color-primary-bg, #e6f4ff);\n border: 1px solid #91caff;\n border: 1px solid var(--ant-color-primary-border, #91caff);\n padding: 8px 10px;\n}\n\n.bubbleAssistant-ob-wr {\n background: #fafafa;\n background: var(--ant-color-fill-quaternary, #fafafa);\n border: 1px solid #e8e8e8;\n border: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n padding: 8px 10px;\n}\n\n.bubbleError-5wL8m {\n border-color: #ffccc7;\n border-color: var(--ant-color-error-border, #ffccc7);\n background: #fff2f0;\n background: var(--ant-color-error-bg, #fff2f0);\n}\n\n.bubblePrompt-qn6rA {\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 13px;\n line-height: 1.4;\n}\n\n.bubbleCaption-W79k0 {\n font-size: 11px;\n opacity: 0.78;\n display: flex;\n flex-wrap: wrap;\n gap: 0 2px;\n}\n\n.bubbleImageGrid-UVzXc {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n grid-gap: 6px;\n gap: 6px;\n}\n\n.bubbleImageItem-CGiZz {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.bubbleImageCost-B2PYt {\n font-size: 10.5px;\n line-height: 1.2;\n font-feature-settings: \"tnum\";\n font-variant-numeric: tabular-nums;\n opacity: 0.7;\n text-align: right;\n padding: 0 2px;\n}\n\n/* Pending/error rows use plain flex so spinner + label + cancel stay on one line. */\n.bubblePending-4Q3z9 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 4px 4px;\n min-width: 0;\n}\n\n.bubblePendingLabel-fll-a {\n flex: 1 1 auto;\n min-width: 0;\n font-size: 13px;\n line-height: 1.3;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.bubbleErrorBody-LZG-A {\n padding: 8px 4px;\n font-size: 13px;\n line-height: 1.4;\n word-break: break-word;\n}\n\n.threadActions-fpeBf {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0 8px;\n margin-top: 2px;\n}\n\n.emptyState-YK-o7 {\n margin: auto;\n padding: 24px;\n text-align: center;\n font-size: 13px;\n opacity: 0.6;\n}\n\n/* ---- API key empty state ---- */\n.apiKeyEmpty-BcMz1 {\n margin: auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n padding: 24px;\n max-width: 420px;\n text-align: center;\n}\n\n.apiKeyEmptyTitle-oSAhY {\n font-size: 14px;\n font-weight: 600;\n}\n\n.apiKeyEmptyDescription--gLYv {\n font-size: 12px;\n opacity: 0.72;\n line-height: 1.5;\n}\n\n/* ---- Message images ---- */\n.messageImg-i3Rcg {\n display: block;\n width: 100%;\n padding: 0;\n margin: 0;\n border: 0;\n background: transparent;\n cursor: pointer;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.messageImg-i3Rcg img {\n display: block;\n width: 100%;\n height: auto;\n -o-object-fit: cover;\n object-fit: cover;\n}\n\n/* ---- Composer ---- */\n.composer-dJW7x {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 12px 12px;\n border-top: 1px solid #e8e8e8;\n border-top: 1px solid var(--ant-color-border-secondary, #e8e8e8);\n background: #fff;\n background: var(--ant-color-bg-container, #fff);\n position: relative;\n}\n\n.composerRefRow-XCqFN {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n/* Hint shown in the composer once the chat has produced its first image: every\n * follow-up automatically refines that image, so reference uploads are hidden. */\n.composerFollowUpHint-6VH61 {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n font-size: 11.5px;\n line-height: 1.4;\n color: rgba(0, 0, 0, 0.65);\n color: var(--ant-color-text-secondary, rgba(0, 0, 0, 0.65));\n background: #fafafa;\n background: var(--ant-color-fill-quaternary, #fafafa);\n border: 1px dashed #e8e8e8;\n border: 1px dashed var(--ant-color-border-secondary, #e8e8e8);\n border-radius: 6px;\n}\n\n.composerTextareaRow-1pKrk {\n display: block;\n width: 100%;\n}\n\n.composerTextareaRow-1pKrk .ant-input,\n.composerTextareaRow-1pKrk textarea {\n width: 100%;\n resize: vertical;\n}\n\n.composerToolbarRow-c05wd {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 6px;\n}\n\n.composerSpacer-kQKVK {\n flex: 1;\n}\n\n.hiddenFileInput-XdLJ3 {\n display: none;\n}\n\n.composerSettings-As0sF {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 280px;\n}\n\n.composerSettingsRow-8v1xx {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n justify-content: space-between;\n}\n\n/* ---- Reference image thumbnails (composer) ---- */\n.refThumbRow-KlFhj {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n flex: 1;\n min-width: 0;\n}\n\n.refThumb-d--qS {\n position: relative;\n width: 44px;\n height: 44px;\n padding: 0;\n border: 2px solid transparent;\n border-radius: 6px;\n overflow: hidden;\n cursor: pointer;\n background: #f5f5f5;\n background: var(--ant-color-fill-secondary, #f5f5f5);\n flex-shrink: 0;\n}\n\n.refThumb-d--qS img {\n width: 100%;\n height: 100%;\n -o-object-fit: cover;\n object-fit: cover;\n display: block;\n}\n\n.refThumb-d--qS:hover {\n border-color: #91caff;\n border-color: var(--ant-color-primary-border-hover, #91caff);\n}\n\n.refThumbSelected-UnCbx {\n border-color: #1677ff;\n border-color: var(--ant-color-primary, #1677ff);\n box-shadow: 0 0 0 1px #1677ff;\n box-shadow: 0 0 0 1px var(--ant-color-primary, #1677ff);\n}\n\n.refThumbRemove-HlsBp {\n position: absolute;\n top: -6px;\n right: -6px;\n width: 16px;\n height: 16px;\n padding: 0;\n border-radius: 50%;\n border: 1px solid #d9d9d9;\n border: 1px solid var(--ant-color-border, #d9d9d9);\n background: #fff;\n background: var(--ant-color-bg-container, #fff);\n color: rgba(0, 0, 0, 0.65);\n color: var(--ant-color-text, rgba(0, 0, 0, 0.65));\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1;\n}\n\n.refThumbRemove-HlsBp:hover {\n border-color: #ff4d4f;\n border-color: var(--ant-color-error, #ff4d4f);\n color: #ff4d4f;\n color: var(--ant-color-error, #ff4d4f);\n}\n\n.refOrderBadge-r-h2t {\n position: absolute;\n top: 2px;\n left: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: #1677ff;\n background: var(--ant-color-primary, #1677ff);\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n pointer-events: none;\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.85);\n}\n\n/* ---- Fullscreen gallery (image lightbox) ---- */\n.fullscreenGallerySwiper-y-BWH {\n position: relative;\n width: 100%;\n height: 100%;\n min-height: 220px;\n box-sizing: border-box;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-slide {\n width: 100%;\n box-sizing: border-box;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-prev,\n.fullscreenGallerySwiper-y-BWH .swiper-button-next {\n width: 40px;\n height: 40px;\n margin-top: 0;\n top: 42%;\n color: rgba(255, 255, 255, 0.95);\n background: transparent;\n border-radius: 0;\n box-shadow: none;\n text-shadow: 0 0 8px rgba(0, 0, 0, 0.85), 0 1px 3px rgba(0, 0, 0, 0.9);\n z-index: 2;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-prev::after,\n.fullscreenGallerySwiper-y-BWH .swiper-button-next::after {\n font-size: 13px;\n font-weight: 700;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-prev {\n left: 10px;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-next {\n right: 10px;\n}\n\n.fullscreenGallerySwiper-y-BWH .swiper-button-disabled {\n opacity: 0.28;\n pointer-events: none;\n}\n";
54985
54886
  styleInject(css_248z);
54986
54887
 
54987
54888
  function ownKeys$4(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
@@ -54997,9 +54898,14 @@ function ChatComposer(_ref) {
54997
54898
  onReferenceUpload = _ref.onReferenceUpload,
54998
54899
  onRemoveReference = _ref.onRemoveReference,
54999
54900
  pending = _ref.pending,
54901
+ isFollowUp = _ref.isFollowUp,
55000
54902
  onSend = _ref.onSend,
55001
54903
  hasApiKey = _ref.hasApiKey,
55002
- onRequestApiKey = _ref.onRequestApiKey;
54904
+ onRequestApiKey = _ref.onRequestApiKey,
54905
+ preservePromptTemplate = _ref.preservePromptTemplate,
54906
+ preservePromptIsCustom = _ref.preservePromptIsCustom,
54907
+ onPreservePromptTemplateChange = _ref.onPreservePromptTemplateChange,
54908
+ onResetPreservePromptTemplate = _ref.onResetPreservePromptTemplate;
55003
54909
  var _useTranslation = useTranslation(),
55004
54910
  t = _useTranslation.t;
55005
54911
  var models = promptAndAiTesterOptions.aiImageTester.models;
@@ -55157,11 +55063,73 @@ function ChatComposer(_ref) {
55157
55063
  })
55158
55064
  }) : null]
55159
55065
  })]
55066
+ }), /*#__PURE__*/jsxs("div", {
55067
+ className: composerSettingsRow,
55068
+ style: {
55069
+ flexDirection: 'column',
55070
+ alignItems: 'stretch',
55071
+ gap: 4
55072
+ },
55073
+ children: [/*#__PURE__*/jsxs("div", {
55074
+ style: {
55075
+ display: 'flex',
55076
+ alignItems: 'center',
55077
+ justifyContent: 'space-between',
55078
+ gap: 8
55079
+ },
55080
+ children: [/*#__PURE__*/jsx("span", {
55081
+ children: t('backoffice.tools.aiPromptImageTester.preservePrompt', {
55082
+ defaultValue: 'Follow-up wrapper prompt'
55083
+ })
55084
+ }), preservePromptIsCustom ? /*#__PURE__*/jsx(Button$1, {
55085
+ type: "link",
55086
+ size: "small",
55087
+ style: {
55088
+ padding: 0
55089
+ },
55090
+ onClick: onResetPreservePromptTemplate,
55091
+ children: t('backoffice.tools.aiPromptImageTester.preservePromptReset', {
55092
+ defaultValue: 'Reset to default'
55093
+ })
55094
+ }) : null]
55095
+ }), /*#__PURE__*/jsx(Input$2.TextArea, {
55096
+ value: preservePromptTemplate,
55097
+ onChange: function onChange(e) {
55098
+ return onPreservePromptTemplateChange(e.target.value);
55099
+ },
55100
+ autoSize: {
55101
+ minRows: 4,
55102
+ maxRows: 10
55103
+ },
55104
+ spellCheck: false
55105
+ }), /*#__PURE__*/jsx("span", {
55106
+ style: {
55107
+ fontSize: 11,
55108
+ opacity: 0.65,
55109
+ lineHeight: 1.4
55110
+ },
55111
+ children: t('backoffice.tools.aiPromptImageTester.preservePromptHint', {
55112
+ defaultValue: "Wraps every follow-up edit. Keep the ".concat(PRESERVE_PROMPT_PLACEHOLDER, " token \u2014 it is replaced with what you type. Stored locally in this browser.")
55113
+ })
55114
+ })]
55160
55115
  })]
55161
55116
  });
55117
+ var placeholder = isFollowUp ? t('backoffice.tools.aiPromptImageTester.composerPlaceholderFollowUp', {
55118
+ defaultValue: 'Tweak the image: add something, change the camera angle, restyle the lighting… (Cmd/Ctrl+Enter to send)'
55119
+ }) : t('backoffice.tools.aiPromptImageTester.composerPlaceholder', {
55120
+ defaultValue: 'Describe the image (Cmd/Ctrl+Enter to send)'
55121
+ });
55122
+ var followUpHintText = isFollowUp ? selectedRefIds.length > 0 ? t('backoffice.tools.aiPromptImageTester.followUpHintWithRefs', {
55123
+ defaultValue: 'Refining the last image. The selected reference(s) will be added to this edit (e.g. "add this lamp left of the sofa").'
55124
+ }) : t('backoffice.tools.aiPromptImageTester.followUpHint', {
55125
+ defaultValue: 'Refining the last image — same scene, just your tweak applied. Attach a reference to add a new element, or start a new chat for a different scene.'
55126
+ }) : null;
55162
55127
  return /*#__PURE__*/jsxs("div", {
55163
55128
  className: composer,
55164
- children: [refs.length > 0 ? /*#__PURE__*/jsxs("div", {
55129
+ children: [followUpHintText ? /*#__PURE__*/jsx("div", {
55130
+ className: composerFollowUpHint,
55131
+ children: followUpHintText
55132
+ }) : null, refs.length > 0 ? /*#__PURE__*/jsxs("div", {
55165
55133
  className: composerRefRow,
55166
55134
  children: [/*#__PURE__*/jsx("div", {
55167
55135
  className: refThumbRow,
@@ -55225,9 +55193,7 @@ function ChatComposer(_ref) {
55225
55193
  return setText(e.target.value);
55226
55194
  },
55227
55195
  onKeyDown: onKeyDown,
55228
- placeholder: t('backoffice.tools.aiPromptImageTester.composerPlaceholder', {
55229
- defaultValue: 'Describe the image (Cmd/Ctrl+Enter to send)'
55230
- }),
55196
+ placeholder: placeholder,
55231
55197
  autoSize: {
55232
55198
  minRows: 2,
55233
55199
  maxRows: 8
@@ -56043,25 +56009,25 @@ function ConversationSidebar(_ref) {
56043
56009
  });
56044
56010
  }
56045
56011
 
56046
- var STORAGE_KEY = 'diva-backoffice.aiPromptImageTester.geminiApiKey';
56012
+ var STORAGE_KEY$1 = 'diva-backoffice.aiPromptImageTester.geminiApiKey';
56047
56013
  function loadApiKey() {
56048
56014
  try {
56049
56015
  var _window$localStorage$;
56050
- return (_window$localStorage$ = window.localStorage.getItem(STORAGE_KEY)) !== null && _window$localStorage$ !== void 0 ? _window$localStorage$ : '';
56016
+ return (_window$localStorage$ = window.localStorage.getItem(STORAGE_KEY$1)) !== null && _window$localStorage$ !== void 0 ? _window$localStorage$ : '';
56051
56017
  } catch (_unused) {
56052
56018
  return '';
56053
56019
  }
56054
56020
  }
56055
56021
  function saveApiKey(key) {
56056
56022
  try {
56057
- window.localStorage.setItem(STORAGE_KEY, key);
56023
+ window.localStorage.setItem(STORAGE_KEY$1, key);
56058
56024
  } catch (_unused2) {
56059
56025
  /* ignore quota / disabled storage */
56060
56026
  }
56061
56027
  }
56062
56028
  function clearApiKey() {
56063
56029
  try {
56064
- window.localStorage.removeItem(STORAGE_KEY);
56030
+ window.localStorage.removeItem(STORAGE_KEY$1);
56065
56031
  } catch (_unused3) {
56066
56032
  /* ignore */
56067
56033
  }
@@ -56081,7 +56047,7 @@ function useApiKey() {
56081
56047
  useEffect(function () {
56082
56048
  var onStorage = function onStorage(e) {
56083
56049
  var _e$newValue;
56084
- if (e.key !== STORAGE_KEY) return;
56050
+ if (e.key !== STORAGE_KEY$1) return;
56085
56051
  setApiKeyState((_e$newValue = e.newValue) !== null && _e$newValue !== void 0 ? _e$newValue : '');
56086
56052
  };
56087
56053
  window.addEventListener('storage', onStorage);
@@ -56371,15 +56337,81 @@ function GalleryFullscreenContent(_ref) {
56371
56337
  });
56372
56338
  }
56373
56339
 
56340
+ var STORAGE_KEY = 'diva-backoffice.aiPromptImageTester.preservePromptTemplate';
56341
+ function loadPreservePromptTemplate() {
56342
+ try {
56343
+ var raw = window.localStorage.getItem(STORAGE_KEY);
56344
+ if (raw && raw.trim().length > 0) return raw;
56345
+ } catch (_unused) {
56346
+ /* ignore disabled / quota */
56347
+ }
56348
+ return DEFAULT_PRESERVE_PROMPT_TEMPLATE;
56349
+ }
56350
+ function savePreservePromptTemplate(template) {
56351
+ try {
56352
+ if (template.trim().length === 0 || template === DEFAULT_PRESERVE_PROMPT_TEMPLATE) {
56353
+ // Nothing to persist — drop the key so future default changes propagate.
56354
+ window.localStorage.removeItem(STORAGE_KEY);
56355
+ return;
56356
+ }
56357
+ window.localStorage.setItem(STORAGE_KEY, template);
56358
+ } catch (_unused2) {
56359
+ /* ignore */
56360
+ }
56361
+ }
56362
+ function clearPreservePromptTemplate() {
56363
+ try {
56364
+ window.localStorage.removeItem(STORAGE_KEY);
56365
+ } catch (_unused3) {
56366
+ /* ignore */
56367
+ }
56368
+ }
56369
+
56370
+ /**
56371
+ * React hook returning the active preserve-prompt template plus mutators.
56372
+ *
56373
+ * `isCustom` flags whether the user has overridden the default — handy for
56374
+ * the UI to surface a "Reset to default" affordance only when meaningful.
56375
+ */
56376
+ function usePreservePromptTemplate() {
56377
+ var _useState = useState(function () {
56378
+ return loadPreservePromptTemplate();
56379
+ }),
56380
+ _useState2 = _slicedToArray(_useState, 2),
56381
+ template = _useState2[0],
56382
+ setTemplateState = _useState2[1];
56383
+ useEffect(function () {
56384
+ var onStorage = function onStorage(e) {
56385
+ if (e.key !== STORAGE_KEY) return;
56386
+ var next = e.newValue && e.newValue.trim().length > 0 ? e.newValue : DEFAULT_PRESERVE_PROMPT_TEMPLATE;
56387
+ setTemplateState(next);
56388
+ };
56389
+ window.addEventListener('storage', onStorage);
56390
+ return function () {
56391
+ return window.removeEventListener('storage', onStorage);
56392
+ };
56393
+ }, []);
56394
+ return {
56395
+ template: template,
56396
+ isCustom: template !== DEFAULT_PRESERVE_PROMPT_TEMPLATE,
56397
+ setTemplate: function setTemplate(next) {
56398
+ var value = next.trim().length > 0 ? next : DEFAULT_PRESERVE_PROMPT_TEMPLATE;
56399
+ savePreservePromptTemplate(value);
56400
+ setTemplateState(value);
56401
+ },
56402
+ reset: function reset() {
56403
+ clearPreservePromptTemplate();
56404
+ setTemplateState(DEFAULT_PRESERVE_PROMPT_TEMPLATE);
56405
+ }
56406
+ };
56407
+ }
56408
+
56374
56409
  function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
56375
56410
  function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
56376
56411
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
56377
56412
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
56378
56413
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
56379
56414
  var aiImageTester = promptAndAiTesterOptions.aiImageTester;
56380
-
56381
- /** Runaway-protection floor on history depth. Normal iterative use never reaches it. */
56382
- var MAX_HISTORY_TURNS = 50;
56383
56415
  function defaultSettings() {
56384
56416
  return {
56385
56417
  model: aiImageTester.defaultModel,
@@ -56395,6 +56427,11 @@ function useAiChat(openFullscreen) {
56395
56427
  hasKey = _useApiKey.hasKey,
56396
56428
  setApiKey = _useApiKey.setApiKey,
56397
56429
  clearApiKey = _useApiKey.clear;
56430
+ var _usePreservePromptTem = usePreservePromptTemplate(),
56431
+ preservePromptTemplate = _usePreservePromptTem.template,
56432
+ preservePromptIsCustom = _usePreservePromptTem.isCustom,
56433
+ setPreservePromptTemplate = _usePreservePromptTem.setTemplate,
56434
+ resetPreservePromptTemplate = _usePreservePromptTem.reset;
56398
56435
  var _useState = useState([]),
56399
56436
  _useState2 = _slicedToArray(_useState, 2),
56400
56437
  conversations = _useState2[0],
@@ -56421,12 +56458,8 @@ function useAiChat(openFullscreen) {
56421
56458
  setSelectedRefIds = _useState12[1];
56422
56459
  var _useState13 = useState(false),
56423
56460
  _useState14 = _slicedToArray(_useState13, 2),
56424
- bootstrapped = _useState14[0],
56425
- setBootstrapped = _useState14[1];
56426
- var _useState15 = useState(false),
56427
- _useState16 = _slicedToArray(_useState15, 2),
56428
- apiKeyModalOpen = _useState16[0],
56429
- setApiKeyModalOpen = _useState16[1];
56461
+ apiKeyModalOpen = _useState14[0],
56462
+ setApiKeyModalOpen = _useState14[1];
56430
56463
  var pendingRequests = useRef(new Map());
56431
56464
  useEffect(function () {
56432
56465
  var cancelled = false;
@@ -56481,14 +56514,10 @@ function useAiChat(openFullscreen) {
56481
56514
  case 26:
56482
56515
  message$1.error("AI tester storage error: ".concat(_context.t0 instanceof Error ? _context.t0.message : String(_context.t0)));
56483
56516
  case 27:
56484
- _context.prev = 27;
56485
- if (!cancelled) setBootstrapped(true);
56486
- return _context.finish(27);
56487
- case 30:
56488
56517
  case "end":
56489
56518
  return _context.stop();
56490
56519
  }
56491
- }, _callee, null, [[0, 22, 27, 30]]);
56520
+ }, _callee, null, [[0, 22]]);
56492
56521
  }))();
56493
56522
  return function () {
56494
56523
  cancelled = true;
@@ -56636,6 +56665,15 @@ function useAiChat(openFullscreen) {
56636
56665
  return c.id === activeConversationId;
56637
56666
  })) !== null && _conversations$find !== void 0 ? _conversations$find : null;
56638
56667
  }, [conversations, activeConversationId]);
56668
+
56669
+ // True once the active chat has produced at least one ready model image. The
56670
+ // composer uses this to switch into "refine the latest image" mode (hide the
56671
+ // reference picker, surface the new-chat hint).
56672
+ var isFollowUp = useMemo(function () {
56673
+ return messages.some(function (m) {
56674
+ return m.kind === 'model' && m.status === 'ready' && m.imageIds.length > 0;
56675
+ });
56676
+ }, [messages]);
56639
56677
  var newConversation = useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
56640
56678
  var _activeConversation$s;
56641
56679
  var created;
@@ -56845,11 +56883,6 @@ function useAiChat(openFullscreen) {
56845
56883
  var clearRefSelection = useCallback(function () {
56846
56884
  return setSelectedRefIds([]);
56847
56885
  }, []);
56848
- var selectAllRefs = useCallback(function () {
56849
- return setSelectedRefIds(refs.map(function (r) {
56850
- return r.id;
56851
- }));
56852
- }, [refs]);
56853
56886
  var removeReference = useCallback(/*#__PURE__*/function () {
56854
56887
  var _ref10 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee10(id) {
56855
56888
  var refreshed;
@@ -56901,7 +56934,7 @@ function useAiChat(openFullscreen) {
56901
56934
  }(), []);
56902
56935
  var sendMessage = useCallback(/*#__PURE__*/function () {
56903
56936
  var _ref12 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee12(text) {
56904
- var conv, trimmed, selectedRefs, uploadedImageIds, priorRecords, userRecord, requestId, startedAt, resolutionCaption, temperatureCaption, modelRecord, userView, modelView, controller, dismissLoading, ai, contents, result, pricePerImage, imageIds, title, updated, msg;
56937
+ var conv, trimmed, priorRecords, lastReadyModel, selectedRefImageIds, promptForModel, referenceImageIds, userRecordImageIds, composite, userRecord, requestId, startedAt, resolutionCaption, temperatureCaption, modelRecord, userView, modelView, controller, dismissLoading, ai, contents, _contents$, result, pricePerImage, imageIds, _iterator2, _step2, img, id, title, updated, msg;
56905
56938
  return _regeneratorRuntime.wrap(function _callee12$(_context12) {
56906
56939
  while (1) switch (_context12.prev = _context12.next) {
56907
56940
  case 0:
@@ -56927,33 +56960,47 @@ function useAiChat(openFullscreen) {
56927
56960
  setApiKeyModalOpen(true);
56928
56961
  return _context12.abrupt("return");
56929
56962
  case 10:
56930
- selectedRefs = selectedRefIds.map(function (id) {
56963
+ _context12.next = 12;
56964
+ return listMessages(conv.id);
56965
+ case 12:
56966
+ priorRecords = _context12.sent;
56967
+ lastReadyModel = _toConsumableArray(priorRecords).reverse().find(function (r) {
56968
+ return r.kind === 'model' && r.status === 'ready' && r.imageIds.length > 0;
56969
+ });
56970
+ selectedRefImageIds = selectedRefIds.map(function (id) {
56931
56971
  return refs.find(function (r) {
56932
56972
  return r.id === id;
56933
56973
  });
56934
56974
  }).filter(function (r) {
56935
56975
  return !!r;
56936
- });
56937
- uploadedImageIds = selectedRefs.map(function (r) {
56976
+ }).map(function (r) {
56938
56977
  return r.imageId;
56939
- }); // Snapshot completed history BEFORE persisting the new user prompt so it isn't echoed.
56940
- _context12.next = 14;
56941
- return listMessages(conv.id);
56942
- case 14:
56943
- priorRecords = _context12.sent.slice(-MAX_HISTORY_TURNS);
56944
- _context12.next = 17;
56978
+ });
56979
+ if (lastReadyModel) {
56980
+ composite = lastReadyModel.imageIds[0];
56981
+ referenceImageIds = [composite].concat(_toConsumableArray(selectedRefImageIds));
56982
+ promptForModel = wrapPreservePrompt(trimmed, preservePromptTemplate, selectedRefImageIds.length);
56983
+ userRecordImageIds = selectedRefImageIds;
56984
+ } else {
56985
+ promptForModel = trimmed;
56986
+ referenceImageIds = selectedRefImageIds;
56987
+ userRecordImageIds = selectedRefImageIds;
56988
+ }
56989
+ _context12.next = 18;
56945
56990
  return putUserMessage({
56946
56991
  conversationId: conv.id,
56947
56992
  text: trimmed,
56948
- uploadedImageIds: uploadedImageIds
56993
+ uploadedImageIds: userRecordImageIds
56949
56994
  });
56950
- case 17:
56995
+ case 18:
56951
56996
  userRecord = _context12.sent;
56952
- requestId = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function' ? crypto.randomUUID() : "r-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 11));
56953
- startedAt = Date.now();
56997
+ requestId = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function' ? crypto.randomUUID() : "r-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 11)); // Force strict ordering relative to the user record we just wrote. `Date.now()` has
56998
+ // ms resolution so the two writes frequently collide; bumping by 1ms guarantees the
56999
+ // model row sorts after its user row in the `byConversationTs` index.
57000
+ startedAt = Math.max(Date.now(), userRecord.ts + 1);
56954
57001
  resolutionCaption = galleryImageConfigCaption(conv.settings.aspectRatio, conv.settings.imageSize);
56955
57002
  temperatureCaption = galleryTemperatureCaption(conv.settings.temperature, t);
56956
- _context12.next = 24;
57003
+ _context12.next = 25;
56957
57004
  return putModelMessage({
56958
57005
  conversationId: conv.id,
56959
57006
  status: 'pending',
@@ -56964,15 +57011,15 @@ function useAiChat(openFullscreen) {
56964
57011
  temperatureCaption: temperatureCaption,
56965
57012
  ts: startedAt
56966
57013
  });
56967
- case 24:
57014
+ case 25:
56968
57015
  modelRecord = _context12.sent;
56969
- _context12.next = 27;
57016
+ _context12.next = 28;
56970
57017
  return toMessageView(userRecord);
56971
- case 27:
57018
+ case 28:
56972
57019
  userView = _context12.sent;
56973
- _context12.next = 30;
57020
+ _context12.next = 31;
56974
57021
  return toMessageView(modelRecord);
56975
- case 30:
57022
+ case 31:
56976
57023
  modelView = _context12.sent;
56977
57024
  setMessages(function (prev) {
56978
57025
  return [].concat(_toConsumableArray(prev), [userView, modelView]);
@@ -56984,13 +57031,30 @@ function useAiChat(openFullscreen) {
56984
57031
  modelMessageId: modelRecord.id
56985
57032
  });
56986
57033
  dismissLoading = message$1.loading(t('backoffice.tools.aiPromptImageTester.generating'), 0);
56987
- _context12.prev = 36;
57034
+ _context12.prev = 37;
56988
57035
  ai = createGeminiClient(apiKey);
56989
- _context12.next = 40;
56990
- return buildContents(priorRecords, trimmed, uploadedImageIds);
56991
- case 40:
57036
+ _context12.next = 41;
57037
+ return buildContents({
57038
+ text: promptForModel,
57039
+ referenceImageIds: referenceImageIds
57040
+ });
57041
+ case 41:
56992
57042
  contents = _context12.sent;
56993
- _context12.next = 43;
57043
+ if (typeof console !== 'undefined') {
57044
+ console.debug('[AiPromptImageTester] gemini request', {
57045
+ model: conv.settings.model,
57046
+ conversationId: conv.id,
57047
+ mode: lastReadyModel ? 'follow-up (preserve+add)' : 'first turn',
57048
+ parts: (_contents$ = contents[0]) === null || _contents$ === void 0 || (_contents$ = _contents$.parts) === null || _contents$ === void 0 ? void 0 : _contents$.map(function (p) {
57049
+ return _objectSpread$3(_objectSpread$3({}, typeof p.text === 'string' ? {
57050
+ text: "len=".concat(p.text.length)
57051
+ } : {}), p.inlineData ? {
57052
+ image: p.inlineData.mimeType
57053
+ } : {});
57054
+ })
57055
+ });
57056
+ }
57057
+ _context12.next = 45;
56994
57058
  return generateImage(_objectSpread$3(_objectSpread$3({
56995
57059
  ai: ai,
56996
57060
  model: conv.settings.model,
@@ -57002,110 +57066,133 @@ function useAiChat(openFullscreen) {
57002
57066
  } : {}), {}, {
57003
57067
  signal: controller.signal
57004
57068
  }));
57005
- case 43:
57069
+ case 45:
57006
57070
  result = _context12.sent;
57007
57071
  if (!(result.images.length === 0)) {
57008
- _context12.next = 51;
57072
+ _context12.next = 53;
57009
57073
  break;
57010
57074
  }
57011
- _context12.next = 47;
57075
+ _context12.next = 49;
57012
57076
  return patchModelMessage(modelRecord.id, {
57013
57077
  status: 'error',
57014
57078
  errorMessage: t('backoffice.tools.aiPromptImageTester.noImage')
57015
57079
  });
57016
- case 47:
57017
- _context12.next = 49;
57018
- return refreshActiveMessages(conv.id);
57019
57080
  case 49:
57081
+ _context12.next = 51;
57082
+ return refreshActiveMessages(conv.id);
57083
+ case 51:
57020
57084
  message$1.warning(t('backoffice.tools.aiPromptImageTester.noImage'));
57021
57085
  return _context12.abrupt("return");
57022
- case 51:
57086
+ case 53:
57023
57087
  pricePerImage = priceForOutputImage(conv.settings.model, conv.settings.imageSize);
57024
- _context12.next = 54;
57025
- return Promise.all(result.images.map(function (g) {
57026
- return putImageBlob(generatedImageToBlob(g), g.mimeType, g.thoughtSignature, pricePerImage);
57027
- }));
57028
- case 54:
57029
- imageIds = _context12.sent;
57030
- if (pricePerImage > 0) addToTotalSpend(pricePerImage * result.images.length);
57088
+ imageIds = [];
57089
+ _iterator2 = _createForOfIteratorHelper(result.images);
57090
+ _context12.prev = 56;
57091
+ _iterator2.s();
57092
+ case 58:
57093
+ if ((_step2 = _iterator2.n()).done) {
57094
+ _context12.next = 66;
57095
+ break;
57096
+ }
57097
+ img = _step2.value;
57098
+ _context12.next = 62;
57099
+ return putImageBlob(generatedImageToBlob(img), img.mimeType, pricePerImage);
57100
+ case 62:
57101
+ id = _context12.sent;
57102
+ imageIds.push(id);
57103
+ case 64:
57031
57104
  _context12.next = 58;
57032
- return patchModelMessage(modelRecord.id, _objectSpread$3(_objectSpread$3({
57105
+ break;
57106
+ case 66:
57107
+ _context12.next = 71;
57108
+ break;
57109
+ case 68:
57110
+ _context12.prev = 68;
57111
+ _context12.t0 = _context12["catch"](56);
57112
+ _iterator2.e(_context12.t0);
57113
+ case 71:
57114
+ _context12.prev = 71;
57115
+ _iterator2.f();
57116
+ return _context12.finish(71);
57117
+ case 74:
57118
+ if (pricePerImage > 0) addToTotalSpend(pricePerImage * result.images.length);
57119
+ _context12.next = 77;
57120
+ return patchModelMessage(modelRecord.id, {
57033
57121
  status: 'ready',
57034
57122
  imageIds: imageIds
57035
- }, result.text ? {
57036
- responseText: result.text
57037
- } : {}), result.thoughtSignature ? {
57038
- responseThoughtSignature: result.thoughtSignature
57039
- } : {}));
57040
- case 58:
57041
- _context12.next = 60;
57123
+ });
57124
+ case 77:
57125
+ _context12.next = 79;
57042
57126
  return updateConversation(conv.id, {});
57043
- case 60:
57044
- _context12.next = 62;
57127
+ case 79:
57128
+ _context12.next = 81;
57045
57129
  return refreshActiveMessages(conv.id);
57046
- case 62:
57130
+ case 81:
57047
57131
  if (!(conv.title === 'New chat')) {
57048
- _context12.next = 68;
57132
+ _context12.next = 87;
57049
57133
  break;
57050
57134
  }
57051
57135
  title = trimmed.slice(0, 60);
57052
- _context12.next = 66;
57136
+ _context12.next = 85;
57053
57137
  return updateConversation(conv.id, {
57054
57138
  title: title
57055
57139
  });
57056
- case 66:
57140
+ case 85:
57057
57141
  updated = _context12.sent;
57058
57142
  if (updated) setConversations(function (prev) {
57059
57143
  return prev.map(function (c) {
57060
57144
  return c.id === updated.id ? updated : c;
57061
57145
  });
57062
57146
  });
57063
- case 68:
57147
+ case 87:
57148
+ // Auto-deselect every reference that was just sent. Its already in the chat history
57149
+
57150
+ setSelectedRefIds([]);
57064
57151
  message$1.success(t('backoffice.tools.aiPromptImageTester.generated'));
57065
- _context12.next = 84;
57152
+ _context12.next = 104;
57066
57153
  break;
57067
- case 71:
57068
- _context12.prev = 71;
57069
- _context12.t0 = _context12["catch"](36);
57154
+ case 91:
57155
+ _context12.prev = 91;
57156
+ _context12.t1 = _context12["catch"](37);
57070
57157
  if (!controller.signal.aborted) {
57071
- _context12.next = 78;
57158
+ _context12.next = 98;
57072
57159
  break;
57073
57160
  }
57074
- _context12.next = 76;
57161
+ _context12.next = 96;
57075
57162
  return patchModelMessage(modelRecord.id, {
57076
57163
  status: 'error',
57077
57164
  errorMessage: 'Cancelled'
57078
57165
  });
57079
- case 76:
57080
- _context12.next = 82;
57166
+ case 96:
57167
+ _context12.next = 102;
57081
57168
  break;
57082
- case 78:
57083
- msg = formatGeminiError(_context12.t0, t);
57084
- _context12.next = 81;
57169
+ case 98:
57170
+ msg = formatGeminiError(_context12.t1, t);
57171
+ _context12.next = 101;
57085
57172
  return patchModelMessage(modelRecord.id, {
57086
57173
  status: 'error',
57087
57174
  errorMessage: msg
57088
57175
  });
57089
- case 81:
57176
+ case 101:
57090
57177
  message$1.error(msg);
57091
- case 82:
57092
- _context12.next = 84;
57178
+ case 102:
57179
+ _context12.next = 104;
57093
57180
  return refreshActiveMessages(conv.id);
57094
- case 84:
57095
- _context12.prev = 84;
57181
+ case 104:
57182
+ _context12.prev = 104;
57096
57183
  pendingRequests.current["delete"](modelRecord.id);
57097
57184
  dismissLoading();
57098
- return _context12.finish(84);
57099
- case 88:
57185
+ return _context12.finish(104);
57186
+ case 108:
57100
57187
  case "end":
57101
57188
  return _context12.stop();
57102
57189
  }
57103
- }, _callee12, null, [[36, 71, 84, 88]]);
57190
+ }, _callee12, null, [[37, 91, 104, 108], [56, 68, 71, 74]]);
57104
57191
  }));
57105
57192
  return function (_x8) {
57106
57193
  return _ref12.apply(this, arguments);
57107
57194
  };
57108
- }(), [activeConversation, apiKey, refs, selectedRefIds, refreshActiveMessages, t]);
57195
+ }(), [activeConversation, apiKey, refs, selectedRefIds, refreshActiveMessages, preservePromptTemplate, t]);
57109
57196
  var abortMessage = useCallback(function (modelMessageId) {
57110
57197
  var entry = pendingRequests.current.get(modelMessageId);
57111
57198
  entry === null || entry === void 0 || entry.controller.abort();
@@ -57182,17 +57269,17 @@ function useAiChat(openFullscreen) {
57182
57269
  }(), [activeConversationId, messages, refreshActiveMessages]);
57183
57270
  var openImageFullscreen = useCallback(function (initialReadyIndex) {
57184
57271
  var slides = [];
57185
- var _iterator2 = _createForOfIteratorHelper(messages),
57186
- _step2;
57272
+ var _iterator3 = _createForOfIteratorHelper(messages),
57273
+ _step3;
57187
57274
  try {
57188
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
57189
- var m = _step2.value;
57275
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
57276
+ var m = _step3.value;
57190
57277
  if (m.kind !== 'model' || m.status !== 'ready') continue;
57191
- var _iterator3 = _createForOfIteratorHelper(m.imageUrls),
57192
- _step3;
57278
+ var _iterator4 = _createForOfIteratorHelper(m.imageUrls),
57279
+ _step4;
57193
57280
  try {
57194
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
57195
- var url = _step3.value;
57281
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
57282
+ var url = _step4.value;
57196
57283
  slides.push({
57197
57284
  imageUrl: url,
57198
57285
  promptText: m.promptText,
@@ -57203,15 +57290,15 @@ function useAiChat(openFullscreen) {
57203
57290
  });
57204
57291
  }
57205
57292
  } catch (err) {
57206
- _iterator3.e(err);
57293
+ _iterator4.e(err);
57207
57294
  } finally {
57208
- _iterator3.f();
57295
+ _iterator4.f();
57209
57296
  }
57210
57297
  }
57211
57298
  } catch (err) {
57212
- _iterator2.e(err);
57299
+ _iterator3.e(err);
57213
57300
  } finally {
57214
- _iterator2.f();
57301
+ _iterator3.f();
57215
57302
  }
57216
57303
  if (slides.length === 0) return;
57217
57304
  var idx = Math.min(Math.max(0, initialReadyIndex), slides.length - 1);
@@ -57225,7 +57312,6 @@ function useAiChat(openFullscreen) {
57225
57312
  });
57226
57313
  }, [messages, openFullscreen]);
57227
57314
  return {
57228
- bootstrapped: bootstrapped,
57229
57315
  conversations: conversations,
57230
57316
  activeConversation: activeConversation,
57231
57317
  activeConversationId: activeConversationId,
@@ -57235,6 +57321,7 @@ function useAiChat(openFullscreen) {
57235
57321
  deleteConversation: deleteConversation$1,
57236
57322
  updateActiveSettings: updateActiveSettings,
57237
57323
  messages: messages,
57324
+ isFollowUp: isFollowUp,
57238
57325
  sendMessage: sendMessage,
57239
57326
  abortMessage: abortMessage,
57240
57327
  retryMessage: retryMessage,
@@ -57245,7 +57332,6 @@ function useAiChat(openFullscreen) {
57245
57332
  selectedRefIds: selectedRefIds,
57246
57333
  toggleRefSelection: toggleRefSelection,
57247
57334
  clearRefSelection: clearRefSelection,
57248
- selectAllRefs: selectAllRefs,
57249
57335
  onReferenceUpload: onReferenceUpload,
57250
57336
  removeReference: removeReference,
57251
57337
  apiKey: apiKey,
@@ -57258,7 +57344,11 @@ function useAiChat(openFullscreen) {
57258
57344
  }, []),
57259
57345
  closeApiKeyModal: useCallback(function () {
57260
57346
  return setApiKeyModalOpen(false);
57261
- }, [])
57347
+ }, []),
57348
+ preservePromptTemplate: preservePromptTemplate,
57349
+ preservePromptIsCustom: preservePromptIsCustom,
57350
+ setPreservePromptTemplate: setPreservePromptTemplate,
57351
+ resetPreservePromptTemplate: resetPreservePromptTemplate
57262
57352
  };
57263
57353
  }
57264
57354
  function toMessageView(_x11) {
@@ -57375,6 +57465,7 @@ var AiPromptImageTester = observer(function (_ref) {
57375
57465
  deleteConversation = _useAiChat.deleteConversation,
57376
57466
  updateActiveSettings = _useAiChat.updateActiveSettings,
57377
57467
  messages = _useAiChat.messages,
57468
+ isFollowUp = _useAiChat.isFollowUp,
57378
57469
  sendMessage = _useAiChat.sendMessage,
57379
57470
  abortMessage = _useAiChat.abortMessage,
57380
57471
  retryMessage = _useAiChat.retryMessage,
@@ -57393,7 +57484,11 @@ var AiPromptImageTester = observer(function (_ref) {
57393
57484
  clearApiKey = _useAiChat.clearApiKey,
57394
57485
  apiKeyModalOpen = _useAiChat.apiKeyModalOpen,
57395
57486
  openApiKeyModal = _useAiChat.openApiKeyModal,
57396
- closeApiKeyModal = _useAiChat.closeApiKeyModal;
57487
+ closeApiKeyModal = _useAiChat.closeApiKeyModal,
57488
+ preservePromptTemplate = _useAiChat.preservePromptTemplate,
57489
+ preservePromptIsCustom = _useAiChat.preservePromptIsCustom,
57490
+ setPreservePromptTemplate = _useAiChat.setPreservePromptTemplate,
57491
+ resetPreservePromptTemplate = _useAiChat.resetPreservePromptTemplate;
57397
57492
  var lastModel = _toConsumableArray(messages).reverse().find(function (m) {
57398
57493
  return m.kind === 'model';
57399
57494
  });
@@ -57451,11 +57546,16 @@ var AiPromptImageTester = observer(function (_ref) {
57451
57546
  return void removeReference(id);
57452
57547
  },
57453
57548
  pending: pending,
57549
+ isFollowUp: isFollowUp,
57454
57550
  onSend: function onSend(text) {
57455
57551
  return void sendMessage(text);
57456
57552
  },
57457
57553
  hasApiKey: hasKey,
57458
- onRequestApiKey: openApiKeyModal
57554
+ onRequestApiKey: openApiKeyModal,
57555
+ preservePromptTemplate: preservePromptTemplate,
57556
+ preservePromptIsCustom: preservePromptIsCustom,
57557
+ onPreservePromptTemplateChange: setPreservePromptTemplate,
57558
+ onResetPreservePromptTemplate: resetPreservePromptTemplate
57459
57559
  }) : null]
57460
57560
  })]
57461
57561
  })