strapi-content-embeddings 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/_chunks/en-B4KWt_jN.js +0 -1
  2. package/dist/_chunks/en-Byx4XI2L.mjs +0 -1
  3. package/dist/admin/index.js +686 -4
  4. package/dist/admin/index.mjs +683 -4
  5. package/dist/server/index.js +293 -287
  6. package/dist/server/index.mjs +293 -287
  7. package/dist/server/src/index.d.ts +5 -0
  8. package/dist/server/src/mcp/schemas/index.d.ts +3 -0
  9. package/dist/server/src/mcp/tools/create-embedding.d.ts +3 -4
  10. package/dist/server/src/mcp/tools/get-embedding.d.ts +3 -3
  11. package/dist/server/src/mcp/tools/index.d.ts +1 -0
  12. package/dist/server/src/mcp/tools/list-embeddings.d.ts +3 -3
  13. package/dist/server/src/mcp/tools/rag-query.d.ts +3 -3
  14. package/dist/server/src/mcp/tools/semantic-search.d.ts +3 -3
  15. package/dist/server/src/services/ai-tools.d.ts +13 -0
  16. package/dist/server/src/services/embeddings.d.ts +2 -2
  17. package/dist/server/src/services/index.d.ts +5 -0
  18. package/dist/server/src/tools/create-embedding.d.ts +9 -0
  19. package/dist/server/src/tools/get-embedding.d.ts +8 -0
  20. package/dist/server/src/tools/index.d.ts +14 -0
  21. package/dist/server/src/tools/list-embeddings.d.ts +8 -0
  22. package/dist/server/src/tools/rag-query.d.ts +8 -0
  23. package/dist/server/src/tools/semantic-search.d.ts +8 -0
  24. package/dist/server/src/tools/types.d.ts +14 -0
  25. package/package.json +1 -1
  26. package/dist/_chunks/App-ByRBbkZn.js +0 -1600
  27. package/dist/_chunks/App-ByRBbkZn.js.map +0 -1
  28. package/dist/_chunks/App-MjsTrWRS.mjs +0 -1596
  29. package/dist/_chunks/App-MjsTrWRS.mjs.map +0 -1
  30. package/dist/_chunks/en-B4KWt_jN.js.map +0 -1
  31. package/dist/_chunks/en-Byx4XI2L.mjs.map +0 -1
  32. package/dist/_chunks/index-TWbcT-zJ.js +0 -785
  33. package/dist/_chunks/index-TWbcT-zJ.js.map +0 -1
  34. package/dist/_chunks/index-ifqYByO5.mjs +0 -783
  35. package/dist/_chunks/index-ifqYByO5.mjs.map +0 -1
  36. package/dist/admin/index.js.map +0 -1
  37. package/dist/admin/index.mjs.map +0 -1
  38. package/dist/server/index.js.map +0 -1
  39. package/dist/server/index.mjs.map +0 -1
@@ -2,4 +2,3 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const en = {};
4
4
  exports.default = en;
5
- //# sourceMappingURL=en-B4KWt_jN.js.map
@@ -2,4 +2,3 @@ const en = {};
2
2
  export {
3
3
  en as default
4
4
  };
5
- //# sourceMappingURL=en-Byx4XI2L.mjs.map
@@ -1,5 +1,687 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-TWbcT-zJ.js");
3
- require("react/jsx-runtime");
4
- module.exports = index.index;
5
- //# sourceMappingURL=index.js.map
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const react = require("react");
4
+ const designSystem = require("@strapi/design-system");
5
+ const reactRouterDom = require("react-router-dom");
6
+ const styled = require("styled-components");
7
+ const qs = require("qs");
8
+ const admin = require("@strapi/strapi/admin");
9
+ const icons = require("@strapi/icons");
10
+ const editor = require("@mdxeditor/editor");
11
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
13
+ const qs__default = /* @__PURE__ */ _interopDefault(qs);
14
+ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
15
+ const v = glob[path];
16
+ if (v) {
17
+ return typeof v === "function" ? v() : Promise.resolve(v);
18
+ }
19
+ return new Promise((_, reject) => {
20
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
21
+ reject.bind(
22
+ null,
23
+ new Error(
24
+ "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
25
+ )
26
+ )
27
+ );
28
+ });
29
+ };
30
+ const PLUGIN_ID = "strapi-content-embeddings";
31
+ const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
32
+ const Initializer = ({ setPlugin }) => {
33
+ const ref = react.useRef(setPlugin);
34
+ react.useEffect(() => {
35
+ ref.current(PLUGIN_ID);
36
+ }, []);
37
+ return null;
38
+ };
39
+ const MDXEditorStyles = styled.createGlobalStyle`
40
+ /* MDXEditor CSS Variables */
41
+ :root {
42
+ --mdx-spacing-0_5: 0.125rem;
43
+ --mdx-spacing-1: 0.25rem;
44
+ --mdx-spacing-1_5: 0.375rem;
45
+ --mdx-spacing-2: 0.5rem;
46
+ --mdx-spacing-3: 0.75rem;
47
+ --mdx-spacing-4: 1rem;
48
+ --mdx-spacing-36: 9rem;
49
+ --mdx-radius-base: 0.25rem;
50
+ --mdx-radius-medium: 0.375rem;
51
+ --mdx-text-sm: 0.875rem;
52
+ --mdx-baseBg: #f6f6f9;
53
+ --mdx-baseBgActive: #e8e8ec;
54
+ --mdx-basePageBg: #ffffff;
55
+ --mdx-baseBorder: #dcdce4;
56
+ --mdx-baseBorderHover: #b9bbc6;
57
+ --mdx-baseBase: #e0e1e6;
58
+ --mdx-baseTextContrast: #1c2024;
59
+ --mdx-accentText: #4945ff;
60
+ }
61
+
62
+ /* Toolbar Root - critical for horizontal layout */
63
+ [class*="_toolbarRoot"] {
64
+ z-index: 2;
65
+ display: flex !important;
66
+ flex-direction: row !important;
67
+ flex-wrap: wrap !important;
68
+ gap: var(--mdx-spacing-1);
69
+ border-radius: var(--mdx-radius-medium);
70
+ padding: var(--mdx-spacing-1_5);
71
+ align-items: center !important;
72
+ overflow-x: auto;
73
+ position: sticky;
74
+ top: 0;
75
+ background-color: var(--mdx-baseBg) !important;
76
+ border-bottom: 1px solid var(--mdx-baseBorder);
77
+ width: 100%;
78
+ }
79
+
80
+ [class*="_toolbarRoot"] div[role='separator'] {
81
+ margin: var(--mdx-spacing-2) var(--mdx-spacing-1);
82
+ border-left: 1px solid var(--mdx-baseBorder);
83
+ border-right: 1px solid var(--mdx-baseBase);
84
+ height: var(--mdx-spacing-4);
85
+ }
86
+
87
+ [class*="_toolbarRoot"] svg {
88
+ color: var(--mdx-baseTextContrast);
89
+ display: block;
90
+ }
91
+
92
+ /* Toolbar button groups */
93
+ [class*="_toolbarGroupOfGroups"] {
94
+ display: flex;
95
+ margin: 0 var(--mdx-spacing-1);
96
+ }
97
+
98
+ [class*="_toolbarToggleSingleGroup"] {
99
+ display: flex;
100
+ align-items: center;
101
+ white-space: nowrap;
102
+ }
103
+
104
+ /* Toolbar buttons and toggle items */
105
+ [class*="_toolbarToggleItem"],
106
+ [class*="_toolbarButton"] {
107
+ border: 0;
108
+ background-color: transparent;
109
+ font-size: inherit;
110
+ appearance: none;
111
+ box-sizing: border-box;
112
+ cursor: pointer;
113
+ padding: var(--mdx-spacing-0_5);
114
+ border-radius: var(--mdx-radius-base);
115
+ }
116
+
117
+ [class*="_toolbarToggleItem"]:hover,
118
+ [class*="_toolbarButton"]:hover {
119
+ background-color: var(--mdx-baseBgActive);
120
+ }
121
+
122
+ [class*="_toolbarToggleItem"][data-state='on'],
123
+ [class*="_toolbarButton"][data-state='on'],
124
+ [class*="_toolbarToggleItem"]:active,
125
+ [class*="_toolbarButton"]:active {
126
+ color: var(--mdx-baseTextContrast);
127
+ background-color: var(--mdx-baseBgActive);
128
+ }
129
+
130
+ /* Block type select dropdown */
131
+ [class*="_toolbarNodeKindSelectTrigger"],
132
+ [class*="_selectTrigger"] {
133
+ border: 0;
134
+ display: flex;
135
+ color: inherit;
136
+ align-items: center;
137
+ width: var(--mdx-spacing-36);
138
+ padding: var(--mdx-spacing-0_5) var(--mdx-spacing-1);
139
+ padding-inline-start: var(--mdx-spacing-2);
140
+ border-radius: var(--mdx-radius-medium);
141
+ white-space: nowrap;
142
+ font-size: var(--mdx-text-sm);
143
+ background-color: var(--mdx-basePageBg);
144
+ margin: 0 var(--mdx-spacing-1);
145
+ cursor: pointer;
146
+ }
147
+
148
+ /* Dropdown containers */
149
+ [class*="_toolbarNodeKindSelectContainer"],
150
+ [class*="_selectContainer"] {
151
+ filter: drop-shadow(0 2px 2px rgb(0 0 0 / 0.2));
152
+ z-index: 100;
153
+ width: var(--mdx-spacing-36);
154
+ border-radius: var(--mdx-radius-base);
155
+ background-color: var(--mdx-basePageBg);
156
+ font-size: var(--mdx-text-sm);
157
+ }
158
+
159
+ /* Select items */
160
+ [class*="_toolbarNodeKindSelectItem"],
161
+ [class*="_selectItem"] {
162
+ cursor: pointer;
163
+ display: flex;
164
+ padding: var(--mdx-spacing-2);
165
+ }
166
+
167
+ [class*="_toolbarNodeKindSelectItem"][data-highlighted],
168
+ [class*="_selectItem"][data-highlighted],
169
+ [class*="_toolbarNodeKindSelectItem"][data-state='checked'],
170
+ [class*="_selectItem"][data-state='checked'] {
171
+ background-color: var(--mdx-baseBg);
172
+ outline: none;
173
+ }
174
+
175
+ /* Dropdown arrow */
176
+ [class*="_selectDropdownArrow"] {
177
+ margin-left: auto;
178
+ display: flex;
179
+ align-items: center;
180
+ }
181
+
182
+ /* Content editable area */
183
+ [class*="_contentEditable"] {
184
+ box-sizing: border-box;
185
+ width: 100%;
186
+ color: var(--mdx-baseTextContrast);
187
+ padding: var(--mdx-spacing-3);
188
+ min-height: 200px;
189
+ outline: none;
190
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
191
+ font-size: 14px;
192
+ line-height: 1.6;
193
+ }
194
+
195
+ [class*="_contentEditable"]:focus {
196
+ outline: none;
197
+ }
198
+
199
+ /* Placeholder positioning - ensure it's at the top */
200
+ [class*="_contentEditable"] {
201
+ position: relative;
202
+ }
203
+
204
+ [class*="_contentEditable"][data-placeholder]::before {
205
+ position: absolute;
206
+ top: var(--mdx-spacing-3);
207
+ left: var(--mdx-spacing-3);
208
+ color: #a5a5ba;
209
+ pointer-events: none;
210
+ }
211
+
212
+ /* MDXEditor/Lexical placeholder styles */
213
+ [class*="_placeholder"],
214
+ [class*="ContentEditable__placeholder"],
215
+ [class*="editor-placeholder"] {
216
+ position: absolute !important;
217
+ top: var(--mdx-spacing-3) !important;
218
+ left: var(--mdx-spacing-3) !important;
219
+ color: #a5a5ba;
220
+ pointer-events: none;
221
+ overflow: hidden;
222
+ text-overflow: ellipsis;
223
+ user-select: none;
224
+ display: inline-block;
225
+ }
226
+
227
+ /* Editor root wrapper needs relative positioning for placeholder */
228
+ [class*="_rootContentEditableWrapper"],
229
+ [class*="_editorWrapper"] {
230
+ position: relative;
231
+ display: flex;
232
+ flex-direction: column;
233
+ }
234
+
235
+ /* Heading styles */
236
+ [class*="_contentEditable"] h1 {
237
+ font-size: 1.75rem;
238
+ font-weight: 600;
239
+ margin: 0 0 1rem;
240
+ }
241
+
242
+ [class*="_contentEditable"] h2 {
243
+ font-size: 1.5rem;
244
+ font-weight: 600;
245
+ margin: 1rem 0 0.75rem;
246
+ }
247
+
248
+ [class*="_contentEditable"] h3 {
249
+ font-size: 1.25rem;
250
+ font-weight: 600;
251
+ margin: 1rem 0 0.5rem;
252
+ }
253
+
254
+ /* Paragraph and list styles */
255
+ [class*="_contentEditable"] p {
256
+ margin: 0 0 1rem;
257
+ }
258
+
259
+ [class*="_contentEditable"] ul,
260
+ [class*="_contentEditable"] ol {
261
+ margin: 0 0 1rem;
262
+ padding-left: 1.5rem;
263
+ }
264
+
265
+ [class*="_contentEditable"] li {
266
+ margin: 0.25rem 0;
267
+ }
268
+
269
+ /* Code styles */
270
+ [class*="_contentEditable"] code {
271
+ background: #f0f0f5;
272
+ padding: 0.2em 0.4em;
273
+ border-radius: 3px;
274
+ font-family: "Monaco", "Menlo", monospace;
275
+ font-size: 0.9em;
276
+ }
277
+
278
+ [class*="_contentEditable"] pre {
279
+ background: #2d2d2d;
280
+ color: #f8f8f2;
281
+ padding: 1rem;
282
+ border-radius: 4px;
283
+ overflow-x: auto;
284
+ margin: 0 0 1rem;
285
+ }
286
+
287
+ [class*="_contentEditable"] pre code {
288
+ background: none;
289
+ padding: 0;
290
+ }
291
+
292
+ /* Blockquote */
293
+ [class*="_contentEditable"] blockquote {
294
+ border-left: 3px solid #dcdce4;
295
+ margin: 0 0 1rem;
296
+ padding-left: 1rem;
297
+ color: #666;
298
+ }
299
+
300
+ /* Links */
301
+ [class*="_contentEditable"] a {
302
+ color: #4945ff;
303
+ text-decoration: underline;
304
+ }
305
+
306
+ /* Horizontal rule */
307
+ [class*="_contentEditable"] hr {
308
+ border: none;
309
+ border-top: 1px solid #dcdce4;
310
+ margin: 1.5rem 0;
311
+ }
312
+
313
+ /* Editor root */
314
+ [class*="_editorRoot"] {
315
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
316
+ color: var(--mdx-baseTextContrast);
317
+ background: var(--mdx-basePageBg);
318
+ }
319
+
320
+ /* Link dialog */
321
+ [class*="_linkDialogPopoverContent"] {
322
+ display: flex;
323
+ flex-direction: column;
324
+ gap: var(--mdx-spacing-2);
325
+ padding: var(--mdx-spacing-3);
326
+ background-color: var(--mdx-basePageBg);
327
+ border-radius: var(--mdx-radius-medium);
328
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
329
+ z-index: 100;
330
+ }
331
+
332
+ [class*="_linkDialogInputWrapper"] {
333
+ display: flex;
334
+ gap: var(--mdx-spacing-1);
335
+ }
336
+
337
+ [class*="_linkDialogInputWrapper"] input {
338
+ flex: 1;
339
+ padding: var(--mdx-spacing-1) var(--mdx-spacing-2);
340
+ border: 1px solid var(--mdx-baseBorder);
341
+ border-radius: var(--mdx-radius-base);
342
+ font-size: var(--mdx-text-sm);
343
+ }
344
+
345
+ [class*="_linkDialogInputWrapper"] button {
346
+ padding: var(--mdx-spacing-1) var(--mdx-spacing-2);
347
+ background-color: var(--mdx-accentText);
348
+ color: white;
349
+ border: none;
350
+ border-radius: var(--mdx-radius-base);
351
+ cursor: pointer;
352
+ }
353
+
354
+ /* Popover positioning */
355
+ [data-radix-popper-content-wrapper] {
356
+ z-index: 100 !important;
357
+ }
358
+ `;
359
+ const EditorWrapper = styled__default.default(designSystem.Box)`
360
+ border: 1px solid ${({ $isFocused }) => $isFocused ? "#4945ff" : "#dcdce4"};
361
+ border-radius: 4px;
362
+ overflow: hidden;
363
+ background: #fff;
364
+ transition: border-color 0.2s, box-shadow 0.2s;
365
+ box-shadow: ${({ $isFocused }) => $isFocused ? "0 0 0 2px rgba(73, 69, 255, 0.2)" : "none"};
366
+ `;
367
+ function ToolbarContents() {
368
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
369
+ /* @__PURE__ */ jsxRuntime.jsx(editor.UndoRedo, {}),
370
+ /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
371
+ /* @__PURE__ */ jsxRuntime.jsx(editor.BlockTypeSelect, {}),
372
+ /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
373
+ /* @__PURE__ */ jsxRuntime.jsx(editor.BoldItalicUnderlineToggles, {}),
374
+ /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
375
+ /* @__PURE__ */ jsxRuntime.jsx(editor.CreateLink, {}),
376
+ /* @__PURE__ */ jsxRuntime.jsx(editor.Separator, {}),
377
+ /* @__PURE__ */ jsxRuntime.jsx(editor.ListsToggle, {})
378
+ ] });
379
+ }
380
+ function MarkdownEditor({ content, onChange, height = 300 }) {
381
+ const [isFocused, setIsFocused] = react.useState(false);
382
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
383
+ /* @__PURE__ */ jsxRuntime.jsx(MDXEditorStyles, {}),
384
+ /* @__PURE__ */ jsxRuntime.jsx(
385
+ EditorWrapper,
386
+ {
387
+ $isFocused: isFocused,
388
+ onFocus: () => setIsFocused(true),
389
+ onBlur: () => setIsFocused(false),
390
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: `${height}px` }, children: /* @__PURE__ */ jsxRuntime.jsx(
391
+ editor.MDXEditor,
392
+ {
393
+ markdown: content,
394
+ onChange,
395
+ placeholder: "Write your content here...",
396
+ plugins: [
397
+ editor.headingsPlugin(),
398
+ editor.listsPlugin(),
399
+ editor.quotePlugin(),
400
+ editor.thematicBreakPlugin(),
401
+ editor.linkPlugin(),
402
+ editor.linkDialogPlugin(),
403
+ editor.markdownShortcutPlugin(),
404
+ editor.toolbarPlugin({
405
+ toolbarContents: ToolbarContents
406
+ })
407
+ ]
408
+ }
409
+ ) })
410
+ }
411
+ )
412
+ ] });
413
+ }
414
+ const StyledTypography = styled__default.default(designSystem.Typography)`
415
+ display: block;
416
+ margin-top: 1rem;
417
+ margin-bottom: 0.5rem;
418
+ `;
419
+ const CHUNK_SIZE = 4e3;
420
+ function EmbeddingsModal() {
421
+ const { post, get } = admin.useFetchClient();
422
+ const { toggleNotification } = admin.useNotification();
423
+ const navigate = reactRouterDom.useNavigate();
424
+ const context = admin.unstable_useContentManagerContext();
425
+ const { form, id, slug, collectionType } = context;
426
+ const modifiedValues = form?.values || {};
427
+ const [isVisible, setIsVisible] = react.useState(false);
428
+ const [title, setTitle] = react.useState("");
429
+ const [content, setContent] = react.useState("");
430
+ const [fieldName, setFieldName] = react.useState("");
431
+ const [isLoading, setIsLoading] = react.useState(false);
432
+ const [isCheckingExisting, setIsCheckingExisting] = react.useState(true);
433
+ const [existingEmbedding, setExistingEmbedding] = react.useState(null);
434
+ react.useEffect(() => {
435
+ async function checkExistingEmbedding() {
436
+ if (!id || !slug) {
437
+ setIsCheckingExisting(false);
438
+ return;
439
+ }
440
+ try {
441
+ const query = qs__default.default.stringify({
442
+ filters: {
443
+ metadata: { $containsi: id }
444
+ }
445
+ });
446
+ const response = await get(`/${PLUGIN_ID}/embeddings/find?${query}`);
447
+ const embeddings = response.data?.data || response.data || [];
448
+ if (Array.isArray(embeddings) && embeddings.length > 0) {
449
+ setExistingEmbedding({
450
+ documentId: embeddings[0].documentId,
451
+ title: embeddings[0].title,
452
+ content: embeddings[0].content
453
+ });
454
+ }
455
+ } catch (error) {
456
+ console.error("Failed to check for existing embedding:", error);
457
+ } finally {
458
+ setIsCheckingExisting(false);
459
+ }
460
+ }
461
+ checkExistingEmbedding();
462
+ }, [id, slug, get]);
463
+ const extractContentFromForm = react.useCallback(() => {
464
+ if (!modifiedValues) return "";
465
+ const textFieldNames = ["content", "description", "body", "text", "richtext", "markdown"];
466
+ for (const name of textFieldNames) {
467
+ const value = modifiedValues[name];
468
+ if (value) {
469
+ if (typeof value === "string" && value.trim()) {
470
+ setFieldName(name);
471
+ return value;
472
+ } else if (Array.isArray(value)) {
473
+ const text = value.map((block) => {
474
+ if (block.children) {
475
+ return block.children.map((child) => child.text || "").join("");
476
+ }
477
+ return "";
478
+ }).join("\n\n");
479
+ if (text.trim()) {
480
+ setFieldName(name);
481
+ return text;
482
+ }
483
+ }
484
+ }
485
+ }
486
+ return "";
487
+ }, [modifiedValues]);
488
+ react.useEffect(() => {
489
+ const formContent = extractContentFromForm();
490
+ if (formContent) {
491
+ setContent(formContent);
492
+ }
493
+ }, [extractContentFromForm]);
494
+ const contentLength = content.length;
495
+ const willChunk = contentLength > CHUNK_SIZE;
496
+ const estimatedChunks = willChunk ? Math.ceil(contentLength / (CHUNK_SIZE - 200)) : 1;
497
+ const isSaved = !!id;
498
+ function generateMetadata() {
499
+ return {
500
+ source: "content-manager",
501
+ collectionType: slug || collectionType || "unknown",
502
+ fieldName: fieldName || "content",
503
+ documentId: id,
504
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
505
+ };
506
+ }
507
+ const isValid = title.trim() && content.trim();
508
+ function handleOpenCreate() {
509
+ setTitle("");
510
+ const formContent = extractContentFromForm();
511
+ if (formContent) {
512
+ setContent(formContent);
513
+ }
514
+ setIsVisible(true);
515
+ }
516
+ async function handleSubmit(e) {
517
+ e.preventDefault();
518
+ if (!title.trim()) {
519
+ toggleNotification({
520
+ type: "warning",
521
+ message: "Embeddings title is required"
522
+ });
523
+ return;
524
+ }
525
+ if (!content.trim()) {
526
+ toggleNotification({
527
+ type: "warning",
528
+ message: "Embeddings content is required"
529
+ });
530
+ return;
531
+ }
532
+ setIsLoading(true);
533
+ try {
534
+ const contentToEmbed = content.trim();
535
+ const shouldChunk = contentToEmbed.length > CHUNK_SIZE;
536
+ const chunks = shouldChunk ? Math.ceil(contentToEmbed.length / CHUNK_SIZE) : 1;
537
+ if (shouldChunk) {
538
+ console.log(`Creating chunked embedding: ${contentToEmbed.length} chars (~${chunks} parts)`);
539
+ }
540
+ const result = await post(`/${PLUGIN_ID}/embeddings/create-embedding`, {
541
+ data: {
542
+ title: title.trim(),
543
+ content: contentToEmbed,
544
+ collectionType: slug || collectionType,
545
+ fieldName,
546
+ metadata: generateMetadata(),
547
+ autoChunk: shouldChunk
548
+ }
549
+ });
550
+ const responseData = result?.data || result;
551
+ if (responseData?.documentId) {
552
+ setExistingEmbedding({
553
+ documentId: responseData.documentId,
554
+ title: responseData.title,
555
+ content: responseData.content
556
+ });
557
+ }
558
+ setIsVisible(false);
559
+ const message = shouldChunk ? `Embedding created and chunked into ${chunks} parts` : "Embedding created successfully";
560
+ toggleNotification({ type: "success", message });
561
+ } catch (error) {
562
+ console.error("Failed to create embedding:", error);
563
+ toggleNotification({
564
+ type: "danger",
565
+ message: error.message || "Failed to create embedding"
566
+ });
567
+ } finally {
568
+ setIsLoading(false);
569
+ }
570
+ }
571
+ function handleViewEmbedding() {
572
+ if (existingEmbedding?.documentId) {
573
+ navigate(`/plugins/${PLUGIN_ID}/embeddings/${existingEmbedding.documentId}`);
574
+ }
575
+ }
576
+ if (!form || !id) {
577
+ return null;
578
+ }
579
+ if (isCheckingExisting) {
580
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true, children: "Checking embeddings..." }) });
581
+ }
582
+ const submitButtonText = isLoading ? "Creating..." : "Create Embedding";
583
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingTop: 2, children: [
584
+ existingEmbedding ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleViewEmbedding, startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Eye, {}), fullWidth: true, children: "View Embedding" }) : /* @__PURE__ */ jsxRuntime.jsx(
585
+ designSystem.Button,
586
+ {
587
+ onClick: handleOpenCreate,
588
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
589
+ disabled: !isSaved,
590
+ fullWidth: true,
591
+ children: "Create Embedding"
592
+ }
593
+ ),
594
+ !isSaved && !existingEmbedding && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { display: "block", marginTop: "0.5rem" }, children: "Save content first to create embedding" }),
595
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isVisible, onOpenChange: setIsVisible, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
596
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: "Create Embedding from Content" }) }),
597
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
598
+ /* @__PURE__ */ jsxRuntime.jsxs(StyledTypography, { variant: "omega", textColor: "neutral600", children: [
599
+ "Content: ",
600
+ contentLength,
601
+ " characters",
602
+ willChunk && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "primary600", children: [
603
+ " (will create ~",
604
+ estimatedChunks,
605
+ " embeddings)"
606
+ ] })
607
+ ] }),
608
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { children: [
609
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Title" }),
610
+ /* @__PURE__ */ jsxRuntime.jsx(
611
+ designSystem.TextInput,
612
+ {
613
+ placeholder: "Enter embedding title",
614
+ value: title,
615
+ onChange: (e) => setTitle(e.target.value)
616
+ }
617
+ )
618
+ ] }) }),
619
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginBottom: 4, children: [
620
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { children: [
621
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Content" }),
622
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, { children: fieldName ? `From field: ${fieldName}` : "Enter content manually" })
623
+ ] }),
624
+ /* @__PURE__ */ jsxRuntime.jsx(
625
+ MarkdownEditor,
626
+ {
627
+ content,
628
+ onChange: setContent,
629
+ height: 200
630
+ }
631
+ )
632
+ ] })
633
+ ] }) }),
634
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
635
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: "Cancel" }) }),
636
+ /* @__PURE__ */ jsxRuntime.jsx(
637
+ designSystem.Button,
638
+ {
639
+ onClick: handleSubmit,
640
+ disabled: isLoading || !isValid,
641
+ loading: isLoading,
642
+ children: submitButtonText
643
+ }
644
+ )
645
+ ] })
646
+ ] }) })
647
+ ] });
648
+ }
649
+ function EmbeddingsWidget() {
650
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(EmbeddingsModal, {}) });
651
+ }
652
+ const index = {
653
+ register(app) {
654
+ app.registerPlugin({
655
+ id: PLUGIN_ID,
656
+ initializer: Initializer,
657
+ isReady: false,
658
+ name: PLUGIN_ID
659
+ });
660
+ },
661
+ bootstrap(app) {
662
+ app.getPlugin("content-manager").injectComponent("editView", "right-links", {
663
+ name: "open-ai-embeddings",
664
+ Component: () => /* @__PURE__ */ jsxRuntime.jsx(EmbeddingsWidget, {})
665
+ });
666
+ },
667
+ async registerTrads(app) {
668
+ const { locales } = app;
669
+ const importedTranslations = await Promise.all(
670
+ locales.map((locale) => {
671
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("../_chunks/en-B4KWt_jN.js")) }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
672
+ return {
673
+ data: getTranslation(data),
674
+ locale
675
+ };
676
+ }).catch(() => {
677
+ return {
678
+ data: {},
679
+ locale
680
+ };
681
+ });
682
+ })
683
+ );
684
+ return importedTranslations;
685
+ }
686
+ };
687
+ module.exports = index;