@cedros/pay-react 1.1.16 → 1.1.17

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 (149) hide show
  1. package/dist/AISettingsSection--jn-BNmd.mjs +539 -0
  2. package/dist/AISettingsSection-BrXUD4l_.js +51 -0
  3. package/dist/AutosaveIndicator-B3T328jH.mjs +35 -0
  4. package/dist/AutosaveIndicator-BQkm3cn8.js +1 -0
  5. package/dist/{CedrosContext-D7nh5-Zh.mjs → CedrosContext-BnJ2Cf7R.mjs} +1179 -642
  6. package/dist/CedrosContext-C26DlvLF.js +6 -0
  7. package/dist/CryptoButton-B4-oJ8lF.js +1 -0
  8. package/dist/CryptoButton-Dhxnk9d7.mjs +542 -0
  9. package/dist/FAQSection-BB1wJRsR.mjs +366 -0
  10. package/dist/FAQSection-aoAz35MV.js +1 -0
  11. package/dist/MessagingSection-BG9O62ko.mjs +347 -0
  12. package/dist/MessagingSection-DId-WJdU.js +1 -0
  13. package/dist/PaymentSettingsSection-D92IO4xJ.js +1 -0
  14. package/dist/PaymentSettingsSection-c13RAUxn.mjs +94 -0
  15. package/dist/SettingsSection-DUxjXl2G.js +1 -0
  16. package/dist/SettingsSection-htem-WL3.mjs +57 -0
  17. package/dist/SingleCategorySettings-BIEs6s6Z.mjs +1421 -0
  18. package/dist/SingleCategorySettings-CQ-osdzb.js +3 -0
  19. package/dist/StorefrontSection-CKTQt255.mjs +765 -0
  20. package/dist/StorefrontSection-DcSoDx-k.js +1 -0
  21. package/dist/SubscriptionsSection-C0hYf7Hr.js +1 -0
  22. package/dist/SubscriptionsSection-CONwHhT4.mjs +616 -0
  23. package/dist/Toggle-CsPSF8Dr.js +1 -0
  24. package/dist/Toggle-DAxIdpY4.mjs +48 -0
  25. package/dist/WalletManager-D6BYTwXn.js +1 -0
  26. package/dist/{WalletManager-oEjZhaFk.mjs → WalletManager-HXXyARQ7.mjs} +36 -32
  27. package/dist/components/CedrosPay.d.ts.map +1 -1
  28. package/dist/components/CryptoSubscribeButton.d.ts.map +1 -1
  29. package/dist/components/PaymentModal.d.ts.map +1 -1
  30. package/dist/components/SubscriptionManagementPanel.d.ts.map +1 -1
  31. package/dist/components/admin/AISettingsSection.d.ts.map +1 -1
  32. package/dist/components/admin/AdminAuthManager.d.ts +2 -1
  33. package/dist/components/admin/AdminAuthManager.d.ts.map +1 -1
  34. package/dist/components/admin/AutosaveIndicator.d.ts +7 -0
  35. package/dist/components/admin/AutosaveIndicator.d.ts.map +1 -0
  36. package/dist/components/admin/CedrosPayAdminDashboard.d.ts.map +1 -1
  37. package/dist/components/admin/ConfigEditor.d.ts +0 -2
  38. package/dist/components/admin/ConfigEditor.d.ts.map +1 -1
  39. package/dist/components/admin/MessagingSection.d.ts.map +1 -1
  40. package/dist/components/admin/ProductsSection.d.ts.map +1 -1
  41. package/dist/components/admin/RefundsSection.d.ts.map +1 -1
  42. package/dist/components/admin/SecretArrayEditor.d.ts +16 -0
  43. package/dist/components/admin/SecretArrayEditor.d.ts.map +1 -0
  44. package/dist/components/admin/SingleCategorySettings.d.ts.map +1 -1
  45. package/dist/components/admin/StorefrontSection.d.ts.map +1 -1
  46. package/dist/components/admin/Toggle.d.ts +14 -0
  47. package/dist/components/admin/Toggle.d.ts.map +1 -0
  48. package/dist/components/admin/TokenMintSelector.d.ts +27 -0
  49. package/dist/components/admin/TokenMintSelector.d.ts.map +1 -0
  50. package/dist/components/admin/configApi.d.ts +5 -3
  51. package/dist/components/admin/configApi.d.ts.map +1 -1
  52. package/dist/components/admin/index.d.ts +8 -9
  53. package/dist/components/admin/index.d.ts.map +1 -1
  54. package/dist/components/admin/sections-more.d.ts +2 -9
  55. package/dist/components/admin/sections-more.d.ts.map +1 -1
  56. package/dist/context/CedrosContext.d.ts +1 -1
  57. package/dist/context/CedrosContext.d.ts.map +1 -1
  58. package/dist/crypto-only.js +1 -1
  59. package/dist/crypto-only.mjs +391 -380
  60. package/dist/ecommerce/__tests__/inventoryHooks.test.d.ts +2 -0
  61. package/dist/ecommerce/__tests__/inventoryHooks.test.d.ts.map +1 -0
  62. package/dist/ecommerce/__tests__/storage.test.d.ts +2 -0
  63. package/dist/ecommerce/__tests__/storage.test.d.ts.map +1 -0
  64. package/dist/ecommerce/adapters/CommerceAdapter.d.ts +5 -0
  65. package/dist/ecommerce/adapters/CommerceAdapter.d.ts.map +1 -1
  66. package/dist/ecommerce/adapters/mock/mockAdapter.d.ts.map +1 -1
  67. package/dist/ecommerce/adapters/paywall/paywallAdapter.d.ts.map +1 -1
  68. package/dist/ecommerce/adapters/paywall/paywallAdapter.test.d.ts +2 -0
  69. package/dist/ecommerce/adapters/paywall/paywallAdapter.test.d.ts.map +1 -0
  70. package/dist/ecommerce/components/catalog/ProductCard.d.ts.map +1 -1
  71. package/dist/ecommerce/components/catalog/QuickViewDialog.d.ts.map +1 -1
  72. package/dist/ecommerce/components/chat/ShopChatPanel.d.ts +4 -0
  73. package/dist/ecommerce/components/chat/ShopChatPanel.d.ts.map +1 -1
  74. package/dist/ecommerce/components/checkout/PaymentStep.d.ts.map +1 -1
  75. package/dist/ecommerce/components/faq/FAQItem.d.ts.map +1 -1
  76. package/dist/ecommerce/config/context.d.ts.map +1 -1
  77. package/dist/ecommerce/hooks/useAIRelatedProducts.d.ts.map +1 -1
  78. package/dist/ecommerce/hooks/useCartInventory.d.ts.map +1 -1
  79. package/dist/ecommerce/hooks/useHoldExpiry.d.ts.map +1 -1
  80. package/dist/ecommerce/hooks/useInventoryVerification.d.ts.map +1 -1
  81. package/dist/ecommerce/hooks/useProducts.d.ts.map +1 -1
  82. package/dist/ecommerce/index.d.ts +2 -0
  83. package/dist/ecommerce/index.d.ts.map +1 -1
  84. package/dist/ecommerce/integrations/cedros-pay/useCedrosPayCheckoutAdapter.d.ts.map +1 -1
  85. package/dist/ecommerce/state/cart/CartProvider.d.ts.map +1 -1
  86. package/dist/ecommerce/state/checkout/checkoutSchema.d.ts +1 -1
  87. package/dist/ecommerce/state/checkout/useCheckout.d.ts.map +1 -1
  88. package/dist/ecommerce/templates/ProductTemplate.d.ts.map +1 -1
  89. package/dist/ecommerce/utils/storage.d.ts +1 -1
  90. package/dist/ecommerce/utils/storage.d.ts.map +1 -1
  91. package/dist/hooks/useCreditsPayment.d.ts.map +1 -1
  92. package/dist/hooks/useCreditsSubscription.d.ts.map +1 -1
  93. package/dist/hooks/useCryptoSubscription.d.ts.map +1 -1
  94. package/dist/hooks/useRefundVerification.d.ts.map +1 -1
  95. package/dist/hooks/useStripeCheckout.d.ts +1 -1
  96. package/dist/hooks/useStripeCheckout.d.ts.map +1 -1
  97. package/dist/hooks/useSubscription.d.ts.map +1 -1
  98. package/dist/hooks/useSubscriptionManagement.d.ts.map +1 -1
  99. package/dist/hooks/useX402Payment.d.ts.map +1 -1
  100. package/dist/index-2N_CMVAv.js +84 -0
  101. package/dist/index-C1hbnxn0.mjs +22915 -0
  102. package/dist/index.js +1 -1
  103. package/dist/index.mjs +67 -72
  104. package/dist/managers/CreditsManager.d.ts +6 -0
  105. package/dist/managers/CreditsManager.d.ts.map +1 -1
  106. package/dist/managers/ManagerCache.d.ts.map +1 -1
  107. package/dist/managers/RouteDiscoveryManager.d.ts +3 -0
  108. package/dist/managers/RouteDiscoveryManager.d.ts.map +1 -1
  109. package/dist/managers/StripeManager.d.ts +15 -0
  110. package/dist/managers/StripeManager.d.ts.map +1 -1
  111. package/dist/managers/SubscriptionChangeManager.d.ts.map +1 -1
  112. package/dist/managers/SubscriptionManager.d.ts +7 -14
  113. package/dist/managers/SubscriptionManager.d.ts.map +1 -1
  114. package/dist/managers/WalletManager.d.ts +2 -1
  115. package/dist/managers/WalletManager.d.ts.map +1 -1
  116. package/dist/managers/X402Manager.d.ts.map +1 -1
  117. package/dist/{sections-CL3lbNui.js → sections-D2GMJuKq.js} +1 -1
  118. package/dist/{sections-DnmB0qdx.mjs → sections-DICaHGhz.mjs} +1 -1
  119. package/dist/stripe-only.js +1 -1
  120. package/dist/stripe-only.mjs +67 -72
  121. package/dist/telemetry.js +1 -1
  122. package/dist/telemetry.mjs +23 -25
  123. package/dist/testing/index.js +1 -1
  124. package/dist/testing/index.mjs +1 -1
  125. package/dist/types/index.d.ts +13 -2
  126. package/dist/types/index.d.ts.map +1 -1
  127. package/dist/useAutosave-B2p6iwh8.js +1 -0
  128. package/dist/useAutosave-YwMqRzqy.mjs +44 -0
  129. package/dist/utils/circuitBreaker.d.ts +3 -1
  130. package/dist/utils/circuitBreaker.d.ts.map +1 -1
  131. package/dist/utils/cspHelper.d.ts +6 -0
  132. package/dist/utils/cspHelper.d.ts.map +1 -1
  133. package/dist/utils/csvHelpers.d.ts +0 -41
  134. package/dist/utils/csvHelpers.d.ts.map +1 -1
  135. package/dist/utils/errorHandling.d.ts.map +1 -1
  136. package/dist/utils/exponentialBackoff.d.ts.map +1 -1
  137. package/dist/utils/requestDeduplication.d.ts.map +1 -1
  138. package/dist/utils/telemetry.d.ts.map +1 -1
  139. package/dist/utils/validateConfig.d.ts +1 -1
  140. package/dist/utils/validateConfig.d.ts.map +1 -1
  141. package/dist/walletDetection-JZR3UCOa.mjs +27 -0
  142. package/dist/walletDetection-bNmV5ItZ.js +1 -0
  143. package/dist/{walletPool-BR6etEiq.mjs → walletPool-BV_z1lEA.mjs} +1 -1
  144. package/dist/{walletPool-BZyAG4YS.js → walletPool-DjA7J3a9.js} +1 -1
  145. package/package.json +8 -7
  146. package/dist/CedrosContext-C2v_s8cc.js +0 -6
  147. package/dist/WalletManager-B5KLZK2D.js +0 -1
  148. package/dist/index-BU0vgA-7.js +0 -136
  149. package/dist/index-DWXEBUbu.mjs +0 -27912
@@ -0,0 +1,539 @@
1
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
2
+ import { useState as u, useRef as S, useCallback as A, useEffect as T, useMemo as q } from "react";
3
+ import { $ as w, a0 as J, a2 as Y } from "./index-C1hbnxn0.mjs";
4
+ import { A as X } from "./AutosaveIndicator-B3T328jH.mjs";
5
+ const E = [
6
+ { id: "not_set", label: "Disabled", provider: null },
7
+ { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash", provider: "gemini" },
8
+ { id: "gemini-2.5-pro", label: "Gemini 2.5 Pro", provider: "gemini" },
9
+ { id: "openai-4o", label: "OpenAI 4o", provider: "openai" },
10
+ { id: "openai-5.1", label: "OpenAI 5.1", provider: "openai" },
11
+ { id: "openai-5.2", label: "OpenAI 5.2", provider: "openai" }
12
+ ], $ = [
13
+ {
14
+ task: "site_chat",
15
+ label: "Site Chat",
16
+ description: "The conversational model that crafts responses to customer messages",
17
+ defaultPrompt: `You are a friendly and helpful shopping assistant for our store. Your role is to:
18
+
19
+ - Help customers find products that match their needs
20
+ - Answer questions about products, shipping, returns, and store policies
21
+ - Provide personalized recommendations based on customer preferences
22
+ - Use the Product Searcher tool when customers are looking for specific items
23
+
24
+ Guidelines:
25
+ - Be warm, conversational, and concise
26
+ - Stay focused on helping with shopping-related questions
27
+ - If you don't know something specific about a product, say so honestly
28
+ - Never make up product details, prices, or availability
29
+ - For complex issues (order problems, refunds), direct customers to contact support`
30
+ },
31
+ {
32
+ task: "product_searcher",
33
+ label: "Product Searcher",
34
+ description: "Tool used by Site Chat to find products based on customer queries",
35
+ defaultPrompt: `You are a product search assistant. Given a customer's query, extract relevant search parameters to find matching products.
36
+
37
+ Extract the following when present:
38
+ - Keywords: Main search terms
39
+ - Category: Product category or type
40
+ - Price range: Min/max price if mentioned
41
+ - Attributes: Color, size, material, brand, or other specifications
42
+ - Sort preference: Price, popularity, newest, etc.
43
+
44
+ Return structured search parameters. Be liberal in interpretation - if a customer says "something for my mom's birthday under $50" extract: keywords=gift, price_max=50, occasion=birthday.
45
+
46
+ Do not make assumptions about specific products. Focus only on extracting search intent.`
47
+ },
48
+ {
49
+ task: "related_product_finder",
50
+ label: "Related Product Finder",
51
+ description: "AI-powered recommendations for related products on product pages",
52
+ defaultPrompt: `You are a product recommendation engine. Given a product, suggest related items that customers might also be interested in.
53
+
54
+ Consider these recommendation types:
55
+ - Complementary items: Products that go well together (e.g., phone case for a phone)
56
+ - Similar alternatives: Products in the same category with different features or price points
57
+ - Frequently bought together: Items commonly purchased as a set
58
+ - Upsells: Premium versions or upgrades
59
+
60
+ Guidelines:
61
+ - Prioritize relevance over variety
62
+ - Consider the product's category, price range, and use case
63
+ - Return product IDs or search criteria for related items
64
+ - Aim for 4-8 recommendations with a mix of types`
65
+ },
66
+ {
67
+ task: "product_detail_assistant",
68
+ label: "Product Detail Assistant",
69
+ description: "Admin tool to generate product descriptions, suggest tags, and fill out product details",
70
+ defaultPrompt: `You are a product copywriting assistant helping store administrators create compelling product listings.
71
+
72
+ You can help with:
73
+ - Writing engaging product descriptions that highlight key features and benefits
74
+ - Suggesting relevant tags and categories for better discoverability
75
+ - Creating SEO-friendly titles and meta descriptions
76
+ - Generating bullet points for key features
77
+ - Writing size guides or care instructions when applicable
78
+
79
+ Guidelines:
80
+ - Match the store's brand voice (ask if unclear)
81
+ - Focus on benefits, not just features
82
+ - Use sensory language when appropriate
83
+ - Keep descriptions scannable with short paragraphs
84
+ - Avoid superlatives and unverifiable claims
85
+ - Include relevant keywords naturally for SEO`
86
+ }
87
+ ], H = [
88
+ { id: "gemini", label: "Google Gemini API", placeholder: "AIza..." },
89
+ { id: "openai", label: "OpenAI API", placeholder: "sk-..." }
90
+ ], D = {
91
+ apiKeys: [
92
+ { provider: "gemini", isConfigured: !1 },
93
+ { provider: "openai", isConfigured: !1 }
94
+ ],
95
+ taskAssignments: $.map((o) => ({
96
+ task: o.task,
97
+ label: o.label,
98
+ description: o.description,
99
+ assignedModel: "not_set",
100
+ systemPrompt: o.defaultPrompt
101
+ }))
102
+ };
103
+ function ee({ serverUrl: o, apiKey: d, authManager: c }) {
104
+ const [y, _] = u("api-keys"), [h, g] = u(D), [N, b] = u(!0), [p, l] = u(!1), [k, f] = u(null), [O, v] = u(!1), [K, R] = u(null), m = S(null), [I, F] = u({
105
+ gemini: "",
106
+ openai: ""
107
+ }), [x, G] = u({
108
+ gemini: !1,
109
+ openai: !1
110
+ }), C = A(async () => {
111
+ try {
112
+ let e;
113
+ if (c?.isAuthenticated())
114
+ e = await c.fetchWithAuth("/admin/config/ai");
115
+ else {
116
+ const s = { "Content-Type": "application/json" };
117
+ d && (s["X-API-Key"] = d);
118
+ const t = await fetch(`${o}/admin/config/ai`, { headers: s });
119
+ if (!t.ok) throw new Error(`Failed to fetch: ${t.status}`);
120
+ e = await t.json();
121
+ }
122
+ e.settings && g(e.settings);
123
+ } catch {
124
+ g(D), R("Could not load saved AI settings. Showing defaults.");
125
+ } finally {
126
+ b(!1);
127
+ }
128
+ }, [o, d, c]);
129
+ T(() => {
130
+ C();
131
+ }, [C]);
132
+ const z = A(
133
+ async (e) => {
134
+ const s = I[e];
135
+ if (s.trim()) {
136
+ l(!0), f(null);
137
+ try {
138
+ const t = { provider: e, apiKey: s };
139
+ if (c?.isAuthenticated())
140
+ await c.fetchWithAuth("/admin/config/ai/api-key", {
141
+ method: "PUT",
142
+ body: JSON.stringify(t)
143
+ });
144
+ else {
145
+ const i = { "Content-Type": "application/json" };
146
+ d && (i["X-API-Key"] = d);
147
+ const a = await fetch(`${o}/admin/config/ai/api-key`, {
148
+ method: "PUT",
149
+ headers: i,
150
+ body: JSON.stringify(t)
151
+ });
152
+ if (!a.ok) throw new Error(`Failed to save: ${a.status}`);
153
+ }
154
+ g((i) => ({
155
+ ...i,
156
+ apiKeys: i.apiKeys.map(
157
+ (a) => a.provider === e ? {
158
+ ...a,
159
+ isConfigured: !0,
160
+ maskedKey: `${s.slice(0, 4)}...${s.slice(-4)}`,
161
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
162
+ } : a
163
+ )
164
+ })), F((i) => ({ ...i, [e]: "" })), v(!0), m.current && clearTimeout(m.current), m.current = setTimeout(() => v(!1), 3e3);
165
+ } catch (t) {
166
+ f(t instanceof Error ? t.message : "Failed to save API key");
167
+ } finally {
168
+ l(!1);
169
+ }
170
+ }
171
+ },
172
+ [I, o, d, c]
173
+ ), j = A(
174
+ async (e) => {
175
+ if (confirm(`Are you sure you want to delete the ${e === "gemini" ? "Google Gemini" : "OpenAI"} API key?`)) {
176
+ l(!0), f(null);
177
+ try {
178
+ if (c?.isAuthenticated())
179
+ await c.fetchWithAuth(`/admin/config/ai/api-key/${e}`, {
180
+ method: "DELETE"
181
+ });
182
+ else {
183
+ const s = { "Content-Type": "application/json" };
184
+ d && (s["X-API-Key"] = d);
185
+ const t = await fetch(`${o}/admin/config/ai/api-key/${e}`, {
186
+ method: "DELETE",
187
+ headers: s
188
+ });
189
+ if (!t.ok) throw new Error(`Failed to delete: ${t.status}`);
190
+ }
191
+ g((s) => ({
192
+ ...s,
193
+ apiKeys: s.apiKeys.map(
194
+ (t) => t.provider === e ? { provider: e, isConfigured: !1 } : t
195
+ )
196
+ }));
197
+ } catch (s) {
198
+ f(s instanceof Error ? s.message : "Failed to delete API key");
199
+ } finally {
200
+ l(!1);
201
+ }
202
+ }
203
+ },
204
+ [o, d, c]
205
+ ), W = A(
206
+ async (e, s) => {
207
+ l(!0), f(null);
208
+ try {
209
+ const t = { task: e, model: s };
210
+ if (c?.isAuthenticated())
211
+ await c.fetchWithAuth("/admin/config/ai/assignment", {
212
+ method: "PUT",
213
+ body: JSON.stringify(t)
214
+ });
215
+ else {
216
+ const i = { "Content-Type": "application/json" };
217
+ d && (i["X-API-Key"] = d);
218
+ const a = await fetch(`${o}/admin/config/ai/assignment`, {
219
+ method: "PUT",
220
+ headers: i,
221
+ body: JSON.stringify(t)
222
+ });
223
+ if (!a.ok) throw new Error(`Failed to save: ${a.status}`);
224
+ }
225
+ g((i) => ({
226
+ ...i,
227
+ taskAssignments: i.taskAssignments.map(
228
+ (a) => a.task === e ? { ...a, assignedModel: s } : a
229
+ )
230
+ })), v(!0), m.current && clearTimeout(m.current), m.current = setTimeout(() => v(!1), 3e3);
231
+ } catch (t) {
232
+ f(t instanceof Error ? t.message : "Failed to save assignment");
233
+ } finally {
234
+ l(!1);
235
+ }
236
+ },
237
+ [o, d, c]
238
+ ), P = A(
239
+ (e) => {
240
+ if (e === "not_set") return !0;
241
+ const s = E.find((i) => i.id === e);
242
+ return s?.provider ? h.apiKeys.find((i) => i.provider === s.provider)?.isConfigured ?? !1 : !0;
243
+ },
244
+ [h.apiKeys]
245
+ ), B = q(() => E.map((e) => {
246
+ const s = P(e.id);
247
+ return {
248
+ value: e.id,
249
+ label: s ? e.label : `${e.label} (API key required)`,
250
+ disabled: !s
251
+ };
252
+ }), [P]), L = A(
253
+ async (e, s) => {
254
+ l(!0), f(null);
255
+ try {
256
+ const t = { task: e, systemPrompt: s };
257
+ if (c?.isAuthenticated())
258
+ await c.fetchWithAuth("/admin/config/ai/prompt", {
259
+ method: "PUT",
260
+ body: JSON.stringify(t)
261
+ });
262
+ else {
263
+ const i = { "Content-Type": "application/json" };
264
+ d && (i["X-API-Key"] = d);
265
+ const a = await fetch(`${o}/admin/config/ai/prompt`, {
266
+ method: "PUT",
267
+ headers: i,
268
+ body: JSON.stringify(t)
269
+ });
270
+ if (!a.ok) throw new Error(`Failed to save: ${a.status}`);
271
+ }
272
+ g((i) => ({
273
+ ...i,
274
+ taskAssignments: i.taskAssignments.map(
275
+ (a) => a.task === e ? { ...a, systemPrompt: s } : a
276
+ )
277
+ })), v(!0), m.current && clearTimeout(m.current), m.current = setTimeout(() => v(!1), 3e3);
278
+ } catch (t) {
279
+ f(t instanceof Error ? t.message : "Failed to save prompt");
280
+ } finally {
281
+ l(!1);
282
+ }
283
+ },
284
+ [o, d, c]
285
+ );
286
+ return T(() => () => {
287
+ m.current && clearTimeout(m.current);
288
+ }, []), N ? /* @__PURE__ */ n("div", { className: "cedros-admin__section", children: /* @__PURE__ */ r("div", { className: "cedros-admin__loading", children: [
289
+ w.loading,
290
+ " Loading AI settings..."
291
+ ] }) }) : /* @__PURE__ */ r("div", { className: "cedros-admin__ai-settings", children: [
292
+ /* @__PURE__ */ r("div", { className: "cedros-admin__page-header", children: [
293
+ /* @__PURE__ */ n("h2", { className: "cedros-admin__page-title", children: "Store AI" }),
294
+ /* @__PURE__ */ n("p", { className: "cedros-admin__page-description", children: "Configure AI providers, model assignments, and system prompts." })
295
+ ] }),
296
+ /* @__PURE__ */ r("div", { className: "cedros-admin__tabs cedros-admin__tabs--line", children: [
297
+ /* @__PURE__ */ n(
298
+ "button",
299
+ {
300
+ type: "button",
301
+ className: `cedros-admin__tab ${y === "api-keys" ? "cedros-admin__tab--active" : ""}`,
302
+ onClick: () => _("api-keys"),
303
+ children: "API Keys"
304
+ }
305
+ ),
306
+ /* @__PURE__ */ n(
307
+ "button",
308
+ {
309
+ type: "button",
310
+ className: `cedros-admin__tab ${y === "assignments" ? "cedros-admin__tab--active" : ""}`,
311
+ onClick: () => _("assignments"),
312
+ children: "Model Assignments"
313
+ }
314
+ ),
315
+ /* @__PURE__ */ n(
316
+ "button",
317
+ {
318
+ type: "button",
319
+ className: `cedros-admin__tab ${y === "prompts" ? "cedros-admin__tab--active" : ""}`,
320
+ onClick: () => _("prompts"),
321
+ children: "Prompts"
322
+ }
323
+ )
324
+ ] }),
325
+ k && /* @__PURE__ */ n("div", { className: "cedros-admin__error-banner", style: { marginTop: "1rem" }, children: k }),
326
+ /* @__PURE__ */ n(J, { message: K, onRetry: C }),
327
+ O && /* @__PURE__ */ r("div", { className: "cedros-admin__success-banner", style: { marginTop: "1rem" }, children: [
328
+ w.check,
329
+ " Settings saved successfully"
330
+ ] }),
331
+ y === "api-keys" && /* @__PURE__ */ r("div", { className: "cedros-admin__section", style: { marginTop: "1rem" }, children: [
332
+ /* @__PURE__ */ n("div", { className: "cedros-admin__section-header", children: /* @__PURE__ */ n("h3", { className: "cedros-admin__section-title", children: "API Keys" }) }),
333
+ /* @__PURE__ */ n("p", { style: { marginBottom: "1.5rem", opacity: 0.7, fontSize: 14 }, children: "Configure API keys for AI providers. Keys are stored securely and never exposed." }),
334
+ /* @__PURE__ */ n("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" }, children: H.map((e) => {
335
+ const s = h.apiKeys.find((i) => i.provider === e.id), t = s?.isConfigured ?? !1;
336
+ return /* @__PURE__ */ r(
337
+ "div",
338
+ {
339
+ className: "cedros-admin__api-key-card",
340
+ style: {
341
+ padding: "1rem",
342
+ border: "1px solid var(--cedros-admin-border)",
343
+ borderRadius: 8
344
+ },
345
+ children: [
346
+ /* @__PURE__ */ r("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "0.75rem" }, children: [
347
+ /* @__PURE__ */ r("div", { children: [
348
+ /* @__PURE__ */ n("div", { style: { fontWeight: 600 }, children: e.label }),
349
+ t && s?.maskedKey && /* @__PURE__ */ r("div", { style: { fontSize: 12, opacity: 0.6, marginTop: 2 }, children: [
350
+ "Current key: ",
351
+ s.maskedKey,
352
+ s.updatedAt && /* @__PURE__ */ r("span", { children: [
353
+ " (updated ",
354
+ new Date(s.updatedAt).toLocaleDateString(),
355
+ ")"
356
+ ] })
357
+ ] })
358
+ ] }),
359
+ /* @__PURE__ */ n(
360
+ "span",
361
+ {
362
+ className: `cedros-admin__badge ${t ? "cedros-admin__badge--success" : "cedros-admin__badge--muted"}`,
363
+ children: t ? "Configured" : "Not Set"
364
+ }
365
+ )
366
+ ] }),
367
+ /* @__PURE__ */ n("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: /* @__PURE__ */ r("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center" }, children: [
368
+ /* @__PURE__ */ n(
369
+ "input",
370
+ {
371
+ type: x[e.id] ? "text" : "password",
372
+ className: "cedros-admin__input",
373
+ placeholder: t ? "Enter new key to replace" : e.placeholder,
374
+ value: I[e.id],
375
+ onChange: (i) => F((a) => ({ ...a, [e.id]: i.target.value })),
376
+ onBlur: () => {
377
+ I[e.id].trim() && z(e.id);
378
+ },
379
+ style: { flex: 1 }
380
+ }
381
+ ),
382
+ /* @__PURE__ */ n(
383
+ "button",
384
+ {
385
+ type: "button",
386
+ className: "cedros-admin__button cedros-admin__button--ghost",
387
+ onClick: () => G((i) => ({ ...i, [e.id]: !i[e.id] })),
388
+ title: x[e.id] ? "Hide key" : "Show key",
389
+ style: { padding: "0.5rem" },
390
+ children: x[e.id] ? w.eyeOff : w.eye
391
+ }
392
+ ),
393
+ t && /* @__PURE__ */ n(
394
+ "button",
395
+ {
396
+ type: "button",
397
+ className: "cedros-admin__button cedros-admin__button--ghost cedros-admin__button--danger",
398
+ onClick: () => j(e.id),
399
+ disabled: p,
400
+ title: "Remove API key",
401
+ style: { padding: "0.5rem" },
402
+ children: w.trash
403
+ }
404
+ )
405
+ ] }) })
406
+ ]
407
+ },
408
+ e.id
409
+ );
410
+ }) })
411
+ ] }),
412
+ y === "assignments" && /* @__PURE__ */ r("div", { className: "cedros-admin__section", style: { marginTop: "1rem" }, children: [
413
+ /* @__PURE__ */ n("div", { className: "cedros-admin__section-header", children: /* @__PURE__ */ n("h3", { className: "cedros-admin__section-title", children: "Model Assignments" }) }),
414
+ /* @__PURE__ */ n("p", { style: { marginBottom: "1.5rem", opacity: 0.7, fontSize: 14 }, children: "Assign AI models to specific tasks. Models require their provider's API key to be configured." }),
415
+ /* @__PURE__ */ n("div", { style: { display: "flex", flexDirection: "column", gap: "1rem" }, children: h.taskAssignments.map((e) => {
416
+ const s = $.find((i) => i.task === e.task), t = E.find((i) => i.id === e.assignedModel);
417
+ return /* @__PURE__ */ r(
418
+ "div",
419
+ {
420
+ style: {
421
+ padding: "1rem",
422
+ border: "1px solid var(--cedros-admin-border)",
423
+ borderRadius: 8
424
+ },
425
+ children: [
426
+ /* @__PURE__ */ r("div", { style: { marginBottom: "0.75rem" }, children: [
427
+ /* @__PURE__ */ n("div", { style: { fontWeight: 600 }, children: s?.label ?? e.task }),
428
+ /* @__PURE__ */ n("div", { style: { fontSize: 13, opacity: 0.7, marginTop: 2 }, children: s?.description })
429
+ ] }),
430
+ /* @__PURE__ */ r("div", { style: { display: "flex", alignItems: "center", gap: "0.75rem" }, children: [
431
+ /* @__PURE__ */ n(
432
+ Y,
433
+ {
434
+ value: e.assignedModel,
435
+ onChange: (i) => W(e.task, i),
436
+ options: B,
437
+ label: "",
438
+ disabled: p,
439
+ style: { flex: 1, maxWidth: 280 }
440
+ }
441
+ ),
442
+ t && t.provider && /* @__PURE__ */ n(
443
+ "span",
444
+ {
445
+ className: `cedros-admin__badge ${P(t.id) ? "cedros-admin__badge--success" : "cedros-admin__badge--warning"}`,
446
+ children: P(t.id) ? "Ready" : "Missing API Key"
447
+ }
448
+ )
449
+ ] })
450
+ ]
451
+ },
452
+ e.task
453
+ );
454
+ }) })
455
+ ] }),
456
+ y === "prompts" && /* @__PURE__ */ r("div", { className: "cedros-admin__section", style: { marginTop: "1rem" }, children: [
457
+ /* @__PURE__ */ n("div", { className: "cedros-admin__section-header", children: /* @__PURE__ */ n("h3", { className: "cedros-admin__section-title", children: "System Prompts" }) }),
458
+ /* @__PURE__ */ n("p", { style: { marginBottom: "1.5rem", opacity: 0.7, fontSize: 14 }, children: "Configure the default system prompts for each AI task. These prompts guide the AI's behavior and responses." }),
459
+ /* @__PURE__ */ n("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" }, children: h.taskAssignments.map((e) => {
460
+ const s = $.find((t) => t.task === e.task);
461
+ return /* @__PURE__ */ n(
462
+ M,
463
+ {
464
+ task: e.task,
465
+ label: s?.label ?? e.task,
466
+ description: s?.description ?? "",
467
+ initialPrompt: e.systemPrompt ?? "",
468
+ onSave: L
469
+ },
470
+ e.task
471
+ );
472
+ }) })
473
+ ] })
474
+ ] });
475
+ }
476
+ function M({
477
+ task: o,
478
+ label: d,
479
+ description: c,
480
+ initialPrompt: y,
481
+ onSave: _
482
+ }) {
483
+ const [h, g] = u(y), [N, b] = u("idle"), p = S(null), l = S(null), k = S(!0);
484
+ return T(() => {
485
+ if (k.current) {
486
+ k.current = !1;
487
+ return;
488
+ }
489
+ return p.current && clearTimeout(p.current), l.current && clearTimeout(l.current), b("pending"), p.current = setTimeout(async () => {
490
+ b("saving");
491
+ try {
492
+ await _(o, h), b("saved"), l.current = setTimeout(() => b("idle"), 2e3);
493
+ } catch {
494
+ b("error");
495
+ }
496
+ }, 1500), () => {
497
+ p.current && clearTimeout(p.current);
498
+ };
499
+ }, [h, o, _]), T(() => () => {
500
+ p.current && clearTimeout(p.current), l.current && clearTimeout(l.current);
501
+ }, []), /* @__PURE__ */ r(
502
+ "div",
503
+ {
504
+ style: {
505
+ padding: "1rem",
506
+ border: "1px solid var(--cedros-admin-border)",
507
+ borderRadius: 8
508
+ },
509
+ children: [
510
+ /* @__PURE__ */ r("div", { style: { marginBottom: "0.75rem", display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: [
511
+ /* @__PURE__ */ r("div", { children: [
512
+ /* @__PURE__ */ n("div", { style: { fontWeight: 600 }, children: d }),
513
+ /* @__PURE__ */ n("div", { style: { fontSize: 13, opacity: 0.7, marginTop: 2 }, children: c })
514
+ ] }),
515
+ /* @__PURE__ */ n(X, { status: N })
516
+ ] }),
517
+ /* @__PURE__ */ n(
518
+ "textarea",
519
+ {
520
+ className: "cedros-admin__input",
521
+ value: h,
522
+ onChange: (f) => g(f.target.value),
523
+ placeholder: "Enter system prompt...",
524
+ rows: 4,
525
+ style: {
526
+ width: "100%",
527
+ resize: "vertical",
528
+ fontFamily: "inherit",
529
+ minHeight: 100
530
+ }
531
+ }
532
+ )
533
+ ]
534
+ }
535
+ );
536
+ }
537
+ export {
538
+ ee as AISettingsSection
539
+ };
@@ -0,0 +1,51 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),a=require("react"),b=require("./index-2N_CMVAv.js"),z=require("./AutosaveIndicator-BQkm3cn8.js"),w=[{id:"not_set",label:"Disabled",provider:null},{id:"gemini-2.5-flash",label:"Gemini 2.5 Flash",provider:"gemini"},{id:"gemini-2.5-pro",label:"Gemini 2.5 Pro",provider:"gemini"},{id:"openai-4o",label:"OpenAI 4o",provider:"openai"},{id:"openai-5.1",label:"OpenAI 5.1",provider:"openai"},{id:"openai-5.2",label:"OpenAI 5.2",provider:"openai"}],P=[{task:"site_chat",label:"Site Chat",description:"The conversational model that crafts responses to customer messages",defaultPrompt:`You are a friendly and helpful shopping assistant for our store. Your role is to:
2
+
3
+ - Help customers find products that match their needs
4
+ - Answer questions about products, shipping, returns, and store policies
5
+ - Provide personalized recommendations based on customer preferences
6
+ - Use the Product Searcher tool when customers are looking for specific items
7
+
8
+ Guidelines:
9
+ - Be warm, conversational, and concise
10
+ - Stay focused on helping with shopping-related questions
11
+ - If you don't know something specific about a product, say so honestly
12
+ - Never make up product details, prices, or availability
13
+ - For complex issues (order problems, refunds), direct customers to contact support`},{task:"product_searcher",label:"Product Searcher",description:"Tool used by Site Chat to find products based on customer queries",defaultPrompt:`You are a product search assistant. Given a customer's query, extract relevant search parameters to find matching products.
14
+
15
+ Extract the following when present:
16
+ - Keywords: Main search terms
17
+ - Category: Product category or type
18
+ - Price range: Min/max price if mentioned
19
+ - Attributes: Color, size, material, brand, or other specifications
20
+ - Sort preference: Price, popularity, newest, etc.
21
+
22
+ Return structured search parameters. Be liberal in interpretation - if a customer says "something for my mom's birthday under $50" extract: keywords=gift, price_max=50, occasion=birthday.
23
+
24
+ Do not make assumptions about specific products. Focus only on extracting search intent.`},{task:"related_product_finder",label:"Related Product Finder",description:"AI-powered recommendations for related products on product pages",defaultPrompt:`You are a product recommendation engine. Given a product, suggest related items that customers might also be interested in.
25
+
26
+ Consider these recommendation types:
27
+ - Complementary items: Products that go well together (e.g., phone case for a phone)
28
+ - Similar alternatives: Products in the same category with different features or price points
29
+ - Frequently bought together: Items commonly purchased as a set
30
+ - Upsells: Premium versions or upgrades
31
+
32
+ Guidelines:
33
+ - Prioritize relevance over variety
34
+ - Consider the product's category, price range, and use case
35
+ - Return product IDs or search criteria for related items
36
+ - Aim for 4-8 recommendations with a mix of types`},{task:"product_detail_assistant",label:"Product Detail Assistant",description:"Admin tool to generate product descriptions, suggest tags, and fill out product details",defaultPrompt:`You are a product copywriting assistant helping store administrators create compelling product listings.
37
+
38
+ You can help with:
39
+ - Writing engaging product descriptions that highlight key features and benefits
40
+ - Suggesting relevant tags and categories for better discoverability
41
+ - Creating SEO-friendly titles and meta descriptions
42
+ - Generating bullet points for key features
43
+ - Writing size guides or care instructions when applicable
44
+
45
+ Guidelines:
46
+ - Match the store's brand voice (ask if unclear)
47
+ - Focus on benefits, not just features
48
+ - Use sensory language when appropriate
49
+ - Keep descriptions scannable with short paragraphs
50
+ - Avoid superlatives and unverifiable claims
51
+ - Include relevant keywords naturally for SEO`}],q=[{id:"gemini",label:"Google Gemini API",placeholder:"AIza..."},{id:"openai",label:"OpenAI API",placeholder:"sk-..."}],N={apiKeys:[{provider:"gemini",isConfigured:!1},{provider:"openai",isConfigured:!1}],taskAssignments:P.map(o=>({task:o.task,label:o.label,description:o.description,assignedModel:"not_set",systemPrompt:o.defaultPrompt}))};function W({serverUrl:o,apiKey:d,authManager:c}){const[h,_]=a.useState("api-keys"),[f,y]=a.useState(N),[j,g]=a.useState(!0),[u,l]=a.useState(!1),[v,p]=a.useState(null),[C,x]=a.useState(!1),[E,$]=a.useState(null),m=a.useRef(null),[A,T]=a.useState({gemini:"",openai:""}),[S,R]=a.useState({gemini:!1,openai:!1}),I=a.useCallback(async()=>{try{let e;if(c?.isAuthenticated())e=await c.fetchWithAuth("/admin/config/ai");else{const i={"Content-Type":"application/json"};d&&(i["X-API-Key"]=d);const s=await fetch(`${o}/admin/config/ai`,{headers:i});if(!s.ok)throw new Error(`Failed to fetch: ${s.status}`);e=await s.json()}e.settings&&y(e.settings)}catch{y(N),$("Could not load saved AI settings. Showing defaults.")}finally{g(!1)}},[o,d,c]);a.useEffect(()=>{I()},[I]);const F=a.useCallback(async e=>{const i=A[e];if(i.trim()){l(!0),p(null);try{const s={provider:e,apiKey:i};if(c?.isAuthenticated())await c.fetchWithAuth("/admin/config/ai/api-key",{method:"PUT",body:JSON.stringify(s)});else{const n={"Content-Type":"application/json"};d&&(n["X-API-Key"]=d);const r=await fetch(`${o}/admin/config/ai/api-key`,{method:"PUT",headers:n,body:JSON.stringify(s)});if(!r.ok)throw new Error(`Failed to save: ${r.status}`)}y(n=>({...n,apiKeys:n.apiKeys.map(r=>r.provider===e?{...r,isConfigured:!0,maskedKey:`${i.slice(0,4)}...${i.slice(-4)}`,updatedAt:new Date().toISOString()}:r)})),T(n=>({...n,[e]:""})),x(!0),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>x(!1),3e3)}catch(s){p(s instanceof Error?s.message:"Failed to save API key")}finally{l(!1)}}},[A,o,d,c]),O=a.useCallback(async e=>{if(confirm(`Are you sure you want to delete the ${e==="gemini"?"Google Gemini":"OpenAI"} API key?`)){l(!0),p(null);try{if(c?.isAuthenticated())await c.fetchWithAuth(`/admin/config/ai/api-key/${e}`,{method:"DELETE"});else{const i={"Content-Type":"application/json"};d&&(i["X-API-Key"]=d);const s=await fetch(`${o}/admin/config/ai/api-key/${e}`,{method:"DELETE",headers:i});if(!s.ok)throw new Error(`Failed to delete: ${s.status}`)}y(i=>({...i,apiKeys:i.apiKeys.map(s=>s.provider===e?{provider:e,isConfigured:!1}:s)}))}catch(i){p(i instanceof Error?i.message:"Failed to delete API key")}finally{l(!1)}}},[o,d,c]),D=a.useCallback(async(e,i)=>{l(!0),p(null);try{const s={task:e,model:i};if(c?.isAuthenticated())await c.fetchWithAuth("/admin/config/ai/assignment",{method:"PUT",body:JSON.stringify(s)});else{const n={"Content-Type":"application/json"};d&&(n["X-API-Key"]=d);const r=await fetch(`${o}/admin/config/ai/assignment`,{method:"PUT",headers:n,body:JSON.stringify(s)});if(!r.ok)throw new Error(`Failed to save: ${r.status}`)}y(n=>({...n,taskAssignments:n.taskAssignments.map(r=>r.task===e?{...r,assignedModel:i}:r)})),x(!0),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>x(!1),3e3)}catch(s){p(s instanceof Error?s.message:"Failed to save assignment")}finally{l(!1)}},[o,d,c]),k=a.useCallback(e=>{if(e==="not_set")return!0;const i=w.find(n=>n.id===e);return i?.provider?f.apiKeys.find(n=>n.provider===i.provider)?.isConfigured??!1:!0},[f.apiKeys]),K=a.useMemo(()=>w.map(e=>{const i=k(e.id);return{value:e.id,label:i?e.label:`${e.label} (API key required)`,disabled:!i}}),[k]),G=a.useCallback(async(e,i)=>{l(!0),p(null);try{const s={task:e,systemPrompt:i};if(c?.isAuthenticated())await c.fetchWithAuth("/admin/config/ai/prompt",{method:"PUT",body:JSON.stringify(s)});else{const n={"Content-Type":"application/json"};d&&(n["X-API-Key"]=d);const r=await fetch(`${o}/admin/config/ai/prompt`,{method:"PUT",headers:n,body:JSON.stringify(s)});if(!r.ok)throw new Error(`Failed to save: ${r.status}`)}y(n=>({...n,taskAssignments:n.taskAssignments.map(r=>r.task===e?{...r,systemPrompt:i}:r)})),x(!0),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>x(!1),3e3)}catch(s){p(s instanceof Error?s.message:"Failed to save prompt")}finally{l(!1)}},[o,d,c]);return a.useEffect(()=>()=>{m.current&&clearTimeout(m.current)},[]),j?t.jsx("div",{className:"cedros-admin__section",children:t.jsxs("div",{className:"cedros-admin__loading",children:[b.Icons.loading," Loading AI settings..."]})}):t.jsxs("div",{className:"cedros-admin__ai-settings",children:[t.jsxs("div",{className:"cedros-admin__page-header",children:[t.jsx("h2",{className:"cedros-admin__page-title",children:"Store AI"}),t.jsx("p",{className:"cedros-admin__page-description",children:"Configure AI providers, model assignments, and system prompts."})]}),t.jsxs("div",{className:"cedros-admin__tabs cedros-admin__tabs--line",children:[t.jsx("button",{type:"button",className:`cedros-admin__tab ${h==="api-keys"?"cedros-admin__tab--active":""}`,onClick:()=>_("api-keys"),children:"API Keys"}),t.jsx("button",{type:"button",className:`cedros-admin__tab ${h==="assignments"?"cedros-admin__tab--active":""}`,onClick:()=>_("assignments"),children:"Model Assignments"}),t.jsx("button",{type:"button",className:`cedros-admin__tab ${h==="prompts"?"cedros-admin__tab--active":""}`,onClick:()=>_("prompts"),children:"Prompts"})]}),v&&t.jsx("div",{className:"cedros-admin__error-banner",style:{marginTop:"1rem"},children:v}),t.jsx(b.ErrorBanner,{message:E,onRetry:I}),C&&t.jsxs("div",{className:"cedros-admin__success-banner",style:{marginTop:"1rem"},children:[b.Icons.check," Settings saved successfully"]}),h==="api-keys"&&t.jsxs("div",{className:"cedros-admin__section",style:{marginTop:"1rem"},children:[t.jsx("div",{className:"cedros-admin__section-header",children:t.jsx("h3",{className:"cedros-admin__section-title",children:"API Keys"})}),t.jsx("p",{style:{marginBottom:"1.5rem",opacity:.7,fontSize:14},children:"Configure API keys for AI providers. Keys are stored securely and never exposed."}),t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"1.5rem"},children:q.map(e=>{const i=f.apiKeys.find(n=>n.provider===e.id),s=i?.isConfigured??!1;return t.jsxs("div",{className:"cedros-admin__api-key-card",style:{padding:"1rem",border:"1px solid var(--cedros-admin-border)",borderRadius:8},children:[t.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"0.75rem"},children:[t.jsxs("div",{children:[t.jsx("div",{style:{fontWeight:600},children:e.label}),s&&i?.maskedKey&&t.jsxs("div",{style:{fontSize:12,opacity:.6,marginTop:2},children:["Current key: ",i.maskedKey,i.updatedAt&&t.jsxs("span",{children:[" (updated ",new Date(i.updatedAt).toLocaleDateString(),")"]})]})]}),t.jsx("span",{className:`cedros-admin__badge ${s?"cedros-admin__badge--success":"cedros-admin__badge--muted"}`,children:s?"Configured":"Not Set"})]}),t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"0.75rem"},children:t.jsxs("div",{style:{display:"flex",gap:"0.5rem",alignItems:"center"},children:[t.jsx("input",{type:S[e.id]?"text":"password",className:"cedros-admin__input",placeholder:s?"Enter new key to replace":e.placeholder,value:A[e.id],onChange:n=>T(r=>({...r,[e.id]:n.target.value})),onBlur:()=>{A[e.id].trim()&&F(e.id)},style:{flex:1}}),t.jsx("button",{type:"button",className:"cedros-admin__button cedros-admin__button--ghost",onClick:()=>R(n=>({...n,[e.id]:!n[e.id]})),title:S[e.id]?"Hide key":"Show key",style:{padding:"0.5rem"},children:S[e.id]?b.Icons.eyeOff:b.Icons.eye}),s&&t.jsx("button",{type:"button",className:"cedros-admin__button cedros-admin__button--ghost cedros-admin__button--danger",onClick:()=>O(e.id),disabled:u,title:"Remove API key",style:{padding:"0.5rem"},children:b.Icons.trash})]})})]},e.id)})})]}),h==="assignments"&&t.jsxs("div",{className:"cedros-admin__section",style:{marginTop:"1rem"},children:[t.jsx("div",{className:"cedros-admin__section-header",children:t.jsx("h3",{className:"cedros-admin__section-title",children:"Model Assignments"})}),t.jsx("p",{style:{marginBottom:"1.5rem",opacity:.7,fontSize:14},children:"Assign AI models to specific tasks. Models require their provider's API key to be configured."}),t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:f.taskAssignments.map(e=>{const i=P.find(n=>n.task===e.task),s=w.find(n=>n.id===e.assignedModel);return t.jsxs("div",{style:{padding:"1rem",border:"1px solid var(--cedros-admin-border)",borderRadius:8},children:[t.jsxs("div",{style:{marginBottom:"0.75rem"},children:[t.jsx("div",{style:{fontWeight:600},children:i?.label??e.task}),t.jsx("div",{style:{fontSize:13,opacity:.7,marginTop:2},children:i?.description})]}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.75rem"},children:[t.jsx(b.FormDropdown,{value:e.assignedModel,onChange:n=>D(e.task,n),options:K,label:"",disabled:u,style:{flex:1,maxWidth:280}}),s&&s.provider&&t.jsx("span",{className:`cedros-admin__badge ${k(s.id)?"cedros-admin__badge--success":"cedros-admin__badge--warning"}`,children:k(s.id)?"Ready":"Missing API Key"})]})]},e.task)})})]}),h==="prompts"&&t.jsxs("div",{className:"cedros-admin__section",style:{marginTop:"1rem"},children:[t.jsx("div",{className:"cedros-admin__section-header",children:t.jsx("h3",{className:"cedros-admin__section-title",children:"System Prompts"})}),t.jsx("p",{style:{marginBottom:"1.5rem",opacity:.7,fontSize:14},children:"Configure the default system prompts for each AI task. These prompts guide the AI's behavior and responses."}),t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"1.5rem"},children:f.taskAssignments.map(e=>{const i=P.find(s=>s.task===e.task);return t.jsx(B,{task:e.task,label:i?.label??e.task,description:i?.description??"",initialPrompt:e.systemPrompt??"",onSave:G},e.task)})})]})]})}function B({task:o,label:d,description:c,initialPrompt:h,onSave:_}){const[f,y]=a.useState(h),[j,g]=a.useState("idle"),u=a.useRef(null),l=a.useRef(null),v=a.useRef(!0);return a.useEffect(()=>{if(v.current){v.current=!1;return}return u.current&&clearTimeout(u.current),l.current&&clearTimeout(l.current),g("pending"),u.current=setTimeout(async()=>{g("saving");try{await _(o,f),g("saved"),l.current=setTimeout(()=>g("idle"),2e3)}catch{g("error")}},1500),()=>{u.current&&clearTimeout(u.current)}},[f,o,_]),a.useEffect(()=>()=>{u.current&&clearTimeout(u.current),l.current&&clearTimeout(l.current)},[]),t.jsxs("div",{style:{padding:"1rem",border:"1px solid var(--cedros-admin-border)",borderRadius:8},children:[t.jsxs("div",{style:{marginBottom:"0.75rem",display:"flex",justifyContent:"space-between",alignItems:"flex-start"},children:[t.jsxs("div",{children:[t.jsx("div",{style:{fontWeight:600},children:d}),t.jsx("div",{style:{fontSize:13,opacity:.7,marginTop:2},children:c})]}),t.jsx(z.AutosaveIndicator,{status:j})]}),t.jsx("textarea",{className:"cedros-admin__input",value:f,onChange:p=>y(p.target.value),placeholder:"Enter system prompt...",rows:4,style:{width:"100%",resize:"vertical",fontFamily:"inherit",minHeight:100}})]})}exports.AISettingsSection=W;
@@ -0,0 +1,35 @@
1
+ import { jsxs as n, jsx as r, Fragment as i } from "react/jsx-runtime";
2
+ import { $ as d } from "./index-C1hbnxn0.mjs";
3
+ function l({ status: e, error: a }) {
4
+ return e === "idle" ? null : /* @__PURE__ */ n(
5
+ "span",
6
+ {
7
+ className: `cedros-admin__autosave-indicator cedros-admin__autosave-indicator--${e}`,
8
+ style: {
9
+ display: "inline-flex",
10
+ alignItems: "center",
11
+ gap: "0.375rem",
12
+ fontSize: "0.8125rem",
13
+ color: e === "error" ? "var(--cedros-admin-error, #ef4444)" : "var(--cedros-admin-text-muted, #64748b)"
14
+ },
15
+ children: [
16
+ e === "pending" && /* @__PURE__ */ r("span", { style: { opacity: 0.7 }, children: "Unsaved changes" }),
17
+ e === "saving" && /* @__PURE__ */ n(i, { children: [
18
+ d.loading,
19
+ /* @__PURE__ */ r("span", { children: "Saving..." })
20
+ ] }),
21
+ e === "saved" && /* @__PURE__ */ n(i, { children: [
22
+ d.check,
23
+ /* @__PURE__ */ r("span", { style: { color: "var(--cedros-admin-success, #22c55e)" }, children: "Saved" })
24
+ ] }),
25
+ e === "error" && /* @__PURE__ */ n("span", { children: [
26
+ "Save failed",
27
+ a ? `: ${a}` : ""
28
+ ] })
29
+ ]
30
+ }
31
+ );
32
+ }
33
+ export {
34
+ l as A
35
+ };
@@ -0,0 +1 @@
1
+ "use strict";const e=require("react/jsx-runtime"),i=require("./index-2N_CMVAv.js");function a({status:n,error:r}){return n==="idle"?null:e.jsxs("span",{className:`cedros-admin__autosave-indicator cedros-admin__autosave-indicator--${n}`,style:{display:"inline-flex",alignItems:"center",gap:"0.375rem",fontSize:"0.8125rem",color:n==="error"?"var(--cedros-admin-error, #ef4444)":"var(--cedros-admin-text-muted, #64748b)"},children:[n==="pending"&&e.jsx("span",{style:{opacity:.7},children:"Unsaved changes"}),n==="saving"&&e.jsxs(e.Fragment,{children:[i.Icons.loading,e.jsx("span",{children:"Saving..."})]}),n==="saved"&&e.jsxs(e.Fragment,{children:[i.Icons.check,e.jsx("span",{style:{color:"var(--cedros-admin-success, #22c55e)"},children:"Saved"})]}),n==="error"&&e.jsxs("span",{children:["Save failed",r?`: ${r}`:""]})]})}exports.AutosaveIndicator=a;