strapi-content-embeddings 0.1.4 → 0.1.5

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 (36) hide show
  1. package/README.md +187 -0
  2. package/dist/_chunks/{App-CnXhqiao.js → App-Rq72tIgS.js} +35 -37
  3. package/dist/_chunks/App-Rq72tIgS.js.map +1 -0
  4. package/dist/_chunks/{App-4UwemHRe.mjs → App-j180lztd.mjs} +35 -37
  5. package/dist/_chunks/App-j180lztd.mjs.map +1 -0
  6. package/dist/_chunks/en-B4KWt_jN.js +1 -0
  7. package/dist/_chunks/en-B4KWt_jN.js.map +1 -0
  8. package/dist/_chunks/en-Byx4XI2L.mjs +1 -0
  9. package/dist/_chunks/en-Byx4XI2L.mjs.map +1 -0
  10. package/dist/_chunks/{index-BWSiu_nE.mjs → index-B3j0IFUi.mjs} +70 -27
  11. package/dist/_chunks/index-B3j0IFUi.mjs.map +1 -0
  12. package/dist/_chunks/{index-BaPVw3mi.js → index-jf6vikTZ.js} +70 -27
  13. package/dist/_chunks/index-jf6vikTZ.js.map +1 -0
  14. package/dist/admin/index.js +2 -1
  15. package/dist/admin/index.js.map +1 -0
  16. package/dist/admin/index.mjs +2 -1
  17. package/dist/admin/index.mjs.map +1 -0
  18. package/dist/admin/src/components/custom/MarkdownEditor.d.ts +1 -1
  19. package/dist/server/index.js +850 -57
  20. package/dist/server/index.js.map +1 -0
  21. package/dist/server/index.mjs +850 -57
  22. package/dist/server/index.mjs.map +1 -0
  23. package/dist/server/src/config/index.d.ts +9 -0
  24. package/dist/server/src/controllers/controller.d.ts +14 -0
  25. package/dist/server/src/controllers/index.d.ts +2 -0
  26. package/dist/server/src/index.d.ts +38 -2
  27. package/dist/server/src/mcp/tools/create-embedding.d.ts +6 -0
  28. package/dist/server/src/mcp/tools/index.d.ts +4 -0
  29. package/dist/server/src/plugin-manager.d.ts +16 -0
  30. package/dist/server/src/routes/content-api.d.ts +10 -0
  31. package/dist/server/src/routes/index.d.ts +10 -0
  32. package/dist/server/src/services/embeddings.d.ts +43 -2
  33. package/dist/server/src/services/index.d.ts +23 -2
  34. package/dist/server/src/services/sync.d.ts +48 -0
  35. package/dist/server/src/utils/chunking.d.ts +44 -0
  36. package/package.json +1 -1
@@ -5,7 +5,7 @@ import { useRef, useState, useEffect, useCallback, useMemo } from "react";
5
5
  import { EmptyStateLayout, Button, Tr, Box, Table, Thead, Th, Typography, VisuallyHidden, Tbody, Td, Flex, IconButton, Modal, TextInput, Link as Link$1, Accordion, Main, Loader, Field, Textarea, Grid, Dialog } from "@strapi/design-system";
6
6
  import { Plus, ArrowRight, Search, ArrowLeft, Cross, Check, Pencil, Trash } from "@strapi/icons";
7
7
  import qs from "qs";
8
- import { P as PLUGIN_ID, R as RobotIcon, M as MarkdownEditor } from "./index-BWSiu_nE.mjs";
8
+ import { P as PLUGIN_ID, R as RobotIcon, M as MarkdownEditor } from "./index-B3j0IFUi.mjs";
9
9
  import styled from "styled-components";
10
10
  import ReactMarkdown from "react-markdown";
11
11
  import { useIntl } from "react-intl";
@@ -477,19 +477,14 @@ function HomePage() {
477
477
  const [isLoading, setIsLoading] = useState(true);
478
478
  const buildQuery = (searchTerm) => qs.stringify({
479
479
  filters: searchTerm ? {
480
- $or: [
481
- { title: { $containsi: searchTerm } },
482
- { content: { $containsi: searchTerm } }
483
- ]
480
+ $or: [{ title: { $containsi: searchTerm } }, { content: { $containsi: searchTerm } }]
484
481
  } : void 0
485
482
  });
486
483
  const fetchData = useCallback(
487
484
  async (searchTerm) => {
488
485
  setIsLoading(true);
489
486
  try {
490
- const response = await get(
491
- `/${PLUGIN_ID}/embeddings/find?${buildQuery(searchTerm)}`
492
- );
487
+ const response = await get(`/${PLUGIN_ID}/embeddings/find?${buildQuery(searchTerm)}`);
493
488
  setEmbeddings(response.data);
494
489
  } catch (error) {
495
490
  console.error("Failed to fetch embeddings:", error);
@@ -500,10 +495,7 @@ function HomePage() {
500
495
  },
501
496
  [get]
502
497
  );
503
- const debouncedFetch = useMemo(
504
- () => debounce(fetchData, 500),
505
- [fetchData]
506
- );
498
+ const debouncedFetch = useMemo(() => debounce(fetchData, 500), [fetchData]);
507
499
  useEffect(() => {
508
500
  debouncedFetch(search);
509
501
  }, [search, debouncedFetch]);
@@ -515,30 +507,31 @@ function HomePage() {
515
507
  };
516
508
  if (isLoading && !embeddings) {
517
509
  return /* @__PURE__ */ jsxs(Main, { children: [
518
- /* @__PURE__ */ jsx(
519
- Layouts.Header,
520
- {
521
- title: "Content Embeddings",
522
- subtitle: "Manage your content embeddings"
523
- }
524
- ),
510
+ /* @__PURE__ */ jsx(Layouts.Header, { title: "Content Embeddings", subtitle: "Manage your content embeddings" }),
525
511
  /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 8, children: /* @__PURE__ */ jsx(Loader, { children: "Loading..." }) }) }),
526
512
  /* @__PURE__ */ jsx(ChatModal, {})
527
513
  ] });
528
514
  }
529
515
  if (embeddings?.totalCount === 0 && !search) {
530
516
  return /* @__PURE__ */ jsxs(Main, { children: [
531
- /* @__PURE__ */ jsx(
532
- Layouts.Header,
533
- {
534
- title: "Content Embeddings",
535
- subtitle: "Manage your content embeddings"
536
- }
537
- ),
517
+ /* @__PURE__ */ jsx(Layouts.Header, { title: "Content Embeddings", subtitle: "Manage your content embeddings" }),
538
518
  /* @__PURE__ */ jsx(Layouts.Content, { children: /* @__PURE__ */ jsx(EmptyState, {}) }),
539
519
  /* @__PURE__ */ jsx(ChatModal, {})
540
520
  ] });
541
521
  }
522
+ const renderEmbeddingsContent = () => {
523
+ if (isLoading) {
524
+ return /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 8, children: /* @__PURE__ */ jsx(Loader, { children: "Loading..." }) });
525
+ }
526
+ if (embeddings?.data && embeddings.data.length > 0) {
527
+ return /* @__PURE__ */ jsx(EmbeddingsTable, { data: embeddings.data });
528
+ }
529
+ return /* @__PURE__ */ jsxs(Box, { padding: 8, textAlign: "center", children: [
530
+ 'No embeddings found matching "',
531
+ search,
532
+ '"'
533
+ ] });
534
+ };
542
535
  return /* @__PURE__ */ jsxs(Main, { children: [
543
536
  /* @__PURE__ */ jsx(
544
537
  Layouts.Header,
@@ -559,11 +552,7 @@ function HomePage() {
559
552
  startAction: /* @__PURE__ */ jsx(Search, {})
560
553
  }
561
554
  ) }),
562
- isLoading ? /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 8, children: /* @__PURE__ */ jsx(Loader, { children: "Loading..." }) }) : embeddings?.data && embeddings.data.length > 0 ? /* @__PURE__ */ jsx(EmbeddingsTable, { data: embeddings.data }) : /* @__PURE__ */ jsxs(Box, { padding: 8, textAlign: "center", children: [
563
- 'No embeddings found matching "',
564
- search,
565
- '"'
566
- ] })
555
+ renderEmbeddingsContent()
567
556
  ] }),
568
557
  /* @__PURE__ */ jsx(ChatModal, {})
569
558
  ] });
@@ -626,7 +615,7 @@ function BackLink({ to }) {
626
615
  }
627
616
  return /* @__PURE__ */ jsx(Link$1, { tag: NavLink, to: "..", relative: "path", startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}), children: "Go back" });
628
617
  }
629
- const MAX_CONTENT_LENGTH = 4e3;
618
+ const CHUNK_SIZE = 4e3;
630
619
  function CreateEmbeddings() {
631
620
  const { formatMessage } = useIntl();
632
621
  const navigate = useNavigate();
@@ -636,8 +625,10 @@ function CreateEmbeddings() {
636
625
  const [content, setContent] = useState("");
637
626
  const [metadata, setMetadata] = useState("");
638
627
  const [error, setError] = useState(null);
639
- const isValid = title.trim() && content.trim() && content.length <= MAX_CONTENT_LENGTH;
628
+ const isValid = title.trim() && content.trim();
640
629
  const contentLength = content.length;
630
+ const willChunk = contentLength > CHUNK_SIZE;
631
+ const estimatedChunks = willChunk ? Math.ceil(contentLength / (CHUNK_SIZE - 200)) : 1;
641
632
  function parseMetadata() {
642
633
  if (!metadata.trim()) return null;
643
634
  try {
@@ -650,7 +641,7 @@ function CreateEmbeddings() {
650
641
  e.preventDefault();
651
642
  e.stopPropagation();
652
643
  if (!isValid) {
653
- setError("Please provide a title and content (max 4000 characters)");
644
+ setError("Please provide a title and content");
654
645
  return;
655
646
  }
656
647
  if (metadata.trim()) {
@@ -685,12 +676,18 @@ function CreateEmbeddings() {
685
676
  id: "CreateEmbeddings.header.title",
686
677
  defaultMessage: "Create Embedding"
687
678
  }),
688
- subtitle: formatMessage(
679
+ subtitle: willChunk ? formatMessage(
680
+ {
681
+ id: "CreateEmbeddings.header.subtitle.chunked",
682
+ defaultMessage: "Content: {length} characters (will create ~{chunks} embeddings)"
683
+ },
684
+ { length: contentLength, chunks: estimatedChunks }
685
+ ) : formatMessage(
689
686
  {
690
687
  id: "CreateEmbeddings.header.subtitle",
691
- defaultMessage: "Content: {length}/{max} characters"
688
+ defaultMessage: "Content: {length} characters"
692
689
  },
693
- { length: contentLength, max: MAX_CONTENT_LENGTH }
690
+ { length: contentLength }
694
691
  ),
695
692
  primaryAction: /* @__PURE__ */ jsx(
696
693
  Button,
@@ -986,3 +983,4 @@ const App = () => {
986
983
  export {
987
984
  App
988
985
  };
986
+ //# sourceMappingURL=App-j180lztd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App-j180lztd.mjs","sources":["../../admin/src/components/custom/Illo.tsx","../../admin/src/components/custom/EmptyState.tsx","../../admin/src/components/custom/EmbeddingsTable.tsx","../../admin/src/components/custom/Markdown.tsx","../../admin/src/components/custom/ChatModal.tsx","../../admin/src/pages/HomePage.tsx","../../admin/src/components/forms/CreateEmbeddingForm.tsx","../../admin/src/components/custom/BackLink.tsx","../../admin/src/pages/CreateEmbeddings.tsx","../../admin/src/pages/EmbeddingDetails.tsx","../../admin/src/pages/App.tsx"],"sourcesContent":["export const Illo = () => (\n <svg width=\"159\" height=\"88\" viewBox=\"0 0 159 88\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M134.933 17.417C137.768 17.417 140.067 19.7153 140.067 22.5503C140.067 25.3854 137.768 27.6837 134.933 27.6837H105.6C108.435 27.6837 110.733 29.9819 110.733 32.817C110.733 35.6521 108.435 37.9503 105.6 37.9503H121.733C124.568 37.9503 126.867 40.2486 126.867 43.0837C126.867 45.9187 124.568 48.217 121.733 48.217H114.272C110.698 48.217 107.8 50.5153 107.8 53.3503C107.8 55.2404 109.267 56.9515 112.2 58.4837C115.035 58.4837 117.333 60.7819 117.333 63.617C117.333 66.4521 115.035 68.7503 112.2 68.7503H51.3333C48.4982 68.7503 46.2 66.4521 46.2 63.617C46.2 60.7819 48.4982 58.4837 51.3333 58.4837H22.7333C19.8982 58.4837 17.6 56.1854 17.6 53.3503C17.6 50.5153 19.8982 48.217 22.7333 48.217H52.0666C54.9017 48.217 57.2 45.9187 57.2 43.0837C57.2 40.2486 54.9017 37.9503 52.0666 37.9503H33.7333C30.8982 37.9503 28.6 35.6521 28.6 32.817C28.6 29.9819 30.8982 27.6837 33.7333 27.6837H63.0666C60.2316 27.6837 57.9333 25.3854 57.9333 22.5503C57.9333 19.7153 60.2316 17.417 63.0666 17.417H134.933ZM134.933 37.9503C137.768 37.9503 140.067 40.2486 140.067 43.0837C140.067 45.9187 137.768 48.217 134.933 48.217C132.098 48.217 129.8 45.9187 129.8 43.0837C129.8 40.2486 132.098 37.9503 134.933 37.9503Z\"\n fill=\"#DBDBFA\"\n />\n\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M95.826 16.6834L102.647 66.4348L103.26 71.4261C103.458 73.034 102.314 74.4976 100.706 74.695L57.7621 79.9679C56.1542 80.1653 54.6906 79.0219 54.4932 77.4139L47.8816 23.5671C47.7829 22.7631 48.3546 22.0313 49.1586 21.9326C49.1637 21.932 49.1688 21.9313 49.1739 21.9307L52.7367 21.5311L95.826 16.6834ZM55.6176 21.208L58.9814 20.8306Z\"\n fill=\"white\"\n />\n\n <path\n d=\"M55.6176 21.208L58.9814 20.8306M95.826 16.6834L102.647 66.4348L103.26 71.4261C103.458 73.034 102.314 74.4976 100.706 74.695L57.7621 79.9679C56.1542 80.1653 54.6906 79.0219 54.4932 77.4139L47.8816 23.5671C47.7829 22.7631 48.3546 22.0313 49.1586 21.9326C49.1637 21.932 49.1688 21.9313 49.1739 21.9307L52.7367 21.5311L95.826 16.6834Z\"\n stroke=\"#7E7BF6\"\n strokeWidth=\"2.5\"\n />\n\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M93.9695 19.8144L100.144 64.9025L100.699 69.4258C100.878 70.8831 99.8559 72.2077 98.416 72.3845L59.9585 77.1065C58.5185 77.2833 57.2062 76.2453 57.0272 74.7881L51.0506 26.112C50.9519 25.308 51.5236 24.5762 52.3276 24.4775L57.0851 23.8934\"\n fill=\"#F0F0FF\"\n />\n\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M97.701 7.33301H64.2927C63.7358 7.33301 63.2316 7.55873 62.8667 7.92368C62.5017 8.28862 62.276 8.79279 62.276 9.34967V65.083C62.276 65.6399 62.5017 66.1441 62.8667 66.509C63.2316 66.874 63.7358 67.0997 64.2927 67.0997H107.559C108.116 67.0997 108.62 66.874 108.985 66.509C109.35 66.1441 109.576 65.6399 109.576 65.083V19.202C109.576 18.6669 109.363 18.1537 108.985 17.7755L99.1265 7.92324C98.7484 7.54531 98.2356 7.33301 97.701 7.33301Z\"\n fill=\"white\"\n stroke=\"#7F7CFA\"\n strokeWidth=\"2.5\"\n />\n\n <path\n d=\"M98.026 8.17871V16.6833C98.026 17.8983 99.011 18.8833 100.226 18.8833H106.044\"\n stroke=\"#807EFA\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n\n <path\n d=\"M70.1594 56.2838H89.2261M70.1594 18.8838H89.2261H70.1594ZM70.1594 27.6838H101.693H70.1594ZM70.1594 37.2171H101.693H70.1594ZM70.1594 46.7505H101.693H70.1594Z\"\n stroke=\"#817FFA\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\n","import { EmptyStateLayout, Button } from '@strapi/design-system';\nimport { Link } from 'react-router-dom';\nimport { PLUGIN_ID } from \"../../pluginId\"\nimport { Plus } from '@strapi/icons';\nimport { Illo } from './Illo';\n\nexport function EmptyState() {\n return (\n <EmptyStateLayout\n icon={<Illo />}\n content=\"Let's create our first embedding...\"\n action={\n <Link to={`/plugins/${PLUGIN_ID}/embeddings`}>\n <Button startIcon={<Plus />}>Create new embedding</Button>\n </Link>\n }\n />\n );\n}","import React from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport styled from \"styled-components\";\nimport {\n Box,\n Table,\n Thead,\n Tbody,\n Tr,\n Td,\n Th,\n Typography,\n VisuallyHidden,\n Flex,\n IconButton,\n} from \"@strapi/design-system\";\nimport { ArrowRight } from \"@strapi/icons\";\nimport { PLUGIN_ID } from \"../../pluginId\";\n\nconst StyledTr = styled(Tr)`\n cursor: pointer;\n &:hover {\n background-color: #f0f0ff;\n }\n`;\n\ninterface Embedding {\n id: number;\n documentId: string;\n title: string;\n content?: string;\n embeddingId?: string;\n}\n\ninterface EmbeddingsTableProps {\n data: Embedding[];\n}\n\nexport function EmbeddingsTable({ data }: EmbeddingsTableProps) {\n const navigate = useNavigate();\n\n const handleRowClick = (documentId: string) => {\n navigate(`/plugins/${PLUGIN_ID}/embeddings/${documentId}`);\n };\n\n return (\n <Box padding={8} background=\"neutral100\">\n <Table colCount={5} rowCount={data.length + 1}>\n <Thead>\n <Tr>\n <Th>\n <Typography variant=\"sigma\">ID</Typography>\n </Th>\n <Th>\n <Typography variant=\"sigma\">Title</Typography>\n </Th>\n <Th>\n <Typography variant=\"sigma\">Content</Typography>\n </Th>\n <Th>\n <Typography variant=\"sigma\">Embed ID</Typography>\n </Th>\n <Th>\n <VisuallyHidden>Actions</VisuallyHidden>\n </Th>\n </Tr>\n </Thead>\n <Tbody>\n {data?.map((entry) => (\n <StyledTr\n key={entry.documentId}\n onClick={() => handleRowClick(entry.documentId)}\n >\n <Td>\n <Typography textColor=\"neutral800\">\n {entry.documentId.slice(0, 8)}...\n </Typography>\n </Td>\n <Td>\n <Typography textColor=\"neutral800\">\n {entry.title?.slice(0, 30)}\n {entry.title?.length > 30 ? \"...\" : \"\"}\n </Typography>\n </Td>\n <Td>\n <Typography textColor=\"neutral800\">\n {entry.content?.slice(0, 30)}\n {entry.content && entry.content.length > 30 ? \"...\" : \"\"}\n </Typography>\n </Td>\n <Td>\n <Typography textColor=\"neutral800\">\n {entry.embeddingId?.slice(0, 8)}\n {entry.embeddingId && entry.embeddingId.length > 8\n ? \"...\"\n : \"\"}\n </Typography>\n </Td>\n <Td>\n <Flex>\n <IconButton\n withTooltip={false}\n label=\"View details\"\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n handleRowClick(entry.documentId);\n }}\n >\n <ArrowRight />\n </IconButton>\n </Flex>\n </Td>\n </StyledTr>\n ))}\n </Tbody>\n </Table>\n </Box>\n );\n}\n","import React from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport styled from \"styled-components\";\n\nconst MarkdownWrapper = styled.div`\n /* Headers */\n h1 {\n font-size: 2.25rem;\n font-weight: 700;\n margin-bottom: 1rem;\n color: #272728;\n }\n\n h2 {\n font-size: 1.75rem;\n font-weight: 700;\n margin-bottom: 1rem;\n color: #272728;\n }\n\n h3 {\n font-size: 1.5rem;\n font-weight: 700;\n margin-bottom: 1rem;\n color: #272728;\n }\n\n h4 {\n font-size: 1.25rem;\n font-weight: 700;\n margin-bottom: 1rem;\n color: #272728;\n }\n\n h5 {\n font-size: 1.125rem;\n font-weight: 700;\n margin-bottom: 1rem;\n color: #272728;\n }\n\n h6 {\n font-size: 1rem;\n font-weight: 700;\n margin-bottom: 1rem;\n color: #9d4edd;\n }\n\n /* Horizontal rules */\n hr {\n border-color: #d1d5db;\n margin-top: 2rem;\n margin-bottom: 2rem;\n }\n\n a {\n color: #4945ff;\n text-decoration: underline;\n }\n\n /* Paragraphs */\n p {\n margin-bottom: 1rem;\n line-height: 1.5rem;\n color: #39393a;\n }\n\n /* Emphasis */\n strong {\n font-weight: 700;\n }\n\n em {\n font-style: italic;\n }\n\n del {\n text-decoration: line-through;\n }\n\n /* Blockquotes */\n blockquote {\n border-left-width: 1px;\n border-color: #9ca3af;\n padding-left: 1rem;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n margin-bottom: 1rem;\n }\n\n /* Lists */\n ul {\n list-style-type: disc;\n padding-left: 1rem;\n margin-bottom: 1rem;\n }\n\n ol {\n list-style-type: decimal;\n padding-left: 1rem;\n margin-bottom: 1rem;\n }\n\n li {\n margin-bottom: 0.5rem;\n }\n\n li > ul {\n list-style-type: disc;\n padding-left: 1rem;\n margin-bottom: 0.5rem;\n }\n\n li > ol {\n list-style-type: decimal;\n padding-left: 1rem;\n margin-bottom: 0.5rem;\n }\n\n /* Code blocks */\n pre {\n font-family: monospace;\n background-color: #1f2937;\n color: #f9fafb;\n border-radius: 0.375rem;\n padding: 1rem;\n margin-top: 1.5rem;\n margin-bottom: 1.5rem;\n line-height: 1.5rem;\n overflow: auto;\n }\n\n code {\n font-family: monospace;\n background-color: #1f2937;\n color: #f9fafb;\n border-radius: 0.375rem;\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n }\n\n /* Tables */\n table {\n width: 100%;\n border-collapse: collapse;\n border-color: #d1d5db;\n margin-top: 1.5rem;\n margin-bottom: 1.5rem;\n }\n\n th {\n background-color: #1f2937;\n text-align: left;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n padding-left: 1rem;\n padding-right: 1rem;\n font-weight: 600;\n border-bottom-width: 1px;\n border-color: #d1d5db;\n }\n\n td {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n padding-left: 1rem;\n padding-right: 1rem;\n border-bottom-width: 1px;\n border-color: #d1d5db;\n }\n\n /* Images */\n img {\n width: 100%;\n object-fit: cover;\n border-radius: 0.75rem;\n margin-top: 1.5rem;\n margin-bottom: 1.5rem;\n }\n`;\n\ninterface MarkdownProps {\n children: string;\n}\n\nexport function Markdown({ children }: MarkdownProps) {\n return (\n <MarkdownWrapper>\n <ReactMarkdown>{children}</ReactMarkdown>\n </MarkdownWrapper>\n );\n}\n","import React, { useState, useRef, useEffect } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport styled from \"styled-components\";\nimport qs from \"qs\";\nimport { useFetchClient } from \"@strapi/strapi/admin\";\nimport {\n Button,\n Typography,\n Box,\n TextInput,\n Modal,\n Accordion,\n Link,\n} from \"@strapi/design-system\";\n\nimport { PLUGIN_ID } from \"../../pluginId\";\nimport { RobotIcon } from \"./RobotIcon\";\nimport { Markdown } from \"./Markdown\";\n\nconst StyledButton = styled(Button)`\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n height: 3.5rem;\n width: 3.5rem;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n z-index: 100;\n\n svg {\n height: 1.75rem;\n width: 1.75rem;\n }\n`;\n\nconst ResponseContainer = styled.div`\n border: solid 1px #e3e9f3;\n border-radius: 4px;\n padding: 1rem;\n color: #32324d;\n font-weight: 400;\n font-size: 0.875rem;\n display: block;\n width: 100%;\n max-height: 400px;\n background: inherit;\n overflow-y: auto;\n scroll-behavior: smooth;\n`;\n\ninterface SourceDocument {\n pageContent: string;\n metadata: {\n id: string;\n title: string;\n collectionType?: string;\n fieldName?: string;\n };\n}\n\ninterface QueryResponse {\n text: string;\n sourceDocuments: SourceDocument[];\n}\n\ninterface AccordionDetailsProps {\n title: string;\n content: React.ReactNode;\n children?: React.ReactNode;\n}\n\nfunction AccordionDetails({ title, content, children }: AccordionDetailsProps) {\n return (\n <Box padding={1} background=\"primary100\">\n <Accordion.Root size=\"S\">\n <Accordion.Item value=\"acc-1\">\n <Accordion.Header>\n <Accordion.Trigger>{title}</Accordion.Trigger>\n </Accordion.Header>\n <Accordion.Content>\n <Box padding={3}>\n <Typography>{content}</Typography>\n {children && <Box padding={1}>{children}</Box>}\n </Box>\n </Accordion.Content>\n </Accordion.Item>\n </Accordion.Root>\n </Box>\n );\n}\n\ninterface ShowResponseProps {\n data: QueryResponse[];\n onNavigate: (id: string) => void;\n}\n\nfunction ShowResponse({ data, onNavigate }: ShowResponseProps) {\n return (\n <>\n {data.map((item, index) => (\n <Box key={index} marginBottom={4}>\n <Box padding={1}>\n <Markdown>{item.text}</Markdown>\n </Box>\n\n {item.sourceDocuments?.length > 0 &&\n item.sourceDocuments.map((doc, docIndex) => (\n <AccordionDetails\n key={docIndex}\n title=\"Original Source Document\"\n content={<Markdown>{doc.pageContent}</Markdown>}\n >\n <Link\n onClick={() => onNavigate(doc.metadata.id)}\n style={{ cursor: \"pointer\" }}\n >\n View Source for {doc.metadata.title}\n </Link>\n </AccordionDetails>\n ))}\n </Box>\n ))}\n </>\n );\n}\n\nexport function ChatModal() {\n const { get } = useFetchClient();\n const containerRef = useRef<HTMLDivElement>(null);\n const navigate = useNavigate();\n\n const [isVisible, setIsVisible] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [inputValue, setInputValue] = useState(\"\");\n const [data, setData] = useState<QueryResponse[]>([]);\n\n useEffect(() => {\n if (containerRef.current) {\n containerRef.current.scrollTop = containerRef.current.scrollHeight;\n }\n }, [data]);\n\n function handleNavigate(id: string) {\n setIsVisible(false);\n navigate(`/plugins/${PLUGIN_ID}/embeddings/${id}`);\n }\n\n async function handleQueryEmbeddings(e: React.FormEvent) {\n e.preventDefault();\n if (!inputValue.trim() || isLoading) return;\n\n setIsLoading(true);\n try {\n const response = await get(\n `/${PLUGIN_ID}/embeddings/embeddings-query?${qs.stringify({\n query: inputValue,\n })}`\n );\n if (response.data && !response.data.error) {\n setData((prev) => [...prev, response.data as QueryResponse]);\n }\n setInputValue(\"\");\n } catch (error) {\n console.error(\"Query failed:\", error);\n } finally {\n setIsLoading(false);\n }\n }\n\n return (\n <>\n <StyledButton onClick={() => setIsVisible(true)} aria-label=\"Open chat\">\n <RobotIcon height={28} width={28} />\n </StyledButton>\n\n <Modal.Root open={isVisible} onOpenChange={setIsVisible}>\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>Chat With Your Data</Modal.Title>\n </Modal.Header>\n <Modal.Body>\n {data.length > 0 && (\n <Box padding={1} marginBottom={4}>\n <ResponseContainer ref={containerRef}>\n <ShowResponse data={data} onNavigate={handleNavigate} />\n </ResponseContainer>\n </Box>\n )}\n <Box padding={1}>\n <form onSubmit={handleQueryEmbeddings}>\n <TextInput\n placeholder=\"Enter your question\"\n type=\"text\"\n aria-label=\"Question\"\n name=\"question\"\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setInputValue(e.target.value)\n }\n value={inputValue}\n />\n </form>\n </Box>\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close>\n <Button variant=\"tertiary\">Cancel</Button>\n </Modal.Close>\n <Button\n onClick={handleQueryEmbeddings}\n disabled={!inputValue.trim() || isLoading}\n loading={isLoading}\n >\n {isLoading ? \"Sending...\" : \"Send\"}\n </Button>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n </>\n );\n}\n","import React, { useEffect, useState, useCallback, useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Main, Box, Button, TextInput, Flex, Loader } from '@strapi/design-system';\nimport { Plus, Search } from '@strapi/icons';\nimport { useFetchClient, Layouts } from '@strapi/strapi/admin';\nimport qs from 'qs';\n\nimport { PLUGIN_ID } from '../pluginId';\nimport { EmptyState } from '../components/custom/EmptyState';\nimport { EmbeddingsTable } from '../components/custom/EmbeddingsTable';\nimport { ChatModal } from '../components/custom/ChatModal';\n\ninterface Embedding {\n id: number;\n documentId: string;\n title: string;\n content?: string;\n embeddingsId?: string;\n}\n\ninterface EmbeddingsResponse {\n data: Embedding[];\n count: number;\n totalCount: number;\n}\n\nfunction debounce<T extends (...args: any[]) => any>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: NodeJS.Timeout;\n return (...args: Parameters<T>) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => func(...args), wait);\n };\n}\n\nexport function HomePage() {\n const { get } = useFetchClient();\n const navigate = useNavigate();\n\n const [embeddings, setEmbeddings] = useState<EmbeddingsResponse | null>(null);\n const [search, setSearch] = useState('');\n const [isLoading, setIsLoading] = useState(true);\n\n const buildQuery = (searchTerm: string) =>\n qs.stringify({\n filters: searchTerm\n ? {\n $or: [{ title: { $containsi: searchTerm } }, { content: { $containsi: searchTerm } }],\n }\n : undefined,\n });\n\n const fetchData = useCallback(\n async (searchTerm: string) => {\n setIsLoading(true);\n try {\n const response = await get(`/${PLUGIN_ID}/embeddings/find?${buildQuery(searchTerm)}`);\n setEmbeddings(response.data as EmbeddingsResponse);\n } catch (error) {\n console.error('Failed to fetch embeddings:', error);\n setEmbeddings({ data: [], count: 0, totalCount: 0 });\n } finally {\n setIsLoading(false);\n }\n },\n [get]\n );\n\n const debouncedFetch = useMemo(() => debounce(fetchData, 500), [fetchData]);\n\n useEffect(() => {\n debouncedFetch(search);\n }, [search, debouncedFetch]);\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearch(e.target.value);\n };\n\n const handleCreateNew = () => {\n navigate(`/plugins/${PLUGIN_ID}/embeddings`);\n };\n\n if (isLoading && !embeddings) {\n return (\n <Main>\n <Layouts.Header title={'Content Embeddings'} subtitle={'Manage your content embeddings'} />\n <Layouts.Content>\n <Flex justifyContent=\"center\" padding={8}>\n <Loader>Loading...</Loader>\n </Flex>\n </Layouts.Content>\n <ChatModal />\n </Main>\n );\n }\n\n if (embeddings?.totalCount === 0 && !search) {\n return (\n <Main>\n <Layouts.Header title={'Content Embeddings'} subtitle={'Manage your content embeddings'} />\n <Layouts.Content>\n <EmptyState />\n </Layouts.Content>\n <ChatModal />\n </Main>\n );\n }\n\n // Render embeddings content based on loading state and data\n const renderEmbeddingsContent = () => {\n if (isLoading) {\n return (\n <Flex justifyContent=\"center\" padding={8}>\n <Loader>Loading...</Loader>\n </Flex>\n );\n }\n\n if (embeddings?.data && embeddings.data.length > 0) {\n return <EmbeddingsTable data={embeddings.data} />;\n }\n\n return (\n <Box padding={8} textAlign=\"center\">\n No embeddings found matching \"{search}\"\n </Box>\n );\n };\n\n return (\n <Main>\n <Layouts.Header\n title={'Content Embeddings'}\n subtitle={`${embeddings?.count || 0} results found`}\n primaryAction={\n <Button startIcon={<Plus />} onClick={handleCreateNew}>\n Create new embedding\n </Button>\n }\n />\n <Layouts.Content>\n <Box paddingBottom={4}>\n <TextInput\n placeholder=\"Search embeddings...\"\n name=\"search\"\n value={search}\n onChange={handleSearchChange}\n startAction={<Search />}\n />\n </Box>\n {renderEmbeddingsContent()}\n </Layouts.Content>\n <ChatModal />\n </Main>\n );\n}\n","import React from 'react';\nimport { Box, Field, TextInput, Textarea } from '@strapi/design-system';\nimport { MarkdownEditor } from '../custom/MarkdownEditor';\n\ninterface CreateEmbeddingsFormProps {\n onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;\n isLoading: boolean;\n input: string;\n setInput: (input: string) => void;\n markdown: string;\n handleMarkdownChange: React.Dispatch<React.SetStateAction<string>>;\n metadata: string;\n setMetadata: (metadata: string) => void;\n height?: number;\n children?: React.ReactNode;\n}\n\nexport function CreateEmbeddingsForm({\n onSubmit,\n isLoading,\n input,\n setInput,\n markdown,\n handleMarkdownChange,\n metadata,\n setMetadata,\n height,\n children,\n}: CreateEmbeddingsFormProps) {\n return (\n <form onSubmit={onSubmit}>\n <fieldset disabled={isLoading} style={{ border: 'none', padding: 0, margin: 0 }}>\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Title</Field.Label>\n <TextInput\n placeholder=\"Enter a title for your embedding\"\n name=\"input\"\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setInput(e.target.value)}\n value={input}\n />\n </Field.Root>\n </Box>\n\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Content</Field.Label>\n <MarkdownEditor\n content={markdown}\n onChange={handleMarkdownChange}\n height={height}\n />\n </Field.Root>\n </Box>\n\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Metadata (JSON)</Field.Label>\n <Field.Hint>Optional JSON metadata for this embedding</Field.Hint>\n <Textarea\n placeholder='{\"category\": \"docs\", \"source\": \"manual\"}'\n name=\"metadata\"\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setMetadata(e.target.value)}\n value={metadata}\n />\n </Field.Root>\n </Box>\n\n {children}\n </fieldset>\n </form>\n );\n}\n","import { Link } from \"@strapi/design-system\";\nimport { ArrowLeft } from \"@strapi/icons\";\nimport { NavLink } from \"react-router-dom\";\n\ninterface BackLinkProps {\n to?: string;\n}\n\nexport function BackLink({ to }: BackLinkProps) {\n if (to) {\n return (\n <Link tag={NavLink} to={to} startIcon={<ArrowLeft />}>\n Go back\n </Link>\n );\n }\n\n return (\n <Link tag={NavLink} to=\"..\" relative=\"path\" startIcon={<ArrowLeft />}>\n Go back\n </Link>\n );\n}\n\nexport default BackLink;\n","import React, { useState } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport { useIntl } from \"react-intl\";\nimport { Main, Box, Button } from \"@strapi/design-system\";\nimport { useFetchClient, Layouts } from \"@strapi/strapi/admin\";\n\nimport { PLUGIN_ID } from \"../pluginId\";\nimport { CreateEmbeddingsForm } from \"../components/forms/CreateEmbeddingForm\";\nimport { BackLink } from \"../components/custom/BackLink\";\n\nconst CHUNK_SIZE = 4000; // Content over this will be auto-chunked\n\nexport default function CreateEmbeddings() {\n const { formatMessage } = useIntl();\n const navigate = useNavigate();\n const { post } = useFetchClient();\n\n const [isLoading, setIsLoading] = useState(false);\n const [title, setTitle] = useState(\"\");\n const [content, setContent] = useState(\"\");\n const [metadata, setMetadata] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n\n const isValid = title.trim() && content.trim();\n const contentLength = content.length;\n const willChunk = contentLength > CHUNK_SIZE;\n const estimatedChunks = willChunk ? Math.ceil(contentLength / (CHUNK_SIZE - 200)) : 1;\n\n function parseMetadata(): Record<string, any> | null {\n if (!metadata.trim()) return null;\n try {\n return JSON.parse(metadata);\n } catch {\n return null;\n }\n }\n\n async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault();\n e.stopPropagation();\n\n if (!isValid) {\n setError(\"Please provide a title and content\");\n return;\n }\n\n // Validate metadata JSON if provided\n if (metadata.trim()) {\n const parsedMetadata = parseMetadata();\n if (parsedMetadata === null) {\n setError(\"Invalid JSON in metadata field\");\n return;\n }\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n await post(`/${PLUGIN_ID}/embeddings/create-embedding`, {\n data: {\n title: title.trim(),\n content: content.trim(),\n metadata: parseMetadata(),\n },\n });\n navigate(`/plugins/${PLUGIN_ID}`);\n } catch (err: any) {\n console.error(\"Failed to create embedding:\", err);\n setError(err.message || \"Failed to create embedding. Please try again.\");\n setIsLoading(false);\n }\n }\n\n return (\n <Main>\n <Layouts.Header\n title={formatMessage({\n id: \"CreateEmbeddings.header.title\",\n defaultMessage: \"Create Embedding\",\n })}\n subtitle={\n willChunk\n ? formatMessage(\n {\n id: \"CreateEmbeddings.header.subtitle.chunked\",\n defaultMessage: \"Content: {length} characters (will create ~{chunks} embeddings)\",\n },\n { length: contentLength, chunks: estimatedChunks }\n )\n : formatMessage(\n {\n id: \"CreateEmbeddings.header.subtitle\",\n defaultMessage: \"Content: {length} characters\",\n },\n { length: contentLength }\n )\n }\n primaryAction={\n <Button\n type=\"submit\"\n disabled={isLoading || !isValid}\n loading={isLoading}\n onClick={(e: React.MouseEvent) => {\n e.preventDefault();\n const form = document.querySelector(\"form\");\n if (form) {\n form.dispatchEvent(\n new Event(\"submit\", { cancelable: true, bubbles: true })\n );\n }\n }}\n >\n {isLoading ? \"Creating...\" : \"Create Embedding\"}\n </Button>\n }\n navigationAction={<BackLink to={`/plugins/${PLUGIN_ID}`} />}\n />\n <Layouts.Content>\n <Box>\n {error && (\n <Box\n padding={4}\n marginBottom={4}\n background=\"danger100\"\n borderColor=\"danger600\"\n hasRadius\n >\n {error}\n </Box>\n )}\n <CreateEmbeddingsForm\n onSubmit={handleSubmit}\n isLoading={isLoading}\n input={title}\n setInput={setTitle}\n markdown={content}\n handleMarkdownChange={setContent}\n metadata={metadata}\n setMetadata={setMetadata}\n />\n </Box>\n </Layouts.Content>\n </Main>\n );\n}\n","import React, { useEffect, useState } from \"react\";\nimport { useNavigate, useParams } from \"react-router-dom\";\nimport styled from \"styled-components\";\nimport {\n Main,\n Box,\n Flex,\n Button,\n Typography,\n Grid,\n Dialog,\n Loader,\n Field,\n TextInput,\n Textarea,\n} from \"@strapi/design-system\";\nimport { Trash, Pencil, Check, Cross } from \"@strapi/icons\";\nimport { useFetchClient, Layouts, useNotification } from \"@strapi/strapi/admin\";\n\nimport { PLUGIN_ID } from \"../pluginId\";\nimport { BackLink } from \"../components/custom/BackLink\";\nimport { Markdown } from \"../components/custom/Markdown\";\nimport { MarkdownEditor } from \"../components/custom/MarkdownEditor\";\n\nconst StyledTypography = styled(Typography)`\n display: block;\n margin-bottom: 1rem;\n`;\n\ninterface EmbeddingData {\n id: number;\n documentId: string;\n title: string;\n content?: string;\n embeddingId?: string;\n embedding?: number[];\n collectionType?: string;\n fieldName?: string;\n metadata?: Record<string, any>;\n}\n\ninterface MetadataProps {\n data: EmbeddingData;\n}\n\nfunction Metadata({ data }: MetadataProps) {\n const metadata = {\n id: data.documentId,\n title: data.title,\n collectionType: data.collectionType || \"standalone\",\n fieldName: data.fieldName || \"content\",\n embeddingId: data.embeddingId || \"N/A\",\n vectorDimensions: data.embedding?.length || 0,\n };\n\n return (\n <Box padding={4} background=\"neutral0\" hasRadius>\n <StyledTypography variant=\"beta\">Metadata</StyledTypography>\n {Object.entries(metadata).map(([key, value]) => (\n <Box key={key} padding={1}>\n <Typography>\n <strong>{key}:</strong> {String(value)}\n </Typography>\n </Box>\n ))}\n {data.metadata && (\n <Box marginTop={4}>\n <Typography variant=\"sigma\">Custom Metadata</Typography>\n <Box padding={2} background=\"neutral100\" hasRadius marginTop={2}>\n <pre style={{ fontSize: \"12px\", margin: 0, whiteSpace: \"pre-wrap\" }}>\n {JSON.stringify(data.metadata, null, 2)}\n </pre>\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n\ninterface ConfirmDeleteProps {\n onConfirm: () => void;\n isLoading: boolean;\n}\n\nfunction ConfirmDeleteEmbedding({ onConfirm, isLoading }: ConfirmDeleteProps) {\n return (\n <Dialog.Root>\n <Dialog.Trigger>\n <Button variant=\"danger-light\" startIcon={<Trash />}>\n Delete\n </Button>\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Header>Confirm Deletion</Dialog.Header>\n <Dialog.Body>\n <Flex direction=\"column\" alignItems=\"center\" gap={2}>\n <Typography>Are you sure you want to delete this embedding?</Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n This action cannot be undone.\n </Typography>\n </Flex>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Cancel>\n <Button variant=\"tertiary\">Cancel</Button>\n </Dialog.Cancel>\n <Dialog.Action>\n <Button\n variant=\"danger\"\n onClick={onConfirm}\n startIcon={<Trash />}\n loading={isLoading}\n >\n {isLoading ? \"Deleting...\" : \"Delete\"}\n </Button>\n </Dialog.Action>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nexport default function EmbeddingDetails() {\n const navigate = useNavigate();\n const { id } = useParams<{ id: string }>();\n const { del, get, put } = useFetchClient();\n const { toggleNotification } = useNotification();\n\n const [data, setData] = useState<EmbeddingData | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isDeleting, setIsDeleting] = useState(false);\n const [isEditing, setIsEditing] = useState(false);\n const [isSaving, setIsSaving] = useState(false);\n\n // Edit form state\n const [editTitle, setEditTitle] = useState(\"\");\n const [editContent, setEditContent] = useState(\"\");\n const [editMetadata, setEditMetadata] = useState(\"\");\n\n useEffect(() => {\n async function fetchData() {\n if (!id) return;\n try {\n const response = await get(`/${PLUGIN_ID}/embeddings/find/${id}`);\n const embeddingData = response.data as EmbeddingData;\n setData(embeddingData);\n // Initialize edit form\n setEditTitle(embeddingData.title || \"\");\n setEditContent(embeddingData.content || \"\");\n setEditMetadata(embeddingData.metadata ? JSON.stringify(embeddingData.metadata, null, 2) : \"\");\n } catch (error) {\n console.error(\"Failed to fetch embedding:\", error);\n } finally {\n setIsLoading(false);\n }\n }\n fetchData();\n }, [id, get]);\n\n const handleDelete = async () => {\n if (!id || isDeleting) return;\n setIsDeleting(true);\n try {\n await del(`/${PLUGIN_ID}/embeddings/delete-embedding/${id}`);\n navigate(`/plugins/${PLUGIN_ID}`);\n } catch (error) {\n console.error(\"Failed to delete embedding:\", error);\n setIsDeleting(false);\n }\n };\n\n const handleStartEdit = () => {\n if (data) {\n setEditTitle(data.title || \"\");\n setEditContent(data.content || \"\");\n setEditMetadata(data.metadata ? JSON.stringify(data.metadata, null, 2) : \"\");\n }\n setIsEditing(true);\n };\n\n const handleCancelEdit = () => {\n setIsEditing(false);\n };\n\n const handleSave = async () => {\n if (!id || isSaving) return;\n\n // Validate metadata JSON if provided\n let parsedMetadata = null;\n if (editMetadata.trim()) {\n try {\n parsedMetadata = JSON.parse(editMetadata);\n } catch {\n toggleNotification({\n type: \"warning\",\n message: \"Invalid JSON in metadata field\",\n });\n return;\n }\n }\n\n setIsSaving(true);\n try {\n const response = await put(`/${PLUGIN_ID}/embeddings/update-embedding/${id}`, {\n data: {\n title: editTitle.trim(),\n content: editContent.trim(),\n metadata: parsedMetadata,\n },\n });\n\n setData(response.data as EmbeddingData);\n setIsEditing(false);\n toggleNotification({\n type: \"success\",\n message: \"Embedding updated successfully\",\n });\n } catch (error: any) {\n console.error(\"Failed to update embedding:\", error);\n toggleNotification({\n type: \"danger\",\n message: error.message || \"Failed to update embedding\",\n });\n } finally {\n setIsSaving(false);\n }\n };\n\n if (isLoading) {\n return (\n <Main>\n <Layouts.Header\n title=\"Loading...\"\n navigationAction={<BackLink to={`/plugins/${PLUGIN_ID}`} />}\n />\n <Layouts.Content>\n <Flex justifyContent=\"center\" padding={8}>\n <Loader>Loading embedding details...</Loader>\n </Flex>\n </Layouts.Content>\n </Main>\n );\n }\n\n if (!data) {\n return (\n <Main>\n <Layouts.Header\n title=\"Embedding Not Found\"\n navigationAction={<BackLink to={`/plugins/${PLUGIN_ID}`} />}\n />\n <Layouts.Content>\n <Box padding={8} textAlign=\"center\">\n <Typography>The requested embedding could not be found.</Typography>\n </Box>\n </Layouts.Content>\n </Main>\n );\n }\n\n return (\n <Main>\n <Layouts.Header\n title={isEditing ? \"Edit Embedding\" : (data.title || \"Embedding Details\")}\n subtitle={`Embedding ID: ${data.embeddingId || \"N/A\"}`}\n primaryAction={\n isEditing ? (\n <Flex gap={2}>\n <Button variant=\"tertiary\" startIcon={<Cross />} onClick={handleCancelEdit}>\n Cancel\n </Button>\n <Button startIcon={<Check />} onClick={handleSave} loading={isSaving}>\n {isSaving ? \"Saving...\" : \"Save\"}\n </Button>\n </Flex>\n ) : (\n <Flex gap={2}>\n <Button variant=\"secondary\" startIcon={<Pencil />} onClick={handleStartEdit}>\n Edit\n </Button>\n <ConfirmDeleteEmbedding onConfirm={handleDelete} isLoading={isDeleting} />\n </Flex>\n )\n }\n navigationAction={<BackLink to={`/plugins/${PLUGIN_ID}`} />}\n />\n <Layouts.Content>\n <Box padding={8}>\n {isEditing ? (\n <Grid.Root gap={6}>\n <Grid.Item col={8} s={12}>\n <Box background=\"neutral100\" padding={1} hasRadius>\n <Box padding={4} background=\"neutral0\" hasRadius>\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Title</Field.Label>\n <TextInput\n value={editTitle}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setEditTitle(e.target.value)\n }\n />\n </Field.Root>\n </Box>\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Content</Field.Label>\n <Field.Hint>\n Changes to content will regenerate the embedding vector\n </Field.Hint>\n </Field.Root>\n <MarkdownEditor\n content={editContent}\n onChange={setEditContent}\n height={300}\n />\n </Box>\n </Box>\n </Box>\n </Grid.Item>\n <Grid.Item col={4} s={12}>\n <Box background=\"neutral100\" padding={1} hasRadius>\n <Box padding={4} background=\"neutral0\" hasRadius>\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Metadata (JSON)</Field.Label>\n <Field.Hint>Optional custom metadata</Field.Hint>\n <Textarea\n value={editMetadata}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n setEditMetadata(e.target.value)\n }\n placeholder='{\"key\": \"value\"}'\n />\n </Field.Root>\n </Box>\n </Box>\n </Box>\n </Grid.Item>\n </Grid.Root>\n ) : (\n <Grid.Root gap={6}>\n <Grid.Item col={8} s={12}>\n <Box background=\"neutral100\" padding={1} hasRadius>\n <Box padding={4} background=\"neutral0\" hasRadius>\n <StyledTypography variant=\"beta\">\n Embedding Content\n </StyledTypography>\n {data.content ? (\n <Markdown>{data.content}</Markdown>\n ) : (\n <Typography textColor=\"neutral600\">No content</Typography>\n )}\n </Box>\n </Box>\n </Grid.Item>\n <Grid.Item col={4} s={12}>\n <Box background=\"neutral100\" padding={1} hasRadius>\n <Metadata data={data} />\n </Box>\n </Grid.Item>\n </Grid.Root>\n )}\n </Box>\n </Layouts.Content>\n </Main>\n );\n}\n","import { Page } from '@strapi/strapi/admin';\nimport { Routes, Route } from 'react-router-dom';\n\nimport { HomePage } from './HomePage';\nimport CreateEmbeddings from './CreateEmbeddings';\nimport EmbeddingDetails from './EmbeddingDetails';\n\nconst App = () => {\n return (\n <Routes>\n <Route index element={<HomePage />} />\n <Route path=\"*\" element={<Page.Error />} />\n <Route path=\"/embeddings\" element={<CreateEmbeddings />} />\n <Route path=\"/embeddings/:id\" element={<EmbeddingDetails />} />\n </Routes>\n );\n};\n\nexport { App };\n"],"names":["Link"],"mappings":"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"}
@@ -2,3 +2,4 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en-B4KWt_jN.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -2,3 +2,4 @@ const en = {};
2
2
  export {
3
3
  en as default
4
4
  };
5
+ //# sourceMappingURL=en-Byx4XI2L.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en-Byx4XI2L.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -206,6 +206,42 @@ const MDXEditorStyles = createGlobalStyle`
206
206
  outline: none;
207
207
  }
208
208
 
209
+ /* Placeholder positioning - ensure it's at the top */
210
+ [class*="_contentEditable"] {
211
+ position: relative;
212
+ }
213
+
214
+ [class*="_contentEditable"][data-placeholder]::before {
215
+ position: absolute;
216
+ top: var(--mdx-spacing-3);
217
+ left: var(--mdx-spacing-3);
218
+ color: #a5a5ba;
219
+ pointer-events: none;
220
+ }
221
+
222
+ /* MDXEditor/Lexical placeholder styles */
223
+ [class*="_placeholder"],
224
+ [class*="ContentEditable__placeholder"],
225
+ [class*="editor-placeholder"] {
226
+ position: absolute !important;
227
+ top: var(--mdx-spacing-3) !important;
228
+ left: var(--mdx-spacing-3) !important;
229
+ color: #a5a5ba;
230
+ pointer-events: none;
231
+ overflow: hidden;
232
+ text-overflow: ellipsis;
233
+ user-select: none;
234
+ display: inline-block;
235
+ }
236
+
237
+ /* Editor root wrapper needs relative positioning for placeholder */
238
+ [class*="_rootContentEditableWrapper"],
239
+ [class*="_editorWrapper"] {
240
+ position: relative;
241
+ display: flex;
242
+ flex-direction: column;
243
+ }
244
+
209
245
  /* Heading styles */
210
246
  [class*="_contentEditable"] h1 {
211
247
  font-size: 1.75rem;
@@ -338,6 +374,19 @@ const EditorWrapper = styled(Box)`
338
374
  transition: border-color 0.2s, box-shadow 0.2s;
339
375
  box-shadow: ${({ $isFocused }) => $isFocused ? "0 0 0 2px rgba(73, 69, 255, 0.2)" : "none"};
340
376
  `;
377
+ function ToolbarContents() {
378
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
379
+ /* @__PURE__ */ jsx(UndoRedo, {}),
380
+ /* @__PURE__ */ jsx(Separator, {}),
381
+ /* @__PURE__ */ jsx(BlockTypeSelect, {}),
382
+ /* @__PURE__ */ jsx(Separator, {}),
383
+ /* @__PURE__ */ jsx(BoldItalicUnderlineToggles, {}),
384
+ /* @__PURE__ */ jsx(Separator, {}),
385
+ /* @__PURE__ */ jsx(CreateLink, {}),
386
+ /* @__PURE__ */ jsx(Separator, {}),
387
+ /* @__PURE__ */ jsx(ListsToggle, {})
388
+ ] });
389
+ }
341
390
  function MarkdownEditor({ content, onChange, height = 300 }) {
342
391
  const [isFocused, setIsFocused] = useState(false);
343
392
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -363,17 +412,7 @@ function MarkdownEditor({ content, onChange, height = 300 }) {
363
412
  linkDialogPlugin(),
364
413
  markdownShortcutPlugin(),
365
414
  toolbarPlugin({
366
- toolbarContents: () => /* @__PURE__ */ jsxs(Fragment, { children: [
367
- /* @__PURE__ */ jsx(UndoRedo, {}),
368
- /* @__PURE__ */ jsx(Separator, {}),
369
- /* @__PURE__ */ jsx(BlockTypeSelect, {}),
370
- /* @__PURE__ */ jsx(Separator, {}),
371
- /* @__PURE__ */ jsx(BoldItalicUnderlineToggles, {}),
372
- /* @__PURE__ */ jsx(Separator, {}),
373
- /* @__PURE__ */ jsx(CreateLink, {}),
374
- /* @__PURE__ */ jsx(Separator, {}),
375
- /* @__PURE__ */ jsx(ListsToggle, {})
376
- ] })
415
+ toolbarContents: ToolbarContents
377
416
  })
378
417
  ]
379
418
  }
@@ -387,7 +426,7 @@ const StyledTypography = styled(Typography)`
387
426
  margin-top: 1rem;
388
427
  margin-bottom: 0.5rem;
389
428
  `;
390
- const MAX_CONTENT_LENGTH = 4e3;
429
+ const CHUNK_SIZE = 4e3;
391
430
  function EmbeddingsModal() {
392
431
  const { post, get, put } = useFetchClient();
393
432
  const { toggleNotification } = useNotification();
@@ -460,7 +499,8 @@ function EmbeddingsModal() {
460
499
  }
461
500
  }, [modifiedValues]);
462
501
  const contentLength = content.length;
463
- const isOverLimit = contentLength > MAX_CONTENT_LENGTH;
502
+ const willChunk = contentLength > CHUNK_SIZE;
503
+ const estimatedChunks = willChunk ? Math.ceil(contentLength / (CHUNK_SIZE - 200)) : 1;
464
504
  const isSaved = !!id;
465
505
  function generateMetadata() {
466
506
  return {
@@ -471,7 +511,7 @@ function EmbeddingsModal() {
471
511
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
472
512
  };
473
513
  }
474
- const isValid = title.trim() && content.trim() && !isOverLimit;
514
+ const isValid = title.trim() && content.trim();
475
515
  function handleOpenCreate() {
476
516
  setIsUpdateMode(false);
477
517
  setTitle("");
@@ -500,13 +540,6 @@ function EmbeddingsModal() {
500
540
  });
501
541
  return;
502
542
  }
503
- if (isOverLimit) {
504
- toggleNotification({
505
- type: "warning",
506
- message: `Content exceeds ${MAX_CONTENT_LENGTH} character limit`
507
- });
508
- return;
509
- }
510
543
  setIsLoading(true);
511
544
  try {
512
545
  if (isUpdateMode && existingEmbedding) {
@@ -569,6 +602,12 @@ function EmbeddingsModal() {
569
602
  if (isCheckingExisting) {
570
603
  return /* @__PURE__ */ jsx(Box, { paddingTop: 2, children: /* @__PURE__ */ jsx(Loader, { small: true, children: "Checking embeddings..." }) });
571
604
  }
605
+ let submitButtonText;
606
+ if (isUpdateMode) {
607
+ submitButtonText = isLoading ? "Updating..." : "Update Embedding";
608
+ } else {
609
+ submitButtonText = isLoading ? "Creating..." : "Create Embedding";
610
+ }
572
611
  return /* @__PURE__ */ jsxs(Box, { paddingTop: 2, children: [
573
612
  existingEmbedding ? /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
574
613
  /* @__PURE__ */ jsx(Button, { onClick: handleViewEmbedding, startIcon: /* @__PURE__ */ jsx(Eye, {}), fullWidth: true, children: "View Embedding" }),
@@ -588,11 +627,14 @@ function EmbeddingsModal() {
588
627
  /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: isUpdateMode ? "Update Embedding" : "Create Embedding from Content" }) }),
589
628
  /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Box, { children: [
590
629
  /* @__PURE__ */ jsxs(StyledTypography, { variant: "omega", textColor: "neutral600", children: [
591
- "Chunk Size: ",
630
+ "Content: ",
592
631
  contentLength,
593
- "/",
594
- MAX_CONTENT_LENGTH,
595
- isOverLimit && /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: " (exceeds limit)" })
632
+ " characters",
633
+ willChunk && /* @__PURE__ */ jsxs(Typography, { textColor: "primary600", children: [
634
+ " (will create ~",
635
+ estimatedChunks,
636
+ " embeddings)"
637
+ ] })
596
638
  ] }),
597
639
  /* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
598
640
  /* @__PURE__ */ jsx(Field.Label, { children: "Title" }),
@@ -631,7 +673,7 @@ function EmbeddingsModal() {
631
673
  onClick: handleSubmit,
632
674
  disabled: isLoading || !isValid,
633
675
  loading: isLoading,
634
- children: isLoading ? isUpdateMode ? "Updating..." : "Creating..." : isUpdateMode ? "Update Embedding" : "Create Embedding"
676
+ children: submitButtonText
635
677
  }
636
678
  )
637
679
  ] })
@@ -651,7 +693,7 @@ const index = {
651
693
  defaultMessage: PLUGIN_ID
652
694
  },
653
695
  Component: async () => {
654
- const { App } = await import("./App-4UwemHRe.mjs");
696
+ const { App } = await import("./App-j180lztd.mjs");
655
697
  return App;
656
698
  }
657
699
  });
@@ -694,3 +736,4 @@ export {
694
736
  RobotIcon as R,
695
737
  index as i
696
738
  };
739
+ //# sourceMappingURL=index-B3j0IFUi.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-B3j0IFUi.mjs","sources":["../../admin/src/pluginId.ts","../../admin/src/utils/getTranslation.ts","../../admin/src/components/Initializer.tsx","../../admin/src/components/custom/RobotIcon.tsx","../../admin/src/components/PluginIcon.tsx","../../admin/src/components/custom/MarkdownEditor.tsx","../../admin/src/components/custom/EmbeddingsModal.tsx","../../admin/src/components/custom/EmbeddingsWidget.tsx","../../admin/src/index.tsx"],"sourcesContent":["export const PLUGIN_ID = 'strapi-content-embeddings';\n","import { PLUGIN_ID } from '../pluginId';\n\nconst getTranslation = (id: string) => `${PLUGIN_ID}.${id}`;\n\nexport { getTranslation };\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","import React from \"react\";\n\ninterface RobotIconProps {\n height?: string | number;\n width?: string | number;\n}\n\nexport function RobotIcon({ height = 48, width = 48 }: RobotIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height={height}\n viewBox=\"0 -960 960 960\"\n width={width}\n fill=\"currentColor\"\n >\n <path d=\"M160-120v-220q0-24.75 17.625-42.375T220-400h520q24.75 0 42.375 17.625T800-340v220H160Zm200-320q-83 0-141.5-58.5T160-640q0-83 58.5-141.5T360-840h240q83 0 141.5 58.5T800-640q0 83-58.5 141.5T600-440H360ZM220-180h520v-160H220v160Zm140-320h240q58.333 0 99.167-40.765 40.833-40.764 40.833-99Q740-698 699.167-739 658.333-780 600-780H360q-58.333 0-99.167 40.765-40.833 40.764-40.833 99Q220-582 260.833-541q40.834 41 99.167 41Zm.175-110q12.825 0 21.325-8.675 8.5-8.676 8.5-21.5 0-12.825-8.675-21.325-8.676-8.5-21.5-8.5-12.825 0-21.325 8.675-8.5 8.676-8.5 21.5 0 12.825 8.675 21.325 8.676 8.5 21.5 8.5Zm240 0q12.825 0 21.325-8.675 8.5-8.676 8.5-21.5 0-12.825-8.675-21.325-8.676-8.5-21.5-8.5-12.825 0-21.325 8.675-8.5 8.676-8.5 21.5 0 12.825 8.675 21.325 8.676 8.5 21.5 8.5ZM480-180Zm0-460Z\" />\n </svg>\n );\n}\n","import { RobotIcon } from './custom/RobotIcon';\n\nconst PluginIcon = () => <RobotIcon height={24} width={24} />;\n\nexport { PluginIcon };\n","import { useState } from 'react';\nimport { Box } from '@strapi/design-system';\nimport styled, { createGlobalStyle } from 'styled-components';\nimport {\n MDXEditor,\n headingsPlugin,\n listsPlugin,\n quotePlugin,\n thematicBreakPlugin,\n markdownShortcutPlugin,\n linkPlugin,\n linkDialogPlugin,\n toolbarPlugin,\n BoldItalicUnderlineToggles,\n BlockTypeSelect,\n CreateLink,\n ListsToggle,\n UndoRedo,\n Separator,\n} from '@mdxeditor/editor';\n\ninterface MarkdownEditorProps {\n content: string;\n onChange: (content: string) => void;\n height?: number;\n}\n\nconst MDXEditorStyles = createGlobalStyle`\n /* MDXEditor CSS Variables */\n :root {\n --mdx-spacing-0_5: 0.125rem;\n --mdx-spacing-1: 0.25rem;\n --mdx-spacing-1_5: 0.375rem;\n --mdx-spacing-2: 0.5rem;\n --mdx-spacing-3: 0.75rem;\n --mdx-spacing-4: 1rem;\n --mdx-spacing-36: 9rem;\n --mdx-radius-base: 0.25rem;\n --mdx-radius-medium: 0.375rem;\n --mdx-text-sm: 0.875rem;\n --mdx-baseBg: #f6f6f9;\n --mdx-baseBgActive: #e8e8ec;\n --mdx-basePageBg: #ffffff;\n --mdx-baseBorder: #dcdce4;\n --mdx-baseBorderHover: #b9bbc6;\n --mdx-baseBase: #e0e1e6;\n --mdx-baseTextContrast: #1c2024;\n --mdx-accentText: #4945ff;\n }\n\n /* Toolbar Root - critical for horizontal layout */\n [class*=\"_toolbarRoot\"] {\n z-index: 2;\n display: flex !important;\n flex-direction: row !important;\n flex-wrap: wrap !important;\n gap: var(--mdx-spacing-1);\n border-radius: var(--mdx-radius-medium);\n padding: var(--mdx-spacing-1_5);\n align-items: center !important;\n overflow-x: auto;\n position: sticky;\n top: 0;\n background-color: var(--mdx-baseBg) !important;\n border-bottom: 1px solid var(--mdx-baseBorder);\n width: 100%;\n }\n\n [class*=\"_toolbarRoot\"] div[role='separator'] {\n margin: var(--mdx-spacing-2) var(--mdx-spacing-1);\n border-left: 1px solid var(--mdx-baseBorder);\n border-right: 1px solid var(--mdx-baseBase);\n height: var(--mdx-spacing-4);\n }\n\n [class*=\"_toolbarRoot\"] svg {\n color: var(--mdx-baseTextContrast);\n display: block;\n }\n\n /* Toolbar button groups */\n [class*=\"_toolbarGroupOfGroups\"] {\n display: flex;\n margin: 0 var(--mdx-spacing-1);\n }\n\n [class*=\"_toolbarToggleSingleGroup\"] {\n display: flex;\n align-items: center;\n white-space: nowrap;\n }\n\n /* Toolbar buttons and toggle items */\n [class*=\"_toolbarToggleItem\"],\n [class*=\"_toolbarButton\"] {\n border: 0;\n background-color: transparent;\n font-size: inherit;\n appearance: none;\n box-sizing: border-box;\n cursor: pointer;\n padding: var(--mdx-spacing-0_5);\n border-radius: var(--mdx-radius-base);\n }\n\n [class*=\"_toolbarToggleItem\"]:hover,\n [class*=\"_toolbarButton\"]:hover {\n background-color: var(--mdx-baseBgActive);\n }\n\n [class*=\"_toolbarToggleItem\"][data-state='on'],\n [class*=\"_toolbarButton\"][data-state='on'],\n [class*=\"_toolbarToggleItem\"]:active,\n [class*=\"_toolbarButton\"]:active {\n color: var(--mdx-baseTextContrast);\n background-color: var(--mdx-baseBgActive);\n }\n\n /* Block type select dropdown */\n [class*=\"_toolbarNodeKindSelectTrigger\"],\n [class*=\"_selectTrigger\"] {\n border: 0;\n display: flex;\n color: inherit;\n align-items: center;\n width: var(--mdx-spacing-36);\n padding: var(--mdx-spacing-0_5) var(--mdx-spacing-1);\n padding-inline-start: var(--mdx-spacing-2);\n border-radius: var(--mdx-radius-medium);\n white-space: nowrap;\n font-size: var(--mdx-text-sm);\n background-color: var(--mdx-basePageBg);\n margin: 0 var(--mdx-spacing-1);\n cursor: pointer;\n }\n\n /* Dropdown containers */\n [class*=\"_toolbarNodeKindSelectContainer\"],\n [class*=\"_selectContainer\"] {\n filter: drop-shadow(0 2px 2px rgb(0 0 0 / 0.2));\n z-index: 100;\n width: var(--mdx-spacing-36);\n border-radius: var(--mdx-radius-base);\n background-color: var(--mdx-basePageBg);\n font-size: var(--mdx-text-sm);\n }\n\n /* Select items */\n [class*=\"_toolbarNodeKindSelectItem\"],\n [class*=\"_selectItem\"] {\n cursor: pointer;\n display: flex;\n padding: var(--mdx-spacing-2);\n }\n\n [class*=\"_toolbarNodeKindSelectItem\"][data-highlighted],\n [class*=\"_selectItem\"][data-highlighted],\n [class*=\"_toolbarNodeKindSelectItem\"][data-state='checked'],\n [class*=\"_selectItem\"][data-state='checked'] {\n background-color: var(--mdx-baseBg);\n outline: none;\n }\n\n /* Dropdown arrow */\n [class*=\"_selectDropdownArrow\"] {\n margin-left: auto;\n display: flex;\n align-items: center;\n }\n\n /* Content editable area */\n [class*=\"_contentEditable\"] {\n box-sizing: border-box;\n width: 100%;\n color: var(--mdx-baseTextContrast);\n padding: var(--mdx-spacing-3);\n min-height: 200px;\n outline: none;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n font-size: 14px;\n line-height: 1.6;\n }\n\n [class*=\"_contentEditable\"]:focus {\n outline: none;\n }\n\n /* Placeholder positioning - ensure it's at the top */\n [class*=\"_contentEditable\"] {\n position: relative;\n }\n\n [class*=\"_contentEditable\"][data-placeholder]::before {\n position: absolute;\n top: var(--mdx-spacing-3);\n left: var(--mdx-spacing-3);\n color: #a5a5ba;\n pointer-events: none;\n }\n\n /* MDXEditor/Lexical placeholder styles */\n [class*=\"_placeholder\"],\n [class*=\"ContentEditable__placeholder\"],\n [class*=\"editor-placeholder\"] {\n position: absolute !important;\n top: var(--mdx-spacing-3) !important;\n left: var(--mdx-spacing-3) !important;\n color: #a5a5ba;\n pointer-events: none;\n overflow: hidden;\n text-overflow: ellipsis;\n user-select: none;\n display: inline-block;\n }\n\n /* Editor root wrapper needs relative positioning for placeholder */\n [class*=\"_rootContentEditableWrapper\"],\n [class*=\"_editorWrapper\"] {\n position: relative;\n display: flex;\n flex-direction: column;\n }\n\n /* Heading styles */\n [class*=\"_contentEditable\"] h1 {\n font-size: 1.75rem;\n font-weight: 600;\n margin: 0 0 1rem;\n }\n\n [class*=\"_contentEditable\"] h2 {\n font-size: 1.5rem;\n font-weight: 600;\n margin: 1rem 0 0.75rem;\n }\n\n [class*=\"_contentEditable\"] h3 {\n font-size: 1.25rem;\n font-weight: 600;\n margin: 1rem 0 0.5rem;\n }\n\n /* Paragraph and list styles */\n [class*=\"_contentEditable\"] p {\n margin: 0 0 1rem;\n }\n\n [class*=\"_contentEditable\"] ul,\n [class*=\"_contentEditable\"] ol {\n margin: 0 0 1rem;\n padding-left: 1.5rem;\n }\n\n [class*=\"_contentEditable\"] li {\n margin: 0.25rem 0;\n }\n\n /* Code styles */\n [class*=\"_contentEditable\"] code {\n background: #f0f0f5;\n padding: 0.2em 0.4em;\n border-radius: 3px;\n font-family: \"Monaco\", \"Menlo\", monospace;\n font-size: 0.9em;\n }\n\n [class*=\"_contentEditable\"] pre {\n background: #2d2d2d;\n color: #f8f8f2;\n padding: 1rem;\n border-radius: 4px;\n overflow-x: auto;\n margin: 0 0 1rem;\n }\n\n [class*=\"_contentEditable\"] pre code {\n background: none;\n padding: 0;\n }\n\n /* Blockquote */\n [class*=\"_contentEditable\"] blockquote {\n border-left: 3px solid #dcdce4;\n margin: 0 0 1rem;\n padding-left: 1rem;\n color: #666;\n }\n\n /* Links */\n [class*=\"_contentEditable\"] a {\n color: #4945ff;\n text-decoration: underline;\n }\n\n /* Horizontal rule */\n [class*=\"_contentEditable\"] hr {\n border: none;\n border-top: 1px solid #dcdce4;\n margin: 1.5rem 0;\n }\n\n /* Editor root */\n [class*=\"_editorRoot\"] {\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n color: var(--mdx-baseTextContrast);\n background: var(--mdx-basePageBg);\n }\n\n /* Link dialog */\n [class*=\"_linkDialogPopoverContent\"] {\n display: flex;\n flex-direction: column;\n gap: var(--mdx-spacing-2);\n padding: var(--mdx-spacing-3);\n background-color: var(--mdx-basePageBg);\n border-radius: var(--mdx-radius-medium);\n box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);\n z-index: 100;\n }\n\n [class*=\"_linkDialogInputWrapper\"] {\n display: flex;\n gap: var(--mdx-spacing-1);\n }\n\n [class*=\"_linkDialogInputWrapper\"] input {\n flex: 1;\n padding: var(--mdx-spacing-1) var(--mdx-spacing-2);\n border: 1px solid var(--mdx-baseBorder);\n border-radius: var(--mdx-radius-base);\n font-size: var(--mdx-text-sm);\n }\n\n [class*=\"_linkDialogInputWrapper\"] button {\n padding: var(--mdx-spacing-1) var(--mdx-spacing-2);\n background-color: var(--mdx-accentText);\n color: white;\n border: none;\n border-radius: var(--mdx-radius-base);\n cursor: pointer;\n }\n\n /* Popover positioning */\n [data-radix-popper-content-wrapper] {\n z-index: 100 !important;\n }\n`;\n\nconst EditorWrapper = styled(Box)<{ $isFocused: boolean }>`\n border: 1px solid ${({ $isFocused }) => ($isFocused ? '#4945ff' : '#dcdce4')};\n border-radius: 4px;\n overflow: hidden;\n background: #fff;\n transition: border-color 0.2s, box-shadow 0.2s;\n box-shadow: ${({ $isFocused }) => ($isFocused ? '0 0 0 2px rgba(73, 69, 255, 0.2)' : 'none')};\n`;\n\n// Toolbar contents component defined outside to prevent re-renders\nfunction ToolbarContents() {\n return (\n <>\n <UndoRedo />\n <Separator />\n <BlockTypeSelect />\n <Separator />\n <BoldItalicUnderlineToggles />\n <Separator />\n <CreateLink />\n <Separator />\n <ListsToggle />\n </>\n );\n}\n\nexport function MarkdownEditor({ content, onChange, height = 300 }: Readonly<MarkdownEditorProps>) {\n const [isFocused, setIsFocused] = useState(false);\n\n return (\n <>\n <MDXEditorStyles />\n <EditorWrapper\n $isFocused={isFocused}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n >\n <div style={{ minHeight: `${height}px` }}>\n <MDXEditor\n markdown={content}\n onChange={onChange}\n placeholder=\"Write your content here...\"\n plugins={[\n headingsPlugin(),\n listsPlugin(),\n quotePlugin(),\n thematicBreakPlugin(),\n linkPlugin(),\n linkDialogPlugin(),\n markdownShortcutPlugin(),\n toolbarPlugin({\n toolbarContents: ToolbarContents,\n }),\n ]}\n />\n </div>\n </EditorWrapper>\n </>\n );\n}\n","import React, { useState, useEffect } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport styled from \"styled-components\";\nimport qs from \"qs\";\nimport {\n unstable_useContentManagerContext as useContentManagerContext,\n useFetchClient,\n useNotification,\n} from \"@strapi/strapi/admin\";\nimport {\n Button,\n Typography,\n Box,\n Modal,\n Field,\n TextInput,\n Loader,\n Flex,\n} from \"@strapi/design-system\";\nimport { Plus, Eye, Pencil } from \"@strapi/icons\";\nimport { PLUGIN_ID } from \"../../pluginId\";\nimport { MarkdownEditor } from \"./MarkdownEditor\";\n\nconst StyledTypography = styled(Typography)`\n display: block;\n margin-top: 1rem;\n margin-bottom: 0.5rem;\n`;\n\nconst CHUNK_SIZE = 4000; // Content over this will be auto-chunked\n\ninterface ExistingEmbedding {\n documentId: string;\n title: string;\n content?: string;\n}\n\nexport function EmbeddingsModal() {\n const { post, get, put } = useFetchClient();\n const { toggleNotification } = useNotification();\n const navigate = useNavigate();\n\n // Access content manager context\n const context = useContentManagerContext();\n const { form, id, slug, collectionType } = context;\n\n const modifiedValues = form?.values || {};\n\n const [isVisible, setIsVisible] = useState(false);\n const [isUpdateMode, setIsUpdateMode] = useState(false);\n const [title, setTitle] = useState(\"\");\n const [content, setContent] = useState(\"\");\n const [fieldName, setFieldName] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const [isCheckingExisting, setIsCheckingExisting] = useState(true);\n const [existingEmbedding, setExistingEmbedding] = useState<ExistingEmbedding | null>(null);\n\n // Check for existing embedding when component mounts or id changes\n useEffect(() => {\n async function checkExistingEmbedding() {\n if (!id || !slug) {\n setIsCheckingExisting(false);\n return;\n }\n\n try {\n // Query embeddings filtered by metadata containing this documentId\n const query = qs.stringify({\n filters: {\n $and: [\n { collectionType: { $eq: slug } },\n { metadata: { $containsi: id } },\n ],\n },\n });\n\n const response = await get(`/${PLUGIN_ID}/embeddings/find?${query}`);\n\n if (response.data?.data?.length > 0) {\n // Found existing embedding for this content\n setExistingEmbedding({\n documentId: response.data.data[0].documentId,\n title: response.data.data[0].title,\n content: response.data.data[0].content,\n });\n }\n } catch (error) {\n console.error(\"Failed to check for existing embedding:\", error);\n } finally {\n setIsCheckingExisting(false);\n }\n }\n\n checkExistingEmbedding();\n }, [id, slug, get]);\n\n // Find text content from form values\n useEffect(() => {\n if (!modifiedValues) return;\n\n // Look for common text field names\n const textFieldNames = [\"content\", \"description\", \"body\", \"text\", \"richtext\", \"markdown\"];\n\n for (const fieldName of textFieldNames) {\n const value = modifiedValues[fieldName];\n if (value) {\n setFieldName(fieldName);\n // Handle different content formats\n if (typeof value === \"string\" && value.trim()) {\n setContent(value);\n break;\n } else if (Array.isArray(value)) {\n // Blocks format - extract text\n const text = value\n .map((block: any) => {\n if (block.children) {\n return block.children.map((child: any) => child.text || \"\").join(\"\");\n }\n return \"\";\n })\n .join(\"\\n\\n\");\n if (text.trim()) {\n setContent(text);\n break;\n }\n }\n }\n }\n }, [modifiedValues]);\n\n const contentLength = content.length;\n const willChunk = contentLength > CHUNK_SIZE;\n const estimatedChunks = willChunk ? Math.ceil(contentLength / (CHUNK_SIZE - 200)) : 1;\n // Check if content is saved (has an id) - don't require publish\n const isSaved = !!id;\n\n // Auto-generate metadata from collection context\n function generateMetadata(): Record<string, any> {\n return {\n source: \"content-manager\",\n collectionType: slug || collectionType || \"unknown\",\n fieldName: fieldName || \"content\",\n documentId: id,\n updatedAt: new Date().toISOString(),\n };\n }\n\n const isValid = title.trim() && content.trim(); // No length limit - auto-chunks if needed\n\n function handleOpenCreate() {\n setIsUpdateMode(false);\n setTitle(\"\");\n // Content is already set from form values\n setIsVisible(true);\n }\n\n function handleOpenUpdate() {\n if (existingEmbedding) {\n setIsUpdateMode(true);\n setTitle(existingEmbedding.title);\n // Use current form content for update\n setIsVisible(true);\n }\n }\n\n async function handleSubmit(e: React.FormEvent) {\n e.preventDefault();\n\n if (!title.trim()) {\n toggleNotification({\n type: \"warning\",\n message: \"Embeddings title is required\",\n });\n return;\n }\n\n if (!content.trim()) {\n toggleNotification({\n type: \"warning\",\n message: \"Embeddings content is required\",\n });\n return;\n }\n\n setIsLoading(true);\n\n try {\n if (isUpdateMode && existingEmbedding) {\n // Update existing embedding\n const result = await put(`/${PLUGIN_ID}/embeddings/update-embedding/${existingEmbedding.documentId}`, {\n data: {\n title: title.trim(),\n content: content.trim(),\n metadata: generateMetadata(),\n },\n });\n\n setExistingEmbedding({\n documentId: result.data.documentId,\n title: result.data.title,\n content: result.data.content,\n });\n setIsVisible(false);\n toggleNotification({\n type: \"success\",\n message: \"Embedding updated successfully\",\n });\n } else {\n // Create new embedding\n const result = await post(`/${PLUGIN_ID}/embeddings/create-embedding`, {\n data: {\n title: title.trim(),\n content: content.trim(),\n collectionType: slug || collectionType,\n fieldName,\n metadata: generateMetadata(),\n },\n });\n\n setExistingEmbedding({\n documentId: result.data.documentId,\n title: result.data.title,\n content: result.data.content,\n });\n setIsVisible(false);\n toggleNotification({\n type: \"success\",\n message: \"Embedding created successfully\",\n });\n }\n } catch (error: any) {\n console.error(\"Failed to save embedding:\", error);\n toggleNotification({\n type: \"danger\",\n message: error.message || \"Failed to save embedding\",\n });\n } finally {\n setIsLoading(false);\n }\n }\n\n function handleViewEmbedding() {\n if (existingEmbedding?.documentId) {\n navigate(`/plugins/${PLUGIN_ID}/embeddings/${existingEmbedding.documentId}`);\n }\n }\n\n // Don't render if not in edit view context\n if (!form || !id) {\n return null;\n }\n\n // Show loading state while checking for existing embedding\n if (isCheckingExisting) {\n return (\n <Box paddingTop={2}>\n <Loader small>Checking embeddings...</Loader>\n </Box>\n );\n }\n\n // Determine button text based on mode and loading state\n let submitButtonText: string;\n if (isUpdateMode) {\n submitButtonText = isLoading ? \"Updating...\" : \"Update Embedding\";\n } else {\n submitButtonText = isLoading ? \"Creating...\" : \"Create Embedding\";\n }\n\n return (\n <Box paddingTop={2}>\n {existingEmbedding ? (\n <Flex direction=\"column\" gap={2}>\n <Button onClick={handleViewEmbedding} startIcon={<Eye />} fullWidth>\n View Embedding\n </Button>\n <Button onClick={handleOpenUpdate} startIcon={<Pencil />} variant=\"secondary\" fullWidth>\n Update Embedding\n </Button>\n </Flex>\n ) : (\n <Button\n onClick={handleOpenCreate}\n startIcon={<Plus />}\n disabled={!isSaved}\n fullWidth\n >\n Create Embedding\n </Button>\n )}\n\n {!isSaved && !existingEmbedding && (\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ display: \"block\", marginTop: \"0.5rem\" }}>\n Save content first to create embedding\n </Typography>\n )}\n\n <Modal.Root open={isVisible} onOpenChange={setIsVisible}>\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>\n {isUpdateMode ? \"Update Embedding\" : \"Create Embedding from Content\"}\n </Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <Box>\n <StyledTypography variant=\"omega\" textColor=\"neutral600\">\n Content: {contentLength} characters\n {willChunk && (\n <Typography textColor=\"primary600\"> (will create ~{estimatedChunks} embeddings)</Typography>\n )}\n </StyledTypography>\n\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Title</Field.Label>\n <TextInput\n placeholder=\"Enter embedding title\"\n value={title}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setTitle(e.target.value)\n }\n />\n </Field.Root>\n </Box>\n\n <Box marginBottom={4}>\n <Field.Root>\n <Field.Label>Content</Field.Label>\n <Field.Hint>\n {fieldName ? `From field: ${fieldName}` : \"Enter content manually\"}\n {isUpdateMode && \" - Changes will regenerate the embedding vector\"}\n </Field.Hint>\n </Field.Root>\n <MarkdownEditor\n content={content}\n onChange={setContent}\n height={200}\n />\n </Box>\n </Box>\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close>\n <Button variant=\"tertiary\">Cancel</Button>\n </Modal.Close>\n <Button\n onClick={handleSubmit}\n disabled={isLoading || !isValid}\n loading={isLoading}\n >\n {submitButtonText}\n </Button>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box } from \"@strapi/design-system\";\nimport { EmbeddingsModal } from \"./EmbeddingsModal\";\n\nexport function EmbeddingsWidget() {\n return (\n <Box>\n <EmbeddingsModal />\n </Box>\n );\n}\n","import React from 'react';\nimport { getTranslation } from './utils/getTranslation';\nimport { PLUGIN_ID } from './pluginId';\nimport { Initializer } from './components/Initializer';\nimport { PluginIcon } from './components/PluginIcon';\nimport { EmbeddingsWidget } from './components/custom/EmbeddingsWidget';\n\nexport default {\n register(app: any) {\n app.addMenuLink({\n to: `plugins/${PLUGIN_ID}`,\n icon: PluginIcon,\n intlLabel: {\n id: `${PLUGIN_ID}.plugin.name`,\n defaultMessage: PLUGIN_ID,\n },\n Component: async () => {\n const { App } = await import('./pages/App');\n return App;\n },\n });\n\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n },\n\n bootstrap(app: any) {\n app.getPlugin('content-manager').injectComponent('editView', 'right-links', {\n name: \"open-ai-embeddings\",\n Component: () => <EmbeddingsWidget />\n })\n },\n\n async registerTrads(app: any) {\n const { locales } = app;\n\n const importedTranslations = await Promise.all(\n (locales as string[]).map((locale) => {\n return import(`./translations/${locale}.json`)\n .then(({ default: data }) => {\n return {\n data: getTranslation(data),\n locale,\n };\n })\n .catch(() => {\n return {\n data: {},\n locale,\n };\n });\n })\n );\n\n return importedTranslations;\n },\n};\n"],"names":["useContentManagerContext","fieldName"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAO,MAAM,YAAY;ACEzB,MAAM,iBAAiB,CAAC,OAAe,GAAG,SAAS,IAAI,EAAE;ACMzD,MAAM,cAAc,CAAC,EAAE,gBAAkC;AACjD,QAAA,MAAM,OAAO,SAAS;AAE5B,YAAU,MAAM;AACd,QAAI,QAAQ,SAAS;AAAA,EACvB,GAAG,EAAE;AAEE,SAAA;AACT;ACTO,SAAS,UAAU,EAAE,SAAS,IAAI,QAAQ,MAAsB;AAEnE,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN;AAAA,MACA,SAAQ;AAAA,MACR;AAAA,MACA,MAAK;AAAA,MAEL,UAAA,oBAAC,QAAK,EAAA,GAAE,8wBAA8wB,CAAA;AAAA,IAAA;AAAA,EACxxB;AAEJ;ACjBA,MAAM,aAAa,MAAM,oBAAC,aAAU,QAAQ,IAAI,OAAO,IAAI;ACyB3D,MAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiUxB,MAAM,gBAAgB,OAAO,GAAG;AAAA,sBACV,CAAC,EAAE,WAAA,MAAkB,aAAa,YAAY,SAAU;AAAA;AAAA;AAAA;AAAA;AAAA,gBAK9D,CAAC,EAAE,WAAA,MAAkB,aAAa,qCAAqC,MAAO;AAAA;AAI9F,SAAS,kBAAkB;AACzB,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA,oBAAC,UAAS,EAAA;AAAA,wBACT,WAAU,EAAA;AAAA,wBACV,iBAAgB,EAAA;AAAA,wBAChB,WAAU,EAAA;AAAA,wBACV,4BAA2B,EAAA;AAAA,wBAC3B,WAAU,EAAA;AAAA,wBACV,YAAW,EAAA;AAAA,wBACX,WAAU,EAAA;AAAA,wBACV,aAAY,CAAA,CAAA;AAAA,EAAA,GACf;AAEJ;AAEO,SAAS,eAAe,EAAE,SAAS,UAAU,SAAS,OAAsC;AACjG,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA,oBAAC,iBAAgB,EAAA;AAAA,IACjB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,YAAY;AAAA,QACZ,SAAS,MAAM,aAAa,IAAI;AAAA,QAChC,QAAQ,MAAM,aAAa,KAAK;AAAA,QAEhC,UAAA,oBAAC,SAAI,OAAO,EAAE,WAAW,GAAG,MAAM,KAChC,GAAA,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,UAAU;AAAA,YACV;AAAA,YACA,aAAY;AAAA,YACZ,SAAS;AAAA,cACP,eAAe;AAAA,cACf,YAAY;AAAA,cACZ,YAAY;AAAA,cACZ,oBAAoB;AAAA,cACpB,WAAW;AAAA,cACX,iBAAiB;AAAA,cACjB,uBAAuB;AAAA,cACvB,cAAc;AAAA,gBACZ,iBAAiB;AAAA,cAClB,CAAA;AAAA,YAAA;AAAA,UACH;AAAA,QAAA,EAEJ,CAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;AChYA,MAAM,mBAAmB,OAAO,UAAU;AAAA;AAAA;AAAA;AAAA;AAM1C,MAAM,aAAa;AAQZ,SAAS,kBAAkB;AAChC,QAAM,EAAE,MAAM,KAAK,IAAA,IAAQ,eAAe;AACpC,QAAA,EAAE,mBAAmB,IAAI,gBAAgB;AAC/C,QAAM,WAAW,YAAY;AAG7B,QAAM,UAAUA,kCAAyB;AACzC,QAAM,EAAE,MAAM,IAAI,MAAM,eAAmB,IAAA;AAErC,QAAA,iBAAiB,MAAM,UAAU,CAAC;AAExC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,EAAE;AACzC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,EAAE;AAC7C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,IAAI;AACjE,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAmC,IAAI;AAGzF,YAAU,MAAM;AACd,mBAAe,yBAAyB;AAClC,UAAA,CAAC,MAAM,CAAC,MAAM;AAChB,8BAAsB,KAAK;AAC3B;AAAA,MAAA;AAGE,UAAA;AAEI,cAAA,QAAQ,GAAG,UAAU;AAAA,UACzB,SAAS;AAAA,YACP,MAAM;AAAA,cACJ,EAAE,gBAAgB,EAAE,KAAK,OAAO;AAAA,cAChC,EAAE,UAAU,EAAE,YAAY,GAAK,EAAA;AAAA,YAAA;AAAA,UACjC;AAAA,QACF,CACD;AAED,cAAM,WAAW,MAAM,IAAI,IAAI,SAAS,oBAAoB,KAAK,EAAE;AAEnE,YAAI,SAAS,MAAM,MAAM,SAAS,GAAG;AAEd,+BAAA;AAAA,YACnB,YAAY,SAAS,KAAK,KAAK,CAAC,EAAE;AAAA,YAClC,OAAO,SAAS,KAAK,KAAK,CAAC,EAAE;AAAA,YAC7B,SAAS,SAAS,KAAK,KAAK,CAAC,EAAE;AAAA,UAAA,CAChC;AAAA,QAAA;AAAA,eAEI,OAAO;AACN,gBAAA,MAAM,2CAA2C,KAAK;AAAA,MAAA,UAC9D;AACA,8BAAsB,KAAK;AAAA,MAAA;AAAA,IAC7B;AAGqB,2BAAA;AAAA,EACtB,GAAA,CAAC,IAAI,MAAM,GAAG,CAAC;AAGlB,YAAU,MAAM;AACd,QAAI,CAAC,eAAgB;AAGrB,UAAM,iBAAiB,CAAC,WAAW,eAAe,QAAQ,QAAQ,YAAY,UAAU;AAExF,eAAWC,cAAa,gBAAgB;AAChC,YAAA,QAAQ,eAAeA,UAAS;AACtC,UAAI,OAAO;AACT,qBAAaA,UAAS;AAEtB,YAAI,OAAO,UAAU,YAAY,MAAM,QAAQ;AAC7C,qBAAW,KAAK;AAChB;AAAA,QACS,WAAA,MAAM,QAAQ,KAAK,GAAG;AAE/B,gBAAM,OAAO,MACV,IAAI,CAAC,UAAe;AACnB,gBAAI,MAAM,UAAU;AACX,qBAAA,MAAM,SAAS,IAAI,CAAC,UAAe,MAAM,QAAQ,EAAE,EAAE,KAAK,EAAE;AAAA,YAAA;AAE9D,mBAAA;AAAA,UAAA,CACR,EACA,KAAK,MAAM;AACV,cAAA,KAAK,QAAQ;AACf,uBAAW,IAAI;AACf;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,GACC,CAAC,cAAc,CAAC;AAEnB,QAAM,gBAAgB,QAAQ;AAC9B,QAAM,YAAY,gBAAgB;AAClC,QAAM,kBAAkB,YAAY,KAAK,KAAK,iBAAiB,aAAa,IAAI,IAAI;AAE9E,QAAA,UAAU,CAAC,CAAC;AAGlB,WAAS,mBAAwC;AACxC,WAAA;AAAA,MACL,QAAQ;AAAA,MACR,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,WAAW,aAAa;AAAA,MACxB,YAAY;AAAA,MACZ,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,EAAA;AAGF,QAAM,UAAU,MAAM,KAAK,KAAK,QAAQ,KAAK;AAE7C,WAAS,mBAAmB;AAC1B,oBAAgB,KAAK;AACrB,aAAS,EAAE;AAEX,iBAAa,IAAI;AAAA,EAAA;AAGnB,WAAS,mBAAmB;AAC1B,QAAI,mBAAmB;AACrB,sBAAgB,IAAI;AACpB,eAAS,kBAAkB,KAAK;AAEhC,mBAAa,IAAI;AAAA,IAAA;AAAA,EACnB;AAGF,iBAAe,aAAa,GAAoB;AAC9C,MAAE,eAAe;AAEb,QAAA,CAAC,MAAM,QAAQ;AACE,yBAAA;AAAA,QACjB,MAAM;AAAA,QACN,SAAS;AAAA,MAAA,CACV;AACD;AAAA,IAAA;AAGE,QAAA,CAAC,QAAQ,QAAQ;AACA,yBAAA;AAAA,QACjB,MAAM;AAAA,QACN,SAAS;AAAA,MAAA,CACV;AACD;AAAA,IAAA;AAGF,iBAAa,IAAI;AAEb,QAAA;AACF,UAAI,gBAAgB,mBAAmB;AAE/B,cAAA,SAAS,MAAM,IAAI,IAAI,SAAS,gCAAgC,kBAAkB,UAAU,IAAI;AAAA,UACpG,MAAM;AAAA,YACJ,OAAO,MAAM,KAAK;AAAA,YAClB,SAAS,QAAQ,KAAK;AAAA,YACtB,UAAU,iBAAiB;AAAA,UAAA;AAAA,QAC7B,CACD;AAEoB,6BAAA;AAAA,UACnB,YAAY,OAAO,KAAK;AAAA,UACxB,OAAO,OAAO,KAAK;AAAA,UACnB,SAAS,OAAO,KAAK;AAAA,QAAA,CACtB;AACD,qBAAa,KAAK;AACC,2BAAA;AAAA,UACjB,MAAM;AAAA,UACN,SAAS;AAAA,QAAA,CACV;AAAA,MAAA,OACI;AAEL,cAAM,SAAS,MAAM,KAAK,IAAI,SAAS,gCAAgC;AAAA,UACrE,MAAM;AAAA,YACJ,OAAO,MAAM,KAAK;AAAA,YAClB,SAAS,QAAQ,KAAK;AAAA,YACtB,gBAAgB,QAAQ;AAAA,YACxB;AAAA,YACA,UAAU,iBAAiB;AAAA,UAAA;AAAA,QAC7B,CACD;AAEoB,6BAAA;AAAA,UACnB,YAAY,OAAO,KAAK;AAAA,UACxB,OAAO,OAAO,KAAK;AAAA,UACnB,SAAS,OAAO,KAAK;AAAA,QAAA,CACtB;AACD,qBAAa,KAAK;AACC,2BAAA;AAAA,UACjB,MAAM;AAAA,UACN,SAAS;AAAA,QAAA,CACV;AAAA,MAAA;AAAA,aAEI,OAAY;AACX,cAAA,MAAM,6BAA6B,KAAK;AAC7B,yBAAA;AAAA,QACjB,MAAM;AAAA,QACN,SAAS,MAAM,WAAW;AAAA,MAAA,CAC3B;AAAA,IAAA,UACD;AACA,mBAAa,KAAK;AAAA,IAAA;AAAA,EACpB;AAGF,WAAS,sBAAsB;AAC7B,QAAI,mBAAmB,YAAY;AACjC,eAAS,YAAY,SAAS,eAAe,kBAAkB,UAAU,EAAE;AAAA,IAAA;AAAA,EAC7E;AAIE,MAAA,CAAC,QAAQ,CAAC,IAAI;AACT,WAAA;AAAA,EAAA;AAIT,MAAI,oBAAoB;AAEpB,WAAA,oBAAC,OAAI,YAAY,GACf,8BAAC,QAAO,EAAA,OAAK,MAAC,UAAA,yBAAA,CAAsB,EACtC,CAAA;AAAA,EAAA;AAKA,MAAA;AACJ,MAAI,cAAc;AAChB,uBAAmB,YAAY,gBAAgB;AAAA,EAAA,OAC1C;AACL,uBAAmB,YAAY,gBAAgB;AAAA,EAAA;AAI/C,SAAA,qBAAC,KAAI,EAAA,YAAY,GACd,UAAA;AAAA,IAAA,oBACE,qBAAA,MAAA,EAAK,WAAU,UAAS,KAAK,GAC5B,UAAA;AAAA,MAAC,oBAAA,QAAA,EAAO,SAAS,qBAAqB,+BAAY,KAAI,CAAA,CAAA,GAAI,WAAS,MAAC,UAEpE,iBAAA,CAAA;AAAA,MACC,oBAAA,QAAA,EAAO,SAAS,kBAAkB,WAAW,oBAAC,QAAO,CAAA,CAAA,GAAI,SAAQ,aAAY,WAAS,MAAC,UAExF,mBAAA,CAAA;AAAA,IAAA,EAAA,CACF,IAEA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS;AAAA,QACT,+BAAY,MAAK,EAAA;AAAA,QACjB,UAAU,CAAC;AAAA,QACX,WAAS;AAAA,QACV,UAAA;AAAA,MAAA;AAAA,IAED;AAAA,IAGD,CAAC,WAAW,CAAC,qBACZ,oBAAC,cAAW,SAAQ,MAAK,WAAU,cAAa,OAAO,EAAE,SAAS,SAAS,WAAW,YAAY,UAElG,0CAAA;AAAA,IAGF,oBAAC,MAAM,MAAN,EAAW,MAAM,WAAW,cAAc,cACzC,UAAA,qBAAC,MAAM,SAAN,EACC,UAAA;AAAA,MAAC,oBAAA,MAAM,QAAN,EACC,UAAC,oBAAA,MAAM,OAAN,EACE,UAAA,eAAe,qBAAqB,gCAAA,CACvC,EACF,CAAA;AAAA,MACC,oBAAA,MAAM,MAAN,EACC,+BAAC,KACC,EAAA,UAAA;AAAA,QAAA,qBAAC,kBAAiB,EAAA,SAAQ,SAAQ,WAAU,cAAa,UAAA;AAAA,UAAA;AAAA,UAC7C;AAAA,UAAc;AAAA,UACvB,aACC,qBAAC,YAAW,EAAA,WAAU,cAAa,UAAA;AAAA,YAAA;AAAA,YAAgB;AAAA,YAAgB;AAAA,UAAA,EAAY,CAAA;AAAA,QAAA,GAEnF;AAAA,4BAEC,KAAI,EAAA,cAAc,GACjB,UAAC,qBAAA,MAAM,MAAN,EACC,UAAA;AAAA,UAAC,oBAAA,MAAM,OAAN,EAAY,UAAK,QAAA,CAAA;AAAA,UAClB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,aAAY;AAAA,cACZ,OAAO;AAAA,cACP,UAAU,CAAC,MACT,SAAS,EAAE,OAAO,KAAK;AAAA,YAAA;AAAA,UAAA;AAAA,QAE3B,EAAA,CACF,EACF,CAAA;AAAA,QAEA,qBAAC,KAAI,EAAA,cAAc,GACjB,UAAA;AAAA,UAAC,qBAAA,MAAM,MAAN,EACC,UAAA;AAAA,YAAC,oBAAA,MAAM,OAAN,EAAY,UAAO,UAAA,CAAA;AAAA,YACpB,qBAAC,MAAM,MAAN,EACE,UAAA;AAAA,cAAY,YAAA,eAAe,SAAS,KAAK;AAAA,cACzC,gBAAgB;AAAA,YAAA,EACnB,CAAA;AAAA,UAAA,GACF;AAAA,UACA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC;AAAA,cACA,UAAU;AAAA,cACV,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV,EACF,CAAA;AAAA,MAAA,EAAA,CACF,EACF,CAAA;AAAA,MACA,qBAAC,MAAM,QAAN,EACC,UAAA;AAAA,QAAC,oBAAA,MAAM,OAAN,EACC,UAAA,oBAAC,UAAO,SAAQ,YAAW,oBAAM,EACnC,CAAA;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS;AAAA,YACT,UAAU,aAAa,CAAC;AAAA,YACxB,SAAS;AAAA,YAER,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACH,EACF,CAAA;AAAA,IAAA,EAAA,CACF,EACF,CAAA;AAAA,EAAA,GACF;AAEJ;AClWO,SAAS,mBAAmB;AACjC,SACG,oBAAA,KAAA,EACC,UAAC,oBAAA,iBAAA,CAAgB,CAAA,GACnB;AAEJ;ACHA,MAAe,QAAA;AAAA,EACb,SAAS,KAAU;AACjB,QAAI,YAAY;AAAA,MACd,IAAI,WAAW,SAAS;AAAA,MACxB,MAAM;AAAA,MACN,WAAW;AAAA,QACT,IAAI,GAAG,SAAS;AAAA,QAChB,gBAAgB;AAAA,MAClB;AAAA,MACA,WAAW,YAAY;AACrB,cAAM,EAAE,IAAA,IAAQ,MAAM,OAAO,oBAAa;AACnC,eAAA;AAAA,MAAA;AAAA,IACT,CACD;AAED,QAAI,eAAe;AAAA,MACjB,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,SAAS;AAAA,MACT,MAAM;AAAA,IAAA,CACP;AAAA,EACH;AAAA,EAEA,UAAU,KAAU;AAClB,QAAI,UAAU,iBAAiB,EAAE,gBAAgB,YAAY,eAAe;AAAA,MAC1E,MAAM;AAAA,MACN,WAAW,MAAM,oBAAC,kBAAiB,CAAA,CAAA;AAAA,IAAA,CACpC;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,KAAU;AACtB,UAAA,EAAE,YAAY;AAEd,UAAA,uBAAuB,MAAM,QAAQ;AAAA,MACxC,QAAqB,IAAI,CAAC,WAAW;AAC7B,eAAA,qCAA+B,uBAAA,OAAA,EAAA,0BAAA,MAAA,OAAA,mBAAA,EAAA,CAAA,GAAA,kBAAA,MAAA,SAAA,CAAA,EACnC,KAAK,CAAC,EAAE,SAAS,WAAW;AACpB,iBAAA;AAAA,YACL,MAAM,eAAe,IAAI;AAAA,YACzB;AAAA,UACF;AAAA,QAAA,CACD,EACA,MAAM,MAAM;AACJ,iBAAA;AAAA,YACL,MAAM,CAAC;AAAA,YACP;AAAA,UACF;AAAA,QAAA,CACD;AAAA,MACJ,CAAA;AAAA,IACH;AAEO,WAAA;AAAA,EAAA;AAEX;"}