@crystaldesign/diva-backoffice 26.5.0-beta.33 → 26.5.0-beta.35

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 (23) hide show
  1. package/build/esm/index.js +453 -348
  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/build/types/backoffice/src/ui/IDMEnricherEditor/modules/TablePackages/PublishCustomCell.d.ts.map +1 -1
  23. package/package.json +9 -9
@@ -34866,14 +34866,14 @@ function PublishCustomCell (_ref) {
34866
34866
  var unpublishedChanges = hasUnpublishedChanges(publishedData === null || publishedData === void 0 ? void 0 : publishedData.publishDate, data === null || data === void 0 ? void 0 : data.lastUpdatedDate);
34867
34867
  var disabled = isPublishing || !(data !== null && data !== void 0 && data.basedCatalogId) && !(data !== null && data !== void 0 && data.basedPackageId) || !(data !== null && data !== void 0 && data.name);
34868
34868
  var fetchOrganizationsWithAutomaticPublishing = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
34869
- var url, response, result, allowedOrgIds, currentOrg, currentOrgParentIds, filtered, allOrgIds;
34869
+ var url, response, result, allowedOrgIds, currentOrg, currentOrgParentIds, isOwner, filtered, allOrgIds;
34870
34870
  return _regeneratorRuntime.wrap(function _callee$(_context) {
34871
34871
  while (1) switch (_context.prev = _context.next) {
34872
34872
  case 0:
34873
34873
  setLoadingOrganizations(true);
34874
34874
  _context.prev = 1;
34875
34875
  // Request organizations with automaticPublishing field from their settings
34876
- url = apiConfig.authService + "/organizations/".concat(organizationId, "/related");
34876
+ url = apiConfig.authService + "/organizations/".concat(organizationId, "/related?limit=1000");
34877
34877
  _context.next = 5;
34878
34878
  return fetch(url, {
34879
34879
  headers: {
@@ -34898,7 +34898,8 @@ function PublishCustomCell (_ref) {
34898
34898
  currentOrg = (result.data || []).find(function (o) {
34899
34899
  return o._id === organizationId;
34900
34900
  });
34901
- currentOrgParentIds = (currentOrg === null || currentOrg === void 0 ? void 0 : currentOrg.parentOrganizations) || []; // Show organizations that are:
34901
+ currentOrgParentIds = (currentOrg === null || currentOrg === void 0 ? void 0 : currentOrg.parentOrganizations) || [];
34902
+ isOwner = data.organizationId === organizationId; // Show organizations that are:
34902
34903
  // 1. In package settings with AutomaticPublishing === true, OR
34903
34904
  // 2. Has access to the package AND have automaticPublishing === true in their own organization settings
34904
34905
  filtered = (result.data || []).filter(function (org) {
@@ -34907,18 +34908,22 @@ function PublishCustomCell (_ref) {
34907
34908
  if (org._id === organizationId) {
34908
34909
  return false;
34909
34910
  }
34910
- // EXCLUDE parents of the current organization
34911
- if (currentOrgParentIds.includes(org._id)) {
34912
- return false;
34913
- }
34914
- // EXCLUDE siblings and their children
34915
34911
  var orgParentIds = org.parentOrganizations || [];
34916
- var isChild = orgParentIds.includes(organizationId);
34917
- var isOfSiblingBranch = !isChild && currentOrgParentIds.some(function (parentId) {
34918
- return orgParentIds.includes(parentId);
34919
- });
34920
- if (isOfSiblingBranch) {
34921
- return false;
34912
+
34913
+ //if only shared with this organization, we only show the subtree of this organization for automatic publishing
34914
+ if (!isOwner) {
34915
+ // EXCLUDE parents of the current organization
34916
+ if (currentOrgParentIds.includes(org._id)) {
34917
+ return false;
34918
+ }
34919
+ // EXCLUDE siblings and their children
34920
+ var isChild = orgParentIds.includes(organizationId);
34921
+ var isOfSiblingBranch = !isChild && currentOrgParentIds.some(function (parentId) {
34922
+ return orgParentIds.includes(parentId);
34923
+ });
34924
+ if (isOfSiblingBranch) {
34925
+ return false;
34926
+ }
34922
34927
  }
34923
34928
  var hasAutomaticPublishingForPackage = ((_data$settings = data.settings) === null || _data$settings === void 0 || (_data$settings = _data$settings[org._id]) === null || _data$settings === void 0 ? void 0 : _data$settings.automaticPublishing) === true;
34924
34929
  var hasAccessToPackage = orgParentIds.includes(data.organizationId) || allowedOrgIds.includes(org._id) || allowedOrgIds.some(function (id) {
@@ -34935,21 +34940,21 @@ function PublishCustomCell (_ref) {
34935
34940
  });
34936
34941
  setSelectedOrganizationIds(allOrgIds);
34937
34942
  return _context.abrupt("return", filtered);
34938
- case 21:
34939
- _context.prev = 21;
34943
+ case 22:
34944
+ _context.prev = 22;
34940
34945
  _context.t0 = _context["catch"](1);
34941
34946
  modalState.showErrorModal("Error fetching organizations: ".concat(_context.t0 instanceof Error ? _context.t0.message : String(_context.t0)));
34942
34947
  setAvailableOrganizations([]);
34943
34948
  return _context.abrupt("return", []);
34944
- case 26:
34945
- _context.prev = 26;
34949
+ case 27:
34950
+ _context.prev = 27;
34946
34951
  setLoadingOrganizations(false);
34947
- return _context.finish(26);
34948
- case 29:
34952
+ return _context.finish(27);
34953
+ case 30:
34949
34954
  case "end":
34950
34955
  return _context.stop();
34951
34956
  }
34952
- }, _callee, null, [[1, 21, 26, 29]]);
34957
+ }, _callee, null, [[1, 22, 27, 30]]);
34953
34958
  })), [apiConfig.authService, organizationId, root.dataStore.jwt, modalState, data.allowedOrganizationIds, data.settings]);
34954
34959
  var performPublish = React.useCallback(/*#__PURE__*/function () {
34955
34960
  var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(publish) {
@@ -53759,25 +53764,23 @@ function _unsupportedIterableToArray$6(r, a) { if (r) { if ("string" == typeof r
53759
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; }
53760
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; }
53761
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; }
53762
- function putImageBlob(_x, _x2, _x3, _x4) {
53767
+ function putImageBlob(_x, _x2, _x3) {
53763
53768
  return _putImageBlob.apply(this, arguments);
53764
53769
  }
53765
53770
  function _putImageBlob() {
53766
- _putImageBlob = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(blob, mime, thoughtSignature, costUsd) {
53771
+ _putImageBlob = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(blob, mime, costUsd) {
53767
53772
  var _ref;
53768
53773
  var id, record;
53769
53774
  return _regeneratorRuntime.wrap(function _callee$(_context) {
53770
53775
  while (1) switch (_context.prev = _context.next) {
53771
53776
  case 0:
53772
53777
  id = newId('img');
53773
- record = _objectSpread$9(_objectSpread$9({
53778
+ record = _objectSpread$9({
53774
53779
  id: id,
53775
53780
  blob: blob,
53776
53781
  mime: (_ref = mime !== null && mime !== void 0 ? mime : blob.type) !== null && _ref !== void 0 ? _ref : 'image/png',
53777
53782
  createdAt: Date.now()
53778
- }, thoughtSignature ? {
53779
- thoughtSignature: thoughtSignature
53780
- } : {}), typeof costUsd === 'number' && costUsd > 0 ? {
53783
+ }, typeof costUsd === 'number' && costUsd > 0 ? {
53781
53784
  costUsd: costUsd
53782
53785
  } : {});
53783
53786
  _context.next = 4;
@@ -53794,7 +53797,7 @@ function _putImageBlob() {
53794
53797
  }));
53795
53798
  return _putImageBlob.apply(this, arguments);
53796
53799
  }
53797
- function getImage(_x5) {
53800
+ function getImage(_x4) {
53798
53801
  return _getImage.apply(this, arguments);
53799
53802
  }
53800
53803
  function _getImage() {
@@ -53813,7 +53816,7 @@ function _getImage() {
53813
53816
  }));
53814
53817
  return _getImage.apply(this, arguments);
53815
53818
  }
53816
- function deleteImages(_x6) {
53819
+ function deleteImages(_x5) {
53817
53820
  return _deleteImages.apply(this, arguments);
53818
53821
  }
53819
53822
 
@@ -53948,103 +53951,103 @@ function _createConversation() {
53948
53951
  }));
53949
53952
  return _createConversation.apply(this, arguments);
53950
53953
  }
53951
- function listConversations(_x4) {
53954
+ function listConversations(_x2) {
53952
53955
  return _listConversations.apply(this, arguments);
53953
53956
  }
53954
53957
  function _listConversations() {
53955
- _listConversations = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(fallbackModel) {
53958
+ _listConversations = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(fallbackModel) {
53956
53959
  var all;
53957
- return _regeneratorRuntime.wrap(function _callee3$(_context3) {
53958
- while (1) switch (_context3.prev = _context3.next) {
53960
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
53961
+ while (1) switch (_context2.prev = _context2.next) {
53959
53962
  case 0:
53960
- _context3.next = 2;
53963
+ _context2.next = 2;
53961
53964
  return withTx(STORE_CONVERSATIONS, 'readonly', function (tx) {
53962
53965
  return reqAsPromise(tx.objectStore(STORE_CONVERSATIONS).getAll());
53963
53966
  });
53964
53967
  case 2:
53965
- all = _context3.sent;
53966
- return _context3.abrupt("return", all.map(function (r) {
53968
+ all = _context2.sent;
53969
+ return _context2.abrupt("return", all.map(function (r) {
53967
53970
  return coerceRecord(r, fallbackModel);
53968
53971
  }).sort(function (a, b) {
53969
53972
  return b.updatedAt - a.updatedAt;
53970
53973
  }));
53971
53974
  case 4:
53972
53975
  case "end":
53973
- return _context3.stop();
53976
+ return _context2.stop();
53974
53977
  }
53975
- }, _callee3);
53978
+ }, _callee2);
53976
53979
  }));
53977
53980
  return _listConversations.apply(this, arguments);
53978
53981
  }
53979
- function updateConversation(_x5, _x6) {
53982
+ function updateConversation(_x3, _x4) {
53980
53983
  return _updateConversation.apply(this, arguments);
53981
53984
  }
53982
53985
  function _updateConversation() {
53983
- _updateConversation = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(id, patch) {
53984
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
53985
- 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) {
53986
53989
  case 0:
53987
- return _context5.abrupt("return", withTx(STORE_CONVERSATIONS, 'readwrite', /*#__PURE__*/function () {
53988
- 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) {
53989
53992
  var _patch$settings;
53990
53993
  var store, existing, next;
53991
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
53992
- while (1) switch (_context4.prev = _context4.next) {
53994
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
53995
+ while (1) switch (_context3.prev = _context3.next) {
53993
53996
  case 0:
53994
53997
  store = tx.objectStore(STORE_CONVERSATIONS);
53995
- _context4.next = 3;
53998
+ _context3.next = 3;
53996
53999
  return reqAsPromise(store.get(id));
53997
54000
  case 3:
53998
- existing = _context4.sent;
54001
+ existing = _context3.sent;
53999
54002
  if (existing) {
54000
- _context4.next = 6;
54003
+ _context3.next = 6;
54001
54004
  break;
54002
54005
  }
54003
- return _context4.abrupt("return", undefined);
54006
+ return _context3.abrupt("return", undefined);
54004
54007
  case 6:
54005
54008
  next = _objectSpread$8(_objectSpread$8(_objectSpread$8({}, existing), patch), {}, {
54006
54009
  settings: (_patch$settings = patch.settings) !== null && _patch$settings !== void 0 ? _patch$settings : existing.settings,
54007
54010
  updatedAt: Date.now()
54008
54011
  });
54009
- _context4.next = 9;
54012
+ _context3.next = 9;
54010
54013
  return reqAsPromise(store.put(next));
54011
54014
  case 9:
54012
- return _context4.abrupt("return", next);
54015
+ return _context3.abrupt("return", next);
54013
54016
  case 10:
54014
54017
  case "end":
54015
- return _context4.stop();
54018
+ return _context3.stop();
54016
54019
  }
54017
- }, _callee4);
54020
+ }, _callee3);
54018
54021
  }));
54019
- return function (_x8) {
54022
+ return function (_x6) {
54020
54023
  return _ref.apply(this, arguments);
54021
54024
  };
54022
54025
  }()));
54023
54026
  case 1:
54024
54027
  case "end":
54025
- return _context5.stop();
54028
+ return _context4.stop();
54026
54029
  }
54027
- }, _callee5);
54030
+ }, _callee4);
54028
54031
  }));
54029
54032
  return _updateConversation.apply(this, arguments);
54030
54033
  }
54031
- function deleteConversation(_x7) {
54034
+ function deleteConversation(_x5) {
54032
54035
  return _deleteConversation.apply(this, arguments);
54033
54036
  }
54034
54037
  function _deleteConversation() {
54035
- _deleteConversation = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6(id) {
54036
- return _regeneratorRuntime.wrap(function _callee6$(_context6) {
54037
- 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) {
54038
54041
  case 0:
54039
- _context6.next = 2;
54042
+ _context5.next = 2;
54040
54043
  return withTx(STORE_CONVERSATIONS, 'readwrite', function (tx) {
54041
54044
  return reqAsPromise(tx.objectStore(STORE_CONVERSATIONS)["delete"](id));
54042
54045
  });
54043
54046
  case 2:
54044
54047
  case "end":
54045
- return _context6.stop();
54048
+ return _context5.stop();
54046
54049
  }
54047
- }, _callee6);
54050
+ }, _callee5);
54048
54051
  }));
54049
54052
  return _deleteConversation.apply(this, arguments);
54050
54053
  }
@@ -54059,10 +54062,12 @@ function listMessages(_x) {
54059
54062
  }
54060
54063
  function _listMessages() {
54061
54064
  _listMessages = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(conversationId) {
54065
+ var records;
54062
54066
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
54063
54067
  while (1) switch (_context2.prev = _context2.next) {
54064
54068
  case 0:
54065
- return _context2.abrupt("return", withTx(STORE_MESSAGES, 'readonly', /*#__PURE__*/function () {
54069
+ _context2.next = 2;
54070
+ return withTx(STORE_MESSAGES, 'readonly', /*#__PURE__*/function () {
54066
54071
  var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(tx) {
54067
54072
  var index, range;
54068
54073
  return _regeneratorRuntime.wrap(function _callee$(_context) {
@@ -54080,8 +54085,15 @@ function _listMessages() {
54080
54085
  return function (_x8) {
54081
54086
  return _ref.apply(this, arguments);
54082
54087
  };
54083
- }()));
54084
- 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:
54085
54097
  case "end":
54086
54098
  return _context2.stop();
54087
54099
  }
@@ -54131,7 +54143,7 @@ function _putModelMessage() {
54131
54143
  return _regeneratorRuntime.wrap(function _callee4$(_context4) {
54132
54144
  while (1) switch (_context4.prev = _context4.next) {
54133
54145
  case 0:
54134
- record = _objectSpread$7(_objectSpread$7(_objectSpread$7({
54146
+ record = _objectSpread$7({
54135
54147
  kind: 'model',
54136
54148
  id: (_input$id2 = input.id) !== null && _input$id2 !== void 0 ? _input$id2 : newId('msg'),
54137
54149
  conversationId: input.conversationId,
@@ -54142,11 +54154,7 @@ function _putModelMessage() {
54142
54154
  promptText: input.promptText,
54143
54155
  resolutionCaption: input.resolutionCaption,
54144
54156
  temperatureCaption: input.temperatureCaption
54145
- }, input.responseText ? {
54146
- responseText: input.responseText
54147
- } : {}), input.responseThoughtSignature ? {
54148
- responseThoughtSignature: input.responseThoughtSignature
54149
- } : {}), input.errorMessage ? {
54157
+ }, input.errorMessage ? {
54150
54158
  errorMessage: input.errorMessage
54151
54159
  } : {});
54152
54160
  _context4.next = 3;
@@ -54569,8 +54577,6 @@ function _createForOfIteratorHelper$2(r, e) { var t = "undefined" != typeof Symb
54569
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; } }
54570
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; }
54571
54579
 
54572
- /** Per-record blob payload pre-resolved by the caller, keyed by `imageId`. */
54573
-
54574
54580
  /** Aspect ratios supported by Gemini image-capable models (per Google docs). */
54575
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'];
54576
54582
 
@@ -54605,9 +54611,20 @@ function optionsForModel(model) {
54605
54611
  }
54606
54612
 
54607
54613
  /**
54608
- * Resolve image bytes for an array of `imageId`s into the `inlineData` shape Gemini expects.
54609
- * 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.
54610
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
+ }
54611
54628
  function imageIdsToParts(_x) {
54612
54629
  return _imageIdsToParts.apply(this, arguments);
54613
54630
  }
@@ -54671,20 +54688,13 @@ function imageRecordToPart(_x2) {
54671
54688
  return _imageRecordToPart.apply(this, arguments);
54672
54689
  }
54673
54690
  /**
54674
- * Convert persisted user/model records into the `Content[]` the SDK accepts.
54691
+ * Build the single-turn `Content[]` payload for `models.generateContent`.
54675
54692
  *
54676
- * - User turn: `text` part (if any) followed by attached reference images.
54677
- * - Model turn: the text the model returned (if any, carrying its thought signature)
54678
- * followed by every generated image part (each with its own signature). Both the
54679
- * text and the images are essential for follow-up prompts like "make it bigger";
54680
- * without the model's own narration the model loses awareness of what it did.
54681
- *
54682
- * The current pending model record (no images yet) is skipped — this builds
54683
- * only completed history, the caller appends the new user prompt separately.
54693
+ * The `text` should already be wrapped with `wrapPreservePrompt` for follow-ups.
54684
54694
  */
54685
54695
  function _imageRecordToPart() {
54686
54696
  _imageRecordToPart = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(rec) {
54687
- var dataUrl, base64, part;
54697
+ var dataUrl, base64;
54688
54698
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
54689
54699
  while (1) switch (_context2.prev = _context2.next) {
54690
54700
  case 0:
@@ -54693,15 +54703,13 @@ function _imageRecordToPart() {
54693
54703
  case 2:
54694
54704
  dataUrl = _context2.sent;
54695
54705
  base64 = dataUrl.includes(',') ? dataUrl.slice(dataUrl.indexOf(',') + 1) : '';
54696
- part = {
54706
+ return _context2.abrupt("return", {
54697
54707
  inlineData: {
54698
54708
  data: base64,
54699
54709
  mimeType: rec.mime
54700
54710
  }
54701
- };
54702
- if (rec.thoughtSignature) part.thoughtSignature = rec.thoughtSignature;
54703
- return _context2.abrupt("return", part);
54704
- case 7:
54711
+ });
54712
+ case 5:
54705
54713
  case "end":
54706
54714
  return _context2.stop();
54707
54715
  }
@@ -54709,149 +54717,52 @@ function _imageRecordToPart() {
54709
54717
  }));
54710
54718
  return _imageRecordToPart.apply(this, arguments);
54711
54719
  }
54712
- function buildContents(_x3, _x4, _x5) {
54720
+ function buildContents(_x3) {
54713
54721
  return _buildContents.apply(this, arguments);
54714
54722
  }
54715
54723
  function _buildContents() {
54716
- _buildContents = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(records, currentText, currentRefImageIds) {
54717
- var out, _iterator2, _step2, r, parts, _parts, currentParts;
54724
+ _buildContents = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(opts) {
54725
+ var parts;
54718
54726
  return _regeneratorRuntime.wrap(function _callee3$(_context3) {
54719
54727
  while (1) switch (_context3.prev = _context3.next) {
54720
54728
  case 0:
54721
- out = [];
54722
- _iterator2 = _createForOfIteratorHelper$2(records);
54723
- _context3.prev = 2;
54724
- _iterator2.s();
54725
- case 4:
54726
- if ((_step2 = _iterator2.n()).done) {
54727
- _context3.next = 27;
54728
- break;
54729
- }
54730
- r = _step2.value;
54731
- if (!(r.kind === 'user')) {
54732
- _context3.next = 20;
54733
- break;
54734
- }
54735
54729
  parts = [];
54736
- if (r.text) parts.push({
54737
- text: r.text
54730
+ if (opts.text) parts.push({
54731
+ text: opts.text
54738
54732
  });
54739
54733
  _context3.t0 = parts.push;
54740
54734
  _context3.t1 = parts;
54741
54735
  _context3.t2 = _toConsumableArray;
54742
- _context3.next = 14;
54743
- return imageIdsToParts(r.uploadedImageIds);
54744
- case 14:
54736
+ _context3.next = 7;
54737
+ return imageIdsToParts(opts.referenceImageIds);
54738
+ case 7:
54745
54739
  _context3.t3 = _context3.sent;
54746
54740
  _context3.t4 = (0, _context3.t2)(_context3.t3);
54747
54741
  _context3.t0.apply.call(_context3.t0, _context3.t1, _context3.t4);
54748
- if (parts.length > 0) out.push({
54742
+ return _context3.abrupt("return", parts.length > 0 ? [{
54749
54743
  role: 'user',
54750
54744
  parts: parts
54751
- });
54752
- _context3.next = 25;
54753
- break;
54754
- case 20:
54755
- if (!(r.kind === 'model' && r.status === 'ready')) {
54756
- _context3.next = 25;
54757
- break;
54758
- }
54759
- _context3.next = 23;
54760
- return buildModelTurnParts(r);
54761
- case 23:
54762
- _parts = _context3.sent;
54763
- if (_parts.length > 0) out.push({
54764
- role: 'model',
54765
- parts: _parts
54766
- });
54767
- case 25:
54768
- _context3.next = 4;
54769
- break;
54770
- case 27:
54771
- _context3.next = 32;
54772
- break;
54773
- case 29:
54774
- _context3.prev = 29;
54775
- _context3.t5 = _context3["catch"](2);
54776
- _iterator2.e(_context3.t5);
54777
- case 32:
54778
- _context3.prev = 32;
54779
- _iterator2.f();
54780
- return _context3.finish(32);
54781
- case 35:
54782
- currentParts = [];
54783
- if (currentText) currentParts.push({
54784
- text: currentText
54785
- });
54786
- _context3.t6 = currentParts.push;
54787
- _context3.t7 = currentParts;
54788
- _context3.t8 = _toConsumableArray;
54789
- _context3.next = 42;
54790
- return imageIdsToParts(currentRefImageIds);
54791
- case 42:
54792
- _context3.t9 = _context3.sent;
54793
- _context3.t10 = (0, _context3.t8)(_context3.t9);
54794
- _context3.t6.apply.call(_context3.t6, _context3.t7, _context3.t10);
54795
- if (currentParts.length > 0) out.push({
54796
- role: 'user',
54797
- parts: currentParts
54798
- });
54799
- return _context3.abrupt("return", out);
54800
- case 47:
54745
+ }] : []);
54746
+ case 11:
54801
54747
  case "end":
54802
54748
  return _context3.stop();
54803
54749
  }
54804
- }, _callee3, null, [[2, 29, 32, 35]]);
54750
+ }, _callee3);
54805
54751
  }));
54806
54752
  return _buildContents.apply(this, arguments);
54807
54753
  }
54808
- function buildModelTurnParts(_x6) {
54809
- return _buildModelTurnParts.apply(this, arguments);
54810
- }
54811
- function _buildModelTurnParts() {
54812
- _buildModelTurnParts = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(r) {
54813
- var parts, _r$responseText, textPart;
54814
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
54815
- while (1) switch (_context4.prev = _context4.next) {
54816
- case 0:
54817
- parts = [];
54818
- if (r.responseText || r.responseThoughtSignature) {
54819
- textPart = {
54820
- text: (_r$responseText = r.responseText) !== null && _r$responseText !== void 0 ? _r$responseText : ''
54821
- };
54822
- if (r.responseThoughtSignature) textPart.thoughtSignature = r.responseThoughtSignature;
54823
- parts.push(textPart);
54824
- }
54825
- _context4.t0 = parts.push;
54826
- _context4.t1 = parts;
54827
- _context4.t2 = _toConsumableArray;
54828
- _context4.next = 7;
54829
- return imageIdsToParts(r.imageIds);
54830
- case 7:
54831
- _context4.t3 = _context4.sent;
54832
- _context4.t4 = (0, _context4.t2)(_context4.t3);
54833
- _context4.t0.apply.call(_context4.t0, _context4.t1, _context4.t4);
54834
- return _context4.abrupt("return", parts);
54835
- case 11:
54836
- case "end":
54837
- return _context4.stop();
54838
- }
54839
- }, _callee4);
54840
- }));
54841
- return _buildModelTurnParts.apply(this, arguments);
54842
- }
54843
54754
  /** Call `models.generateContent` and pluck the inline image parts from the response. */
54844
- function generateImage(_x7) {
54755
+ function generateImage(_x4) {
54845
54756
  return _generateImage.apply(this, arguments);
54846
54757
  }
54847
54758
 
54848
54759
  /** Convert a `GeneratedImage` into a `Blob` ready for IndexedDB. */
54849
54760
  function _generateImage() {
54850
- _generateImage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5(opts) {
54761
+ _generateImage = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(opts) {
54851
54762
  var _response$candidates, _candidate$content$pa, _candidate$content;
54852
- 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;
54853
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
54854
- 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) {
54855
54766
  case 0:
54856
54767
  ai = opts.ai, model = opts.model, contents = opts.contents, aspectRatio = opts.aspectRatio, imageSize = opts.imageSize, temperature = opts.temperature, signal = opts.signal;
54857
54768
  config = {};
@@ -54861,7 +54772,7 @@ function _generateImage() {
54861
54772
  if (Object.keys(imageConfig).length > 0) config.imageConfig = imageConfig;
54862
54773
  if (typeof temperature === 'number' && Number.isFinite(temperature)) config.temperature = temperature;
54863
54774
  if (signal) config.abortSignal = signal;
54864
- _context5.next = 10;
54775
+ _context4.next = 10;
54865
54776
  return ai.models.generateContent(_objectSpread$5({
54866
54777
  model: model,
54867
54778
  contents: contents
@@ -54869,45 +54780,39 @@ function _generateImage() {
54869
54780
  config: config
54870
54781
  } : {}));
54871
54782
  case 10:
54872
- response = _context5.sent;
54783
+ response = _context4.sent;
54873
54784
  images = [];
54874
54785
  text = '';
54875
54786
  candidate = (_response$candidates = response.candidates) === null || _response$candidates === void 0 ? void 0 : _response$candidates[0];
54876
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 : [];
54877
- _iterator3 = _createForOfIteratorHelper$2(parts);
54788
+ _iterator2 = _createForOfIteratorHelper$2(parts);
54878
54789
  try {
54879
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
54880
- p = _step3.value;
54790
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
54791
+ p = _step2.value;
54881
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/')) {
54882
- img = {
54793
+ images.push({
54883
54794
  mimeType: p.inlineData.mimeType,
54884
54795
  base64: p.inlineData.data
54885
- };
54886
- if (p.thoughtSignature) img.thoughtSignature = p.thoughtSignature;
54887
- images.push(img);
54888
- } else if (typeof p.text === 'string') {
54889
- // Visible text contributes to `text`; pure `thought` parts only contribute their
54890
- // signature. Either way, capture the FIRST signature so the next turn can replay it.
54891
- if (!p.thought) text += p.text;
54892
- if (!textThoughtSignature && p.thoughtSignature) textThoughtSignature = p.thoughtSignature;
54796
+ });
54797
+ } else if (typeof p.text === 'string' && !p.thought) {
54798
+ text += p.text;
54893
54799
  }
54894
54800
  }
54895
54801
  } catch (err) {
54896
- _iterator3.e(err);
54802
+ _iterator2.e(err);
54897
54803
  } finally {
54898
- _iterator3.f();
54804
+ _iterator2.f();
54899
54805
  }
54900
54806
  result = {
54901
54807
  images: images
54902
54808
  };
54903
54809
  if (text) result.text = text;
54904
- if (textThoughtSignature) result.thoughtSignature = textThoughtSignature;
54905
- return _context5.abrupt("return", result);
54906
- case 21:
54810
+ return _context4.abrupt("return", result);
54811
+ case 20:
54907
54812
  case "end":
54908
- return _context5.stop();
54813
+ return _context4.stop();
54909
54814
  }
54910
- }, _callee5);
54815
+ }, _callee4);
54911
54816
  }));
54912
54817
  return _generateImage.apply(this, arguments);
54913
54818
  }
@@ -54964,6 +54869,7 @@ var apiKeyEmptyDescription = "apiKeyEmptyDescription--gLYv";
54964
54869
  var messageImg = "messageImg-i3Rcg";
54965
54870
  var composer = "composer-dJW7x";
54966
54871
  var composerRefRow = "composerRefRow-XCqFN";
54872
+ var composerFollowUpHint = "composerFollowUpHint-6VH61";
54967
54873
  var composerTextareaRow = "composerTextareaRow-1pKrk";
54968
54874
  var composerToolbarRow = "composerToolbarRow-c05wd";
54969
54875
  var composerSpacer = "composerSpacer-kQKVK";
@@ -54976,7 +54882,7 @@ var refThumbSelected = "refThumbSelected-UnCbx";
54976
54882
  var refThumbRemove = "refThumbRemove-HlsBp";
54977
54883
  var refOrderBadge = "refOrderBadge-r-h2t";
54978
54884
  var fullscreenGallerySwiper = "fullscreenGallerySwiper-y-BWH";
54979
- 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";
54980
54886
  styleInject(css_248z);
54981
54887
 
54982
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; }
@@ -54992,9 +54898,14 @@ function ChatComposer(_ref) {
54992
54898
  onReferenceUpload = _ref.onReferenceUpload,
54993
54899
  onRemoveReference = _ref.onRemoveReference,
54994
54900
  pending = _ref.pending,
54901
+ isFollowUp = _ref.isFollowUp,
54995
54902
  onSend = _ref.onSend,
54996
54903
  hasApiKey = _ref.hasApiKey,
54997
- onRequestApiKey = _ref.onRequestApiKey;
54904
+ onRequestApiKey = _ref.onRequestApiKey,
54905
+ preservePromptTemplate = _ref.preservePromptTemplate,
54906
+ preservePromptIsCustom = _ref.preservePromptIsCustom,
54907
+ onPreservePromptTemplateChange = _ref.onPreservePromptTemplateChange,
54908
+ onResetPreservePromptTemplate = _ref.onResetPreservePromptTemplate;
54998
54909
  var _useTranslation = useTranslation(),
54999
54910
  t = _useTranslation.t;
55000
54911
  var models = promptAndAiTesterOptions.aiImageTester.models;
@@ -55152,11 +55063,73 @@ function ChatComposer(_ref) {
55152
55063
  })
55153
55064
  }) : null]
55154
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
+ })]
55155
55115
  })]
55156
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;
55157
55127
  return /*#__PURE__*/jsxs("div", {
55158
55128
  className: composer,
55159
- 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", {
55160
55133
  className: composerRefRow,
55161
55134
  children: [/*#__PURE__*/jsx("div", {
55162
55135
  className: refThumbRow,
@@ -55220,9 +55193,7 @@ function ChatComposer(_ref) {
55220
55193
  return setText(e.target.value);
55221
55194
  },
55222
55195
  onKeyDown: onKeyDown,
55223
- placeholder: t('backoffice.tools.aiPromptImageTester.composerPlaceholder', {
55224
- defaultValue: 'Describe the image (Cmd/Ctrl+Enter to send)'
55225
- }),
55196
+ placeholder: placeholder,
55226
55197
  autoSize: {
55227
55198
  minRows: 2,
55228
55199
  maxRows: 8
@@ -56038,25 +56009,25 @@ function ConversationSidebar(_ref) {
56038
56009
  });
56039
56010
  }
56040
56011
 
56041
- var STORAGE_KEY = 'diva-backoffice.aiPromptImageTester.geminiApiKey';
56012
+ var STORAGE_KEY$1 = 'diva-backoffice.aiPromptImageTester.geminiApiKey';
56042
56013
  function loadApiKey() {
56043
56014
  try {
56044
56015
  var _window$localStorage$;
56045
- 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$ : '';
56046
56017
  } catch (_unused) {
56047
56018
  return '';
56048
56019
  }
56049
56020
  }
56050
56021
  function saveApiKey(key) {
56051
56022
  try {
56052
- window.localStorage.setItem(STORAGE_KEY, key);
56023
+ window.localStorage.setItem(STORAGE_KEY$1, key);
56053
56024
  } catch (_unused2) {
56054
56025
  /* ignore quota / disabled storage */
56055
56026
  }
56056
56027
  }
56057
56028
  function clearApiKey() {
56058
56029
  try {
56059
- window.localStorage.removeItem(STORAGE_KEY);
56030
+ window.localStorage.removeItem(STORAGE_KEY$1);
56060
56031
  } catch (_unused3) {
56061
56032
  /* ignore */
56062
56033
  }
@@ -56076,7 +56047,7 @@ function useApiKey() {
56076
56047
  useEffect(function () {
56077
56048
  var onStorage = function onStorage(e) {
56078
56049
  var _e$newValue;
56079
- if (e.key !== STORAGE_KEY) return;
56050
+ if (e.key !== STORAGE_KEY$1) return;
56080
56051
  setApiKeyState((_e$newValue = e.newValue) !== null && _e$newValue !== void 0 ? _e$newValue : '');
56081
56052
  };
56082
56053
  window.addEventListener('storage', onStorage);
@@ -56366,15 +56337,81 @@ function GalleryFullscreenContent(_ref) {
56366
56337
  });
56367
56338
  }
56368
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
+
56369
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; }
56370
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; }
56371
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; } } }; }
56372
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; } }
56373
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; }
56374
56414
  var aiImageTester = promptAndAiTesterOptions.aiImageTester;
56375
-
56376
- /** Runaway-protection floor on history depth. Normal iterative use never reaches it. */
56377
- var MAX_HISTORY_TURNS = 50;
56378
56415
  function defaultSettings() {
56379
56416
  return {
56380
56417
  model: aiImageTester.defaultModel,
@@ -56390,6 +56427,11 @@ function useAiChat(openFullscreen) {
56390
56427
  hasKey = _useApiKey.hasKey,
56391
56428
  setApiKey = _useApiKey.setApiKey,
56392
56429
  clearApiKey = _useApiKey.clear;
56430
+ var _usePreservePromptTem = usePreservePromptTemplate(),
56431
+ preservePromptTemplate = _usePreservePromptTem.template,
56432
+ preservePromptIsCustom = _usePreservePromptTem.isCustom,
56433
+ setPreservePromptTemplate = _usePreservePromptTem.setTemplate,
56434
+ resetPreservePromptTemplate = _usePreservePromptTem.reset;
56393
56435
  var _useState = useState([]),
56394
56436
  _useState2 = _slicedToArray(_useState, 2),
56395
56437
  conversations = _useState2[0],
@@ -56416,12 +56458,8 @@ function useAiChat(openFullscreen) {
56416
56458
  setSelectedRefIds = _useState12[1];
56417
56459
  var _useState13 = useState(false),
56418
56460
  _useState14 = _slicedToArray(_useState13, 2),
56419
- bootstrapped = _useState14[0],
56420
- setBootstrapped = _useState14[1];
56421
- var _useState15 = useState(false),
56422
- _useState16 = _slicedToArray(_useState15, 2),
56423
- apiKeyModalOpen = _useState16[0],
56424
- setApiKeyModalOpen = _useState16[1];
56461
+ apiKeyModalOpen = _useState14[0],
56462
+ setApiKeyModalOpen = _useState14[1];
56425
56463
  var pendingRequests = useRef(new Map());
56426
56464
  useEffect(function () {
56427
56465
  var cancelled = false;
@@ -56476,14 +56514,10 @@ function useAiChat(openFullscreen) {
56476
56514
  case 26:
56477
56515
  message$1.error("AI tester storage error: ".concat(_context.t0 instanceof Error ? _context.t0.message : String(_context.t0)));
56478
56516
  case 27:
56479
- _context.prev = 27;
56480
- if (!cancelled) setBootstrapped(true);
56481
- return _context.finish(27);
56482
- case 30:
56483
56517
  case "end":
56484
56518
  return _context.stop();
56485
56519
  }
56486
- }, _callee, null, [[0, 22, 27, 30]]);
56520
+ }, _callee, null, [[0, 22]]);
56487
56521
  }))();
56488
56522
  return function () {
56489
56523
  cancelled = true;
@@ -56631,6 +56665,15 @@ function useAiChat(openFullscreen) {
56631
56665
  return c.id === activeConversationId;
56632
56666
  })) !== null && _conversations$find !== void 0 ? _conversations$find : null;
56633
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]);
56634
56677
  var newConversation = useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
56635
56678
  var _activeConversation$s;
56636
56679
  var created;
@@ -56840,11 +56883,6 @@ function useAiChat(openFullscreen) {
56840
56883
  var clearRefSelection = useCallback(function () {
56841
56884
  return setSelectedRefIds([]);
56842
56885
  }, []);
56843
- var selectAllRefs = useCallback(function () {
56844
- return setSelectedRefIds(refs.map(function (r) {
56845
- return r.id;
56846
- }));
56847
- }, [refs]);
56848
56886
  var removeReference = useCallback(/*#__PURE__*/function () {
56849
56887
  var _ref10 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee10(id) {
56850
56888
  var refreshed;
@@ -56896,7 +56934,7 @@ function useAiChat(openFullscreen) {
56896
56934
  }(), []);
56897
56935
  var sendMessage = useCallback(/*#__PURE__*/function () {
56898
56936
  var _ref12 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee12(text) {
56899
- 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;
56900
56938
  return _regeneratorRuntime.wrap(function _callee12$(_context12) {
56901
56939
  while (1) switch (_context12.prev = _context12.next) {
56902
56940
  case 0:
@@ -56922,33 +56960,47 @@ function useAiChat(openFullscreen) {
56922
56960
  setApiKeyModalOpen(true);
56923
56961
  return _context12.abrupt("return");
56924
56962
  case 10:
56925
- 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) {
56926
56971
  return refs.find(function (r) {
56927
56972
  return r.id === id;
56928
56973
  });
56929
56974
  }).filter(function (r) {
56930
56975
  return !!r;
56931
- });
56932
- uploadedImageIds = selectedRefs.map(function (r) {
56976
+ }).map(function (r) {
56933
56977
  return r.imageId;
56934
- }); // Snapshot completed history BEFORE persisting the new user prompt so it isn't echoed.
56935
- _context12.next = 14;
56936
- return listMessages(conv.id);
56937
- case 14:
56938
- priorRecords = _context12.sent.slice(-MAX_HISTORY_TURNS);
56939
- _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;
56940
56990
  return putUserMessage({
56941
56991
  conversationId: conv.id,
56942
56992
  text: trimmed,
56943
- uploadedImageIds: uploadedImageIds
56993
+ uploadedImageIds: userRecordImageIds
56944
56994
  });
56945
- case 17:
56995
+ case 18:
56946
56996
  userRecord = _context12.sent;
56947
- requestId = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function' ? crypto.randomUUID() : "r-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 11));
56948
- 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);
56949
57001
  resolutionCaption = galleryImageConfigCaption(conv.settings.aspectRatio, conv.settings.imageSize);
56950
57002
  temperatureCaption = galleryTemperatureCaption(conv.settings.temperature, t);
56951
- _context12.next = 24;
57003
+ _context12.next = 25;
56952
57004
  return putModelMessage({
56953
57005
  conversationId: conv.id,
56954
57006
  status: 'pending',
@@ -56959,15 +57011,15 @@ function useAiChat(openFullscreen) {
56959
57011
  temperatureCaption: temperatureCaption,
56960
57012
  ts: startedAt
56961
57013
  });
56962
- case 24:
57014
+ case 25:
56963
57015
  modelRecord = _context12.sent;
56964
- _context12.next = 27;
57016
+ _context12.next = 28;
56965
57017
  return toMessageView(userRecord);
56966
- case 27:
57018
+ case 28:
56967
57019
  userView = _context12.sent;
56968
- _context12.next = 30;
57020
+ _context12.next = 31;
56969
57021
  return toMessageView(modelRecord);
56970
- case 30:
57022
+ case 31:
56971
57023
  modelView = _context12.sent;
56972
57024
  setMessages(function (prev) {
56973
57025
  return [].concat(_toConsumableArray(prev), [userView, modelView]);
@@ -56979,13 +57031,30 @@ function useAiChat(openFullscreen) {
56979
57031
  modelMessageId: modelRecord.id
56980
57032
  });
56981
57033
  dismissLoading = message$1.loading(t('backoffice.tools.aiPromptImageTester.generating'), 0);
56982
- _context12.prev = 36;
57034
+ _context12.prev = 37;
56983
57035
  ai = createGeminiClient(apiKey);
56984
- _context12.next = 40;
56985
- return buildContents(priorRecords, trimmed, uploadedImageIds);
56986
- case 40:
57036
+ _context12.next = 41;
57037
+ return buildContents({
57038
+ text: promptForModel,
57039
+ referenceImageIds: referenceImageIds
57040
+ });
57041
+ case 41:
56987
57042
  contents = _context12.sent;
56988
- _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;
56989
57058
  return generateImage(_objectSpread$3(_objectSpread$3({
56990
57059
  ai: ai,
56991
57060
  model: conv.settings.model,
@@ -56997,110 +57066,133 @@ function useAiChat(openFullscreen) {
56997
57066
  } : {}), {}, {
56998
57067
  signal: controller.signal
56999
57068
  }));
57000
- case 43:
57069
+ case 45:
57001
57070
  result = _context12.sent;
57002
57071
  if (!(result.images.length === 0)) {
57003
- _context12.next = 51;
57072
+ _context12.next = 53;
57004
57073
  break;
57005
57074
  }
57006
- _context12.next = 47;
57075
+ _context12.next = 49;
57007
57076
  return patchModelMessage(modelRecord.id, {
57008
57077
  status: 'error',
57009
57078
  errorMessage: t('backoffice.tools.aiPromptImageTester.noImage')
57010
57079
  });
57011
- case 47:
57012
- _context12.next = 49;
57013
- return refreshActiveMessages(conv.id);
57014
57080
  case 49:
57081
+ _context12.next = 51;
57082
+ return refreshActiveMessages(conv.id);
57083
+ case 51:
57015
57084
  message$1.warning(t('backoffice.tools.aiPromptImageTester.noImage'));
57016
57085
  return _context12.abrupt("return");
57017
- case 51:
57086
+ case 53:
57018
57087
  pricePerImage = priceForOutputImage(conv.settings.model, conv.settings.imageSize);
57019
- _context12.next = 54;
57020
- return Promise.all(result.images.map(function (g) {
57021
- return putImageBlob(generatedImageToBlob(g), g.mimeType, g.thoughtSignature, pricePerImage);
57022
- }));
57023
- case 54:
57024
- imageIds = _context12.sent;
57025
- 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:
57026
57104
  _context12.next = 58;
57027
- 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, {
57028
57121
  status: 'ready',
57029
57122
  imageIds: imageIds
57030
- }, result.text ? {
57031
- responseText: result.text
57032
- } : {}), result.thoughtSignature ? {
57033
- responseThoughtSignature: result.thoughtSignature
57034
- } : {}));
57035
- case 58:
57036
- _context12.next = 60;
57123
+ });
57124
+ case 77:
57125
+ _context12.next = 79;
57037
57126
  return updateConversation(conv.id, {});
57038
- case 60:
57039
- _context12.next = 62;
57127
+ case 79:
57128
+ _context12.next = 81;
57040
57129
  return refreshActiveMessages(conv.id);
57041
- case 62:
57130
+ case 81:
57042
57131
  if (!(conv.title === 'New chat')) {
57043
- _context12.next = 68;
57132
+ _context12.next = 87;
57044
57133
  break;
57045
57134
  }
57046
57135
  title = trimmed.slice(0, 60);
57047
- _context12.next = 66;
57136
+ _context12.next = 85;
57048
57137
  return updateConversation(conv.id, {
57049
57138
  title: title
57050
57139
  });
57051
- case 66:
57140
+ case 85:
57052
57141
  updated = _context12.sent;
57053
57142
  if (updated) setConversations(function (prev) {
57054
57143
  return prev.map(function (c) {
57055
57144
  return c.id === updated.id ? updated : c;
57056
57145
  });
57057
57146
  });
57058
- case 68:
57147
+ case 87:
57148
+ // Auto-deselect every reference that was just sent. Its already in the chat history
57149
+
57150
+ setSelectedRefIds([]);
57059
57151
  message$1.success(t('backoffice.tools.aiPromptImageTester.generated'));
57060
- _context12.next = 84;
57152
+ _context12.next = 104;
57061
57153
  break;
57062
- case 71:
57063
- _context12.prev = 71;
57064
- _context12.t0 = _context12["catch"](36);
57154
+ case 91:
57155
+ _context12.prev = 91;
57156
+ _context12.t1 = _context12["catch"](37);
57065
57157
  if (!controller.signal.aborted) {
57066
- _context12.next = 78;
57158
+ _context12.next = 98;
57067
57159
  break;
57068
57160
  }
57069
- _context12.next = 76;
57161
+ _context12.next = 96;
57070
57162
  return patchModelMessage(modelRecord.id, {
57071
57163
  status: 'error',
57072
57164
  errorMessage: 'Cancelled'
57073
57165
  });
57074
- case 76:
57075
- _context12.next = 82;
57166
+ case 96:
57167
+ _context12.next = 102;
57076
57168
  break;
57077
- case 78:
57078
- msg = formatGeminiError(_context12.t0, t);
57079
- _context12.next = 81;
57169
+ case 98:
57170
+ msg = formatGeminiError(_context12.t1, t);
57171
+ _context12.next = 101;
57080
57172
  return patchModelMessage(modelRecord.id, {
57081
57173
  status: 'error',
57082
57174
  errorMessage: msg
57083
57175
  });
57084
- case 81:
57176
+ case 101:
57085
57177
  message$1.error(msg);
57086
- case 82:
57087
- _context12.next = 84;
57178
+ case 102:
57179
+ _context12.next = 104;
57088
57180
  return refreshActiveMessages(conv.id);
57089
- case 84:
57090
- _context12.prev = 84;
57181
+ case 104:
57182
+ _context12.prev = 104;
57091
57183
  pendingRequests.current["delete"](modelRecord.id);
57092
57184
  dismissLoading();
57093
- return _context12.finish(84);
57094
- case 88:
57185
+ return _context12.finish(104);
57186
+ case 108:
57095
57187
  case "end":
57096
57188
  return _context12.stop();
57097
57189
  }
57098
- }, _callee12, null, [[36, 71, 84, 88]]);
57190
+ }, _callee12, null, [[37, 91, 104, 108], [56, 68, 71, 74]]);
57099
57191
  }));
57100
57192
  return function (_x8) {
57101
57193
  return _ref12.apply(this, arguments);
57102
57194
  };
57103
- }(), [activeConversation, apiKey, refs, selectedRefIds, refreshActiveMessages, t]);
57195
+ }(), [activeConversation, apiKey, refs, selectedRefIds, refreshActiveMessages, preservePromptTemplate, t]);
57104
57196
  var abortMessage = useCallback(function (modelMessageId) {
57105
57197
  var entry = pendingRequests.current.get(modelMessageId);
57106
57198
  entry === null || entry === void 0 || entry.controller.abort();
@@ -57177,17 +57269,17 @@ function useAiChat(openFullscreen) {
57177
57269
  }(), [activeConversationId, messages, refreshActiveMessages]);
57178
57270
  var openImageFullscreen = useCallback(function (initialReadyIndex) {
57179
57271
  var slides = [];
57180
- var _iterator2 = _createForOfIteratorHelper(messages),
57181
- _step2;
57272
+ var _iterator3 = _createForOfIteratorHelper(messages),
57273
+ _step3;
57182
57274
  try {
57183
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
57184
- var m = _step2.value;
57275
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
57276
+ var m = _step3.value;
57185
57277
  if (m.kind !== 'model' || m.status !== 'ready') continue;
57186
- var _iterator3 = _createForOfIteratorHelper(m.imageUrls),
57187
- _step3;
57278
+ var _iterator4 = _createForOfIteratorHelper(m.imageUrls),
57279
+ _step4;
57188
57280
  try {
57189
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
57190
- var url = _step3.value;
57281
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
57282
+ var url = _step4.value;
57191
57283
  slides.push({
57192
57284
  imageUrl: url,
57193
57285
  promptText: m.promptText,
@@ -57198,15 +57290,15 @@ function useAiChat(openFullscreen) {
57198
57290
  });
57199
57291
  }
57200
57292
  } catch (err) {
57201
- _iterator3.e(err);
57293
+ _iterator4.e(err);
57202
57294
  } finally {
57203
- _iterator3.f();
57295
+ _iterator4.f();
57204
57296
  }
57205
57297
  }
57206
57298
  } catch (err) {
57207
- _iterator2.e(err);
57299
+ _iterator3.e(err);
57208
57300
  } finally {
57209
- _iterator2.f();
57301
+ _iterator3.f();
57210
57302
  }
57211
57303
  if (slides.length === 0) return;
57212
57304
  var idx = Math.min(Math.max(0, initialReadyIndex), slides.length - 1);
@@ -57220,7 +57312,6 @@ function useAiChat(openFullscreen) {
57220
57312
  });
57221
57313
  }, [messages, openFullscreen]);
57222
57314
  return {
57223
- bootstrapped: bootstrapped,
57224
57315
  conversations: conversations,
57225
57316
  activeConversation: activeConversation,
57226
57317
  activeConversationId: activeConversationId,
@@ -57230,6 +57321,7 @@ function useAiChat(openFullscreen) {
57230
57321
  deleteConversation: deleteConversation$1,
57231
57322
  updateActiveSettings: updateActiveSettings,
57232
57323
  messages: messages,
57324
+ isFollowUp: isFollowUp,
57233
57325
  sendMessage: sendMessage,
57234
57326
  abortMessage: abortMessage,
57235
57327
  retryMessage: retryMessage,
@@ -57240,7 +57332,6 @@ function useAiChat(openFullscreen) {
57240
57332
  selectedRefIds: selectedRefIds,
57241
57333
  toggleRefSelection: toggleRefSelection,
57242
57334
  clearRefSelection: clearRefSelection,
57243
- selectAllRefs: selectAllRefs,
57244
57335
  onReferenceUpload: onReferenceUpload,
57245
57336
  removeReference: removeReference,
57246
57337
  apiKey: apiKey,
@@ -57253,7 +57344,11 @@ function useAiChat(openFullscreen) {
57253
57344
  }, []),
57254
57345
  closeApiKeyModal: useCallback(function () {
57255
57346
  return setApiKeyModalOpen(false);
57256
- }, [])
57347
+ }, []),
57348
+ preservePromptTemplate: preservePromptTemplate,
57349
+ preservePromptIsCustom: preservePromptIsCustom,
57350
+ setPreservePromptTemplate: setPreservePromptTemplate,
57351
+ resetPreservePromptTemplate: resetPreservePromptTemplate
57257
57352
  };
57258
57353
  }
57259
57354
  function toMessageView(_x11) {
@@ -57370,6 +57465,7 @@ var AiPromptImageTester = observer(function (_ref) {
57370
57465
  deleteConversation = _useAiChat.deleteConversation,
57371
57466
  updateActiveSettings = _useAiChat.updateActiveSettings,
57372
57467
  messages = _useAiChat.messages,
57468
+ isFollowUp = _useAiChat.isFollowUp,
57373
57469
  sendMessage = _useAiChat.sendMessage,
57374
57470
  abortMessage = _useAiChat.abortMessage,
57375
57471
  retryMessage = _useAiChat.retryMessage,
@@ -57388,7 +57484,11 @@ var AiPromptImageTester = observer(function (_ref) {
57388
57484
  clearApiKey = _useAiChat.clearApiKey,
57389
57485
  apiKeyModalOpen = _useAiChat.apiKeyModalOpen,
57390
57486
  openApiKeyModal = _useAiChat.openApiKeyModal,
57391
- closeApiKeyModal = _useAiChat.closeApiKeyModal;
57487
+ closeApiKeyModal = _useAiChat.closeApiKeyModal,
57488
+ preservePromptTemplate = _useAiChat.preservePromptTemplate,
57489
+ preservePromptIsCustom = _useAiChat.preservePromptIsCustom,
57490
+ setPreservePromptTemplate = _useAiChat.setPreservePromptTemplate,
57491
+ resetPreservePromptTemplate = _useAiChat.resetPreservePromptTemplate;
57392
57492
  var lastModel = _toConsumableArray(messages).reverse().find(function (m) {
57393
57493
  return m.kind === 'model';
57394
57494
  });
@@ -57446,11 +57546,16 @@ var AiPromptImageTester = observer(function (_ref) {
57446
57546
  return void removeReference(id);
57447
57547
  },
57448
57548
  pending: pending,
57549
+ isFollowUp: isFollowUp,
57449
57550
  onSend: function onSend(text) {
57450
57551
  return void sendMessage(text);
57451
57552
  },
57452
57553
  hasApiKey: hasKey,
57453
- onRequestApiKey: openApiKeyModal
57554
+ onRequestApiKey: openApiKeyModal,
57555
+ preservePromptTemplate: preservePromptTemplate,
57556
+ preservePromptIsCustom: preservePromptIsCustom,
57557
+ onPreservePromptTemplateChange: setPreservePromptTemplate,
57558
+ onResetPreservePromptTemplate: resetPreservePromptTemplate
57454
57559
  }) : null]
57455
57560
  })]
57456
57561
  })