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.
- package/README.md +187 -0
- package/dist/_chunks/{App-CnXhqiao.js → App-Rq72tIgS.js} +35 -37
- package/dist/_chunks/App-Rq72tIgS.js.map +1 -0
- package/dist/_chunks/{App-4UwemHRe.mjs → App-j180lztd.mjs} +35 -37
- package/dist/_chunks/App-j180lztd.mjs.map +1 -0
- package/dist/_chunks/en-B4KWt_jN.js +1 -0
- package/dist/_chunks/en-B4KWt_jN.js.map +1 -0
- package/dist/_chunks/en-Byx4XI2L.mjs +1 -0
- package/dist/_chunks/en-Byx4XI2L.mjs.map +1 -0
- package/dist/_chunks/{index-BWSiu_nE.mjs → index-B3j0IFUi.mjs} +70 -27
- package/dist/_chunks/index-B3j0IFUi.mjs.map +1 -0
- package/dist/_chunks/{index-BaPVw3mi.js → index-jf6vikTZ.js} +70 -27
- package/dist/_chunks/index-jf6vikTZ.js.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/index.mjs +2 -1
- package/dist/admin/index.mjs.map +1 -0
- package/dist/admin/src/components/custom/MarkdownEditor.d.ts +1 -1
- package/dist/server/index.js +850 -57
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +850 -57
- package/dist/server/index.mjs.map +1 -0
- package/dist/server/src/config/index.d.ts +9 -0
- package/dist/server/src/controllers/controller.d.ts +14 -0
- package/dist/server/src/controllers/index.d.ts +2 -0
- package/dist/server/src/index.d.ts +38 -2
- package/dist/server/src/mcp/tools/create-embedding.d.ts +6 -0
- package/dist/server/src/mcp/tools/index.d.ts +4 -0
- package/dist/server/src/plugin-manager.d.ts +16 -0
- package/dist/server/src/routes/content-api.d.ts +10 -0
- package/dist/server/src/routes/index.d.ts +10 -0
- package/dist/server/src/services/embeddings.d.ts +43 -2
- package/dist/server/src/services/index.d.ts +23 -2
- package/dist/server/src/services/sync.d.ts +48 -0
- package/dist/server/src/utils/chunking.d.ts +44 -0
- 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-
|
|
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
|
-
|
|
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
|
|
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()
|
|
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
|
|
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}
|
|
688
|
+
defaultMessage: "Content: {length} characters"
|
|
692
689
|
},
|
|
693
|
-
{ length: contentLength
|
|
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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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"en-B4KWt_jN.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -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:
|
|
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
|
|
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
|
|
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()
|
|
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
|
-
"
|
|
630
|
+
"Content: ",
|
|
592
631
|
contentLength,
|
|
593
|
-
"
|
|
594
|
-
|
|
595
|
-
|
|
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:
|
|
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-
|
|
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;"}
|