diff --git a/.changeset/hot-moments-slide.md b/.changeset/hot-moments-slide.md new file mode 100644 index 000000000..0284b0442 --- /dev/null +++ b/.changeset/hot-moments-slide.md @@ -0,0 +1,5 @@ +--- +"@create-llama/llama-index-server": patch +--- + +Add support for upload file diff --git a/.changeset/wide-queens-drop.md b/.changeset/wide-queens-drop.md new file mode 100644 index 000000000..f68975899 --- /dev/null +++ b/.changeset/wide-queens-drop.md @@ -0,0 +1,5 @@ +--- +"@llamaindex/server": patch +--- + +Add support for chat upload file diff --git a/packages/server/README.md b/packages/server/README.md index 8b91a2c57..3188034d0 100644 --- a/packages/server/README.md +++ b/packages/server/README.md @@ -60,6 +60,7 @@ The `LlamaIndexServer` accepts the following configuration options: - `workflow`: A callable function that creates a workflow instance for each request. See [Workflow factory contract](#workflow-factory-contract) for more details. - `uiConfig`: An object to configure the chat UI containing the following properties: - `starterQuestions`: List of starter questions for the chat UI (default: `[]`) + - `enableFileUpload`: Whether to enable file upload in the chat UI (default: `false`). See [Upload file example](./examples/private-file/README.md) for more details. - `componentsDir`: The directory for custom UI components rendering events emitted by the workflow. The default is undefined, which does not render custom UI components. - `layoutDir`: The directory for custom layout sections. The default value is `layout`. See [Custom Layout](#custom-layout) for more details. - `llamaCloudIndexSelector`: Whether to show the LlamaCloud index selector in the chat UI (requires `LLAMA_CLOUD_API_KEY` to be set in the environment variables) (default: `false`) @@ -71,9 +72,18 @@ See all Nextjs Custom Server options [here](https://nextjs.org/docs/app/building ## Workflow factory contract -The `workflow` provided will be called for each chat request to initialize a new workflow instance. The contract of the generated workflow must be the same as for the [Agent Workflow](https://ts.llamaindex.ai/docs/llamaindex/modules/agents/agent_workflow). +The `workflow` provided will be called for each chat request to initialize a new workflow instance. For advanced use cases, you can define workflowFactory with a chatBody which include list of UI messages in the request body. -This means that the workflow must handle a `startAgentEvent` event, which is the entry point of the workflow and contains the following information in it's `data` property: +```typescript +import { type Message } from "ai"; +import { agent } from "@llamaindex/workflow"; + +const workflowFactory = (chatBody: { messages: Message[] }) => { + ... +}; +``` + +The contract of the generated workflow must be the same as for the [Agent Workflow](https://ts.llamaindex.ai/docs/llamaindex/modules/agents/agent_workflow). This means that the workflow must handle a `startAgentEvent` event, which is the entry point of the workflow and contains the following information in it's `data` property: ```typescript { diff --git a/packages/server/examples/README.md b/packages/server/examples/README.md index 5d912159e..565a56c30 100644 --- a/packages/server/examples/README.md +++ b/packages/server/examples/README.md @@ -1,12 +1,38 @@ # LlamaIndex Server Examples -This directory contains examples of how to use the LlamaIndex Server. +This directory provides example projects demonstrating how to use the LlamaIndex Server. -## Running the examples +## How to Run the Examples -```bash -export OPENAI_API_KEY=your_openai_api_key -pnpm run dev -``` +1. **Install dependencies** -## Open browser at http://localhost:3000 + In the root of this directory, run: + + ```bash + pnpm install + ``` + +2. **Set your OpenAI API key** + + Export your OpenAI API key as an environment variable: + + ```bash + export OPENAI_API_KEY=your_openai_api_key + ``` + +3. **Start an example** + + Replace `` with the name of the example you want to run (e.g., `private-file`): + + ```bash + pnpm nodemon --exec tsx /index.ts + ``` + +4. **Open the application in your browser** + + Visit [http://localhost:3000](http://localhost:3000) to interact with the running example. + +## Notes + +- Make sure you have [pnpm](https://pnpm.io/) installed. +- Each example may have its own specific instructions or requirements; check the individual example's index.ts for details. diff --git a/packages/server/examples/private-file/README.md b/packages/server/examples/private-file/README.md new file mode 100644 index 000000000..80cb75ebd --- /dev/null +++ b/packages/server/examples/private-file/README.md @@ -0,0 +1,68 @@ +# Upload File Example + +This example shows how to use the uploaded file (private file) from the user in the workflow. + +## Prerequisites + +Please follow the setup instructions in the [examples README](../README.md). + +You will also need: + +- An OpenAI API key +- The `enableFileUpload` option in the `uiConfig` is set to `true`. + +```typescript +new LlamaIndexServer({ + // ... other options + uiConfig: { enableFileUpload: true }, +}).start(); +``` + +## How to get the uploaded files in your workflow: + +In LlamaIndexServer, the uploaded file is included in chat message annotations. You can easily get the uploaded files from chat messages using the [extractFileAttachments](https://github.com/llamaindex/llamaindex/blob/main/packages/server/src/utils/events.ts) function. + +```typescript +import { type Message } from "ai"; +import { extractFileAttachments } from "@llamaindex/server"; + +async function workflowFactory(reqBody: { messages: Message[] }) { + const attachments = extractFileAttachments(reqBody.messages); + // ... +} +``` + +### AgentWorkflow + +If you are using AgentWorkflow, to provide file access to the agent, you can create a tool to read the file content. We recommend to use the `fileId` as the parameter of the tool instead of the `filePath` to avoid showing internal file path to the user. You can use the `getStoredFilePath` helper function to get the file path from the file id. + +```typescript +import { getStoredFilePath, extractFileAttachments } from "@llamaindex/server"; + +const readFileTool = tool( + ({ fileId }) => { + // Get the file path from the file id + const filePath = getStoredFilePath({ id: fileId }); + return fsPromises.readFile(filePath, "utf8"); + }, + { + name: "read_file", + description: `Use this tool with the file id to read the file content. The available file are: [${attachments.map((file) => file.id).join(", ")}]`, + parameters: z.object({ + fileId: z.string(), + }), + }, +); +``` + +**Tip:** You can either put the attachments file information to the tool description or agent's system prompt. + +Check: [agent-workflow.ts](./agent-workflow.ts) for the full example. + +### Custom Workflow + +In custom workflow, instead of defining a tool, you can use the helper functions (`extractFileAttachments` and `getStoredFilePath`) to work with file attachments in your workflow. + +Check: [custom-workflow.ts](./custom-workflow.ts) for the full example. + +> To run custom workflow example, update the `index.ts` file to use the `workflowFactory` from `custom-workflow.ts` instead of `agent-workflow.ts`. diff --git a/packages/server/examples/private-file/agent-workflow.ts b/packages/server/examples/private-file/agent-workflow.ts new file mode 100644 index 000000000..d5921fa53 --- /dev/null +++ b/packages/server/examples/private-file/agent-workflow.ts @@ -0,0 +1,39 @@ +import { extractFileAttachments, getStoredFilePath } from "@llamaindex/server"; +import { agent } from "@llamaindex/workflow"; +import { type Message } from "ai"; +import { tool } from "llamaindex"; +import { promises as fsPromises } from "node:fs"; +import { z } from "zod"; + +export const workflowFactory = async (reqBody: { messages: Message[] }) => { + const { messages } = reqBody; + // Extract the files from the messages + const files = extractFileAttachments(messages); + const fileIds = files.map((file) => file.id); + + // Define a tool to read the file content using the id + const readFileTool = tool( + ({ fileId }) => { + if (!fileIds.includes(fileId)) { + throw new Error(`File with id ${fileId} not found`); + } + + const filePath = getStoredFilePath({ id: fileId }); + return fsPromises.readFile(filePath, "utf8"); + }, + { + name: "read_file", + description: `Use this tool with the id of the file to read the file content. Here are the available file ids: [${fileIds.join(", ")}]`, + parameters: z.object({ + fileId: z.string(), + }), + }, + ); + return agent({ + tools: [readFileTool], + systemPrompt: ` + You are a helpful assistant that can help the user with their file. + You can use the read_file tool to read the file content. + `, + }); +}; diff --git a/packages/server/examples/private-file/custom-workflow.ts b/packages/server/examples/private-file/custom-workflow.ts new file mode 100644 index 000000000..dd76f8ad6 --- /dev/null +++ b/packages/server/examples/private-file/custom-workflow.ts @@ -0,0 +1,98 @@ +import { extractFileAttachments } from "@llamaindex/server"; +import { ChatMemoryBuffer, MessageContent, Settings } from "llamaindex"; + +import { + agentStreamEvent, + createStatefulMiddleware, + createWorkflow, + startAgentEvent, + stopAgentEvent, + workflowEvent, +} from "@llamaindex/workflow"; +import { Message } from "ai"; +import { promises as fsPromises } from "node:fs"; + +const fileHelperEvent = workflowEvent<{ + userInput: MessageContent; + fileContent: string; +}>(); + +/** + * This is an simple workflow to demonstrate how to use uploaded files in the workflow. + */ +export function workflowFactory(reqBody: { messages: Message[] }) { + const llm = Settings.llm; + + // First, extract the uploaded file from the messages + const attachments = extractFileAttachments(reqBody.messages); + + if (attachments.length === 0) { + throw new Error("Please upload a file to start"); + } + + // Then, add the uploaded file info to the workflow state + const { withState, getContext } = createStatefulMiddleware(() => { + return { + memory: new ChatMemoryBuffer({ llm }), + uploadedFile: attachments[attachments.length - 1], + }; + }); + const workflow = withState(createWorkflow()); + + // Handle the start of the workflow: read the file content + workflow.handle([startAgentEvent], async ({ data }) => { + const { userInput } = data; + // Prepare chat history + const { state } = getContext(); + if (!userInput) { + throw new Error("Missing user input to start the workflow"); + } + state.memory.put({ role: "user", content: userInput }); + + // Read file content + const fileContent = await fsPromises.readFile( + state.uploadedFile.path, + "utf8", + ); + + return fileHelperEvent.with({ + userInput, + fileContent, + }); + }); + + // Use LLM to help the user with the file content + workflow.handle([fileHelperEvent], async ({ data }) => { + const { sendEvent } = getContext(); + + const prompt = ` +You are a helpful assistant that can help the user with their file. + +Here is the provided file content: +${data.fileContent} + +Now, let help the user with this request: +${data.userInput} +`; + + const response = await llm.complete({ + prompt, + stream: true, + }); + + // Stream the response + for await (const chunk of response) { + sendEvent( + agentStreamEvent.with({ + delta: chunk.text, + response: chunk.text, + currentAgentName: "agent", + raw: chunk.raw, + }), + ); + } + sendEvent(stopAgentEvent.with({ result: "" })); + }); + + return workflow; +} diff --git a/packages/server/examples/private-file/index.ts b/packages/server/examples/private-file/index.ts new file mode 100644 index 000000000..94b233f9d --- /dev/null +++ b/packages/server/examples/private-file/index.ts @@ -0,0 +1,23 @@ +import { OpenAI, OpenAIEmbedding } from "@llamaindex/openai"; +import { LlamaIndexServer } from "@llamaindex/server"; +import { Settings } from "llamaindex"; +import { workflowFactory } from "./agent-workflow"; +// Uncomment this to use a custom workflow +// import { workflowFactory } from "./custom-workflow"; + +Settings.llm = new OpenAI({ + model: "gpt-4o-mini", +}); + +Settings.embedModel = new OpenAIEmbedding({ + model: "text-embedding-3-small", +}); + +new LlamaIndexServer({ + workflow: workflowFactory, + suggestNextQuestions: false, + uiConfig: { + enableFileUpload: true, + }, + port: 3000, +}).start(); diff --git a/packages/server/next/app/api/files/helpers.ts b/packages/server/next/app/api/files/helpers.ts new file mode 100644 index 000000000..d21ff7e9d --- /dev/null +++ b/packages/server/next/app/api/files/helpers.ts @@ -0,0 +1,57 @@ +import crypto from "node:crypto"; +import fs from "node:fs"; +import path from "node:path"; + +import { type ServerFile } from "@llamaindex/server"; + +export const UPLOADED_FOLDER = "output/uploaded"; + +export async function storeFile( + name: string, + fileBuffer: Buffer, +): Promise { + const parts = name.split("."); + const fileName = parts[0]; + const fileExt = parts[1]; + if (!fileName) { + throw new Error("File name is required"); + } + if (!fileExt) { + throw new Error("File extension is required"); + } + + const id = crypto.randomUUID(); + const fileId = `${sanitizeFileName(fileName)}_${id}.${fileExt}`; + const filepath = path.join(UPLOADED_FOLDER, fileId); + const fileUrl = await saveFile(filepath, fileBuffer); + return { + id: fileId, + size: fileBuffer.length, + type: fileExt, + url: fileUrl, + path: filepath, + }; +} + +// Save document to file server and return the file url +async function saveFile(filepath: string, content: string | Buffer) { + if (path.isAbsolute(filepath)) { + throw new Error("Absolute file paths are not allowed."); + } + + const dirPath = path.dirname(filepath); + await fs.promises.mkdir(dirPath, { recursive: true }); + + if (typeof content === "string") { + await fs.promises.writeFile(filepath, content, "utf-8"); + } else { + await fs.promises.writeFile(filepath, content); + } + + const fileurl = `/api/files/${filepath}`; + return fileurl; +} + +function sanitizeFileName(fileName: string) { + return fileName.replace(/[^a-zA-Z0-9_-]/g, "_"); +} diff --git a/packages/server/next/app/api/files/route.ts b/packages/server/next/app/api/files/route.ts new file mode 100644 index 000000000..919309665 --- /dev/null +++ b/packages/server/next/app/api/files/route.ts @@ -0,0 +1,49 @@ +import { type FileAnnotation } from "@llamaindex/server"; +import { NextRequest, NextResponse } from "next/server"; +import { storeFile } from "./helpers"; + +export async function POST(request: NextRequest) { + try { + const { + name, + base64, + }: { + name: string; + base64: string; + } = await request.json(); + if (!base64 || !name) { + return NextResponse.json( + { error: "base64 and name is required in the request body" }, + { status: 400 }, + ); + } + + const parts = base64.split(","); + if (parts.length !== 2) { + return NextResponse.json( + { error: "Invalid base64 format" }, + { status: 400 }, + ); + } + + const [header, content] = parts; + if (!header || !content) { + return NextResponse.json( + { error: "Invalid base64 format" }, + { status: 400 }, + ); + } + + const fileBuffer = Buffer.from(content, "base64"); + + const file = await storeFile(name, fileBuffer); + + return NextResponse.json(file as FileAnnotation); + } catch (error) { + console.error("[Upload API]", error); + return NextResponse.json( + { error: (error as Error).message }, + { status: 500 }, + ); + } +} diff --git a/packages/server/package.json b/packages/server/package.json index 29fac104f..a19e4321f 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -65,7 +65,7 @@ "@babel/traverse": "^7.27.0", "@babel/types": "^7.27.0", "@hookform/resolvers": "^5.0.1", - "@llamaindex/chat-ui": "0.5.2", + "@llamaindex/chat-ui": "0.5.6", "@radix-ui/react-accordion": "^1.2.3", "@radix-ui/react-alert-dialog": "^1.1.7", "@radix-ui/react-aspect-ratio": "^1.1.3", diff --git a/packages/server/project-config/package.json b/packages/server/project-config/package.json index ae5083908..853208099 100644 --- a/packages/server/project-config/package.json +++ b/packages/server/project-config/package.json @@ -41,7 +41,7 @@ "@babel/traverse": "^7.27.0", "@babel/types": "^7.27.0", "@hookform/resolvers": "^5.0.1", - "@llamaindex/chat-ui": "0.5.2", + "@llamaindex/chat-ui": "0.5.6", "@llamaindex/env": "~0.1.30", "@llamaindex/openai": "~0.4.0", "@llamaindex/readers": "~3.1.4", diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index b0d3f9abe..9a038147c 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -1,6 +1,7 @@ export * from "./server"; export * from "./types"; export * from "./utils/events"; +export { getStoredFilePath } from "./utils/file"; export { generateEventComponent } from "./utils/gen-ui"; export * from "./utils/inline"; export * from "./utils/prompts"; diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index 71f1c83da..a5a3036b8 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -47,7 +47,7 @@ export class LlamaIndexServer { const componentsApi = this.componentsDir ? "/api/components" : undefined; const layoutApi = this.layoutDir ? "/api/layout" : undefined; const devMode = uiConfig?.devMode ?? false; - + const enableFileUpload = uiConfig?.enableFileUpload ?? false; // content in javascript format const content = ` window.LLAMAINDEX = { @@ -57,7 +57,8 @@ export class LlamaIndexServer { COMPONENTS_API: ${JSON.stringify(componentsApi)}, LAYOUT_API: ${JSON.stringify(layoutApi)}, DEV_MODE: ${JSON.stringify(devMode)}, - SUGGEST_NEXT_QUESTIONS: ${JSON.stringify(this.suggestNextQuestions)} + SUGGEST_NEXT_QUESTIONS: ${JSON.stringify(this.suggestNextQuestions)}, + UPLOAD_API: ${JSON.stringify(enableFileUpload ? "/api/files" : undefined)} } `; fs.writeFileSync(configFile, content); diff --git a/packages/server/src/types.ts b/packages/server/src/types.ts index d428f3313..93ac0c294 100644 --- a/packages/server/src/types.ts +++ b/packages/server/src/types.ts @@ -18,6 +18,7 @@ export type UIConfig = { layoutDir?: string; llamaCloudIndexSelector?: boolean; devMode?: boolean; + enableFileUpload?: boolean; }; export type LlamaIndexServerOptions = NextAppOptions & { diff --git a/packages/server/src/utils/events.ts b/packages/server/src/utils/events.ts index 86b31d52d..ebf528ebc 100644 --- a/packages/server/src/utils/events.ts +++ b/packages/server/src/utils/events.ts @@ -1,5 +1,6 @@ import { randomUUID } from "@llamaindex/env"; import { workflowEvent } from "@llamaindex/workflow"; +import type { Message } from "ai"; import { MetadataMode, type ChatMessage, @@ -7,6 +8,7 @@ import { type NodeWithScore, } from "llamaindex"; import { z } from "zod"; +import { getStoredFilePath } from "./file"; import { getInlineAnnotations } from "./inline"; // Events that appended to stream as annotations @@ -214,3 +216,64 @@ export function extractLastArtifact( return artifacts[artifacts.length - 1]; } + +export const fileAnnotationSchema = z.object({ + id: z.string(), + size: z.number(), + type: z.string(), + url: z.string(), +}); + +export const documentFileAnnotationSchema = z.object({ + type: z.literal("document_file"), + data: z.object({ + files: z.array(fileAnnotationSchema), + }), +}); +type DocumentFileAnnotation = z.infer; + +export type FileAnnotation = z.infer; + +export type ServerFile = FileAnnotation & { + path: string; +}; + +/** + * Extract file attachments from an user message. + * @param message - The message to extract file attachments from. + * @returns The file attachments. + */ +export function extractFileAttachmentsFromMessage( + message: Message, +): ServerFile[] { + const fileAttachments: ServerFile[] = []; + if (message.role === "user" && message.annotations) { + for (const annotation of message.annotations) { + if (documentFileAnnotationSchema.safeParse(annotation).success) { + const { data } = annotation as DocumentFileAnnotation; + for (const file of data.files) { + fileAttachments.push({ + ...file, + path: getStoredFilePath({ id: file.id }), + }); + } + } + } + } + return fileAttachments; +} + +/** + * Extract file attachments from all user messages. + * @param messages - The messages to extract file attachments from. + * @returns The file attachments. + */ +export function extractFileAttachments(messages: Message[]): ServerFile[] { + const fileAttachments: ServerFile[] = []; + + for (const message of messages) { + fileAttachments.push(...extractFileAttachmentsFromMessage(message)); + } + + return fileAttachments; +} diff --git a/packages/server/src/utils/file.ts b/packages/server/src/utils/file.ts index 7538c68cd..0cfbc6415 100644 --- a/packages/server/src/utils/file.ts +++ b/packages/server/src/utils/file.ts @@ -1,5 +1,6 @@ import fs from "node:fs"; import https from "node:https"; +import path from "node:path"; export async function downloadFile( urlToDownload: string, @@ -29,3 +30,41 @@ export async function downloadFile( throw new Error(`Error downloading file: ${error}`); } } + +/** + * Returns the full path to a stored file given its id and optional save directory. + * If saveDir is not provided, defaults to "output/uploaded". + * + * @param {Object} params - The parameters object. + * @param {string} params.id - The file identifier. + * @param {string} [params.saveDir] - Optional directory to save the file. + * @returns {string} The full file path. + */ + +/** + * Constructs a stored file path from an ID and optional directory. + * Uses path.join for cross-platform safety and validates the ID to prevent path traversal. + * + * @param {Object} params - The parameters object. + * @param {string} params.id - The file identifier (must not contain path separators). + * @param {string} [params.saveDir] - Optional directory to save the file. Defaults to "output/uploaded". + * @returns {string} The full file path. + * @throws {Error} If the id contains invalid path characters. + */ +export function getStoredFilePath({ + id, + saveDir, +}: { + id: string; + saveDir?: string; +}): string { + // Validate id to prevent path traversal and invalid characters + if (id.includes("/") || id.includes("\\") || id.includes("..")) { + throw new Error( + "Invalid file id: path traversal or separators are not allowed.", + ); + } + // Use path.join to construct the default directory for cross-platform compatibility + const directory = saveDir ?? path.join("output", "uploaded"); + return path.join(directory, id); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75525440f..df9fc4956 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -181,8 +181,8 @@ importers: specifier: ^5.0.1 version: 5.0.1(react-hook-form@7.56.1(react@19.1.0)) '@llamaindex/chat-ui': - specifier: 0.5.2 - version: 0.5.2(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.7)(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 0.5.6 + version: 0.5.6(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.1)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.37.1)(@lezer/highlight@1.2.1)(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(yjs@13.6.27) '@llamaindex/env': specifier: ~0.1.30 version: 0.1.30 @@ -569,26 +569,83 @@ packages: '@codemirror/commands@6.8.1': resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==} + '@codemirror/lang-angular@0.1.4': + resolution: {integrity: sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==} + + '@codemirror/lang-cpp@6.0.2': + resolution: {integrity: sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg==} + '@codemirror/lang-css@6.3.1': resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + '@codemirror/lang-go@6.0.1': + resolution: {integrity: sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==} + '@codemirror/lang-html@6.4.9': resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==} - '@codemirror/lang-javascript@6.2.3': - resolution: {integrity: sha512-8PR3vIWg7pSu7ur8A07pGiYHgy3hHj+mRYRCSG8q+mPIrl0F02rgpGv+DsQTHRTc30rydOsf5PZ7yjKFg2Ackw==} + '@codemirror/lang-java@6.0.1': + resolution: {integrity: sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==} + + '@codemirror/lang-javascript@6.2.4': + resolution: {integrity: sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==} + + '@codemirror/lang-json@6.0.1': + resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==} + + '@codemirror/lang-less@6.0.2': + resolution: {integrity: sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==} + + '@codemirror/lang-liquid@6.2.3': + resolution: {integrity: sha512-yeN+nMSrf/lNii3FJxVVEGQwFG0/2eDyH6gNOj+TGCa0hlNO4bhQnoO5ISnd7JOG+7zTEcI/GOoyraisFVY7jQ==} + + '@codemirror/lang-markdown@6.3.2': + resolution: {integrity: sha512-c/5MYinGbFxYl4itE9q/rgN/sMTjOr8XL5OWnC+EaRMLfCbVUmmubTJfdgpfcSS2SCaT7b+Q+xi3l6CgoE+BsA==} + + '@codemirror/lang-php@6.0.1': + resolution: {integrity: sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==} + + '@codemirror/lang-python@6.2.1': + resolution: {integrity: sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==} + + '@codemirror/lang-rust@6.0.1': + resolution: {integrity: sha512-344EMWFBzWArHWdZn/NcgkwMvZIWUR1GEBdwG8FEp++6o6vT6KL9V7vGs2ONsKxxFUPXKI0SPcWhyYyl2zPYxQ==} + + '@codemirror/lang-sass@6.0.2': + resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==} + + '@codemirror/lang-sql@6.9.0': + resolution: {integrity: sha512-xmtpWqKSgum1B1J3Ro6rf7nuPqf2+kJQg5SjrofCAcyCThOe0ihSktSoXfXuhQBnwx1QbmreBbLJM5Jru6zitg==} + + '@codemirror/lang-vue@0.1.3': + resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==} + + '@codemirror/lang-wast@6.0.2': + resolution: {integrity: sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==} + + '@codemirror/lang-xml@6.1.0': + resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} - '@codemirror/lang-python@6.2.0': - resolution: {integrity: sha512-+oLTR88uLib84tvb4XmOBBq/dgrctvPXueP3Wjotu4zmHLM2KW2wfswJ6r1BKlfJNcGgdWX1AgUeGEf3E2H5LA==} + '@codemirror/lang-yaml@6.1.2': + resolution: {integrity: sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==} - '@codemirror/language@6.11.0': - resolution: {integrity: sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==} + '@codemirror/language-data@6.5.1': + resolution: {integrity: sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==} + + '@codemirror/language@6.11.1': + resolution: {integrity: sha512-5kS1U7emOGV84vxC+ruBty5sUgcD0te6dyupyRVG2zaSjhTDM73LhVKUtVwiqSe6QwmEoA4SCiU8AKPFyumAWQ==} + + '@codemirror/legacy-modes@6.5.1': + resolution: {integrity: sha512-DJYQQ00N1/KdESpZV7jg9hafof/iBNp9h7TYo1SLMk86TWl9uDsVdho2dzd81K+v4retmK6mdC7WpuOQDytQqw==} '@codemirror/lint@6.8.5': resolution: {integrity: sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==} - '@codemirror/search@6.5.10': - resolution: {integrity: sha512-RMdPdmsrUf53pb2VwflKGHEe1XVM07hI7vV2ntgw1dmqhimpatSJKva4VA9h4TLUDOD4EIF02201oZurpnEFsg==} + '@codemirror/merge@6.10.1': + resolution: {integrity: sha512-TgZD+LDa2EIeqTkptg42TAU6n3meq++rQC+e7FuCi1arEm8CRGVQw5Fygb7UIfDzFAt4QrE6SS3CPOz06D2ALg==} + + '@codemirror/search@6.5.11': + resolution: {integrity: sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==} '@codemirror/state@6.5.2': resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==} @@ -596,8 +653,20 @@ packages: '@codemirror/theme-one-dark@6.1.2': resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==} - '@codemirror/view@6.36.7': - resolution: {integrity: sha512-kCWGW/chWGPgZqfZ36Um9Iz0X2IVpmCjg1P/qY6B6a2ecXtWRRAigmpJ6YgUQ5lTWXMyyVdfmpzhLZmsZQMbtg==} + '@codemirror/view@6.37.1': + resolution: {integrity: sha512-Qy4CAUwngy/VQkEz0XzMKVRcckQuqLYWKqVpDDDghBe5FSXSqfVrJn49nw3ePZHxRUz4nRmb05Lgi+9csWo4eg==} + + '@codesandbox/nodebox@0.1.8': + resolution: {integrity: sha512-2VRS6JDSk+M+pg56GA6CryyUSGPjBEe8Pnae0QL3jJF1mJZJVMDKr93gJRtBbLkfZN6LD/DwMtf+2L0bpWrjqg==} + + '@codesandbox/sandpack-client@2.19.8': + resolution: {integrity: sha512-CMV4nr1zgKzVpx4I3FYvGRM5YT0VaQhALMW9vy4wZRhEyWAtJITQIqZzrTGWqB1JvV7V72dVEUCUPLfYz5hgJQ==} + + '@codesandbox/sandpack-react@2.20.0': + resolution: {integrity: sha512-takd1YpW/PMQ6KPQfvseWLHWklJovGY8QYj8MtWnskGKbjOGJ6uZfyZbcJ6aCFLQMpNyjTqz9AKNbvhCOZ1TUQ==} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 + react-dom: ^16.8.0 || ^17 || ^18 || ^19 '@connectrpc/connect-web@2.0.0-rc.3': resolution: {integrity: sha512-w88P8Lsn5CCsA7MFRl2e6oLY4J/5toiNtJns/YJrlyQaWOy3RO8pDgkz+iIkG98RPMhj2thuBvsd3Cn4DKKCkw==} @@ -1142,11 +1211,88 @@ packages: '@jsdevtools/ono@7.1.3': resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + '@lexical/clipboard@0.27.2': + resolution: {integrity: sha512-rfnFYf8P0081IvPOJjE7fWJE+d/dz0Xdsw83uizY5X6HaLXFB/Qy1MrzEqWZnYnOpgi1snAuolZ5Rbg83SIlYA==} + + '@lexical/code@0.27.2': + resolution: {integrity: sha512-GoTy57CYoXvP1N+E9ptCJ47LQCAu67K/HQsjg0NmmtNbWlInk6Sa2V4pM1KePp6JAQapGpIlCoEyC3/KkrQ55g==} + + '@lexical/devtools-core@0.27.2': + resolution: {integrity: sha512-LAI7j9roS2i/lV/6Z4AAx2+EVOEnMVzLZFB6aQfSjRbZ9lzA8S17743OJUHRXyTvBWc5520ihhBybO0EfjTagw==} + peerDependencies: + react: '>=17.x' + react-dom: '>=17.x' + + '@lexical/dragon@0.27.2': + resolution: {integrity: sha512-0xI98esvgtJpVLJUADtvJ/yKk4kFFrn2h7GgzvihLXeVe+O149DONFSarB9yguDyvHUblKtfjB2BcJaeOIpouQ==} + + '@lexical/hashtag@0.27.2': + resolution: {integrity: sha512-BBwMT3rz/TlZZ6ZjkP5+Yj86ffufiktOBwry7kPDUqOMyTuTFEE58cmd4SXiYEs7yifrC6TenRmFZgBui7xpmQ==} + + '@lexical/history@0.27.2': + resolution: {integrity: sha512-5CihqjvlmXuiLZYpKZMfYISpVSSpUrs3jpC5XK0kAv0etUWyf2/JzY0BLfD2kb7x/tOrU7O+WptNNyl5WL3N5A==} + + '@lexical/html@0.27.2': + resolution: {integrity: sha512-6kPvrTxAE39jUhnbYMCenHVHXTlew9sBprniQu5iZSszMfcn/SDkqmHWi8//fhiLlcAa/p0vRDxaBYoQQf0r9A==} + + '@lexical/link@0.27.2': + resolution: {integrity: sha512-t+tMr1aEwy67D4+GU6XX78Dxllyu3xebYAlB5ANpnv0oV8PSxT8h6aHHVwj0a55a89NnSPTzpBhqtX0QO374+A==} + + '@lexical/list@0.27.2': + resolution: {integrity: sha512-jE7e95ttO26Xtt322dnUwWSG7QgeAfBg3Ghyjd8ByGI5O5wmMgMgb3NCiSSRPBWOpt6PEeD5s5KjQKfMUCCuHQ==} + + '@lexical/mark@0.27.2': + resolution: {integrity: sha512-6rTwfVuuFeiTy6MU8yY3nyBOe2KtcB1lL0zg8ygIRjSYsV2+HAVAUesDFnaCUHJ1qimj9pJB8fW+GU2ur8uGvQ==} + + '@lexical/markdown@0.27.2': + resolution: {integrity: sha512-XbM/G0CPoH2BUAuKSRS5L2pAU1kreZDOH0Eh4DR2sLzosM48ZyRktgKAUwHItQPQ/in5hkH3Xd5D4RAtYWhKUA==} + + '@lexical/offset@0.27.2': + resolution: {integrity: sha512-li+NxLeU2IW7JKOr8pheS/7aGlU8sKThPEKDtM20d0drvMAo03ebu5X/wxmy1e4zWKbpH3dll/ocE+gGV9DcLA==} + + '@lexical/overflow@0.27.2': + resolution: {integrity: sha512-vkKrZyes4/r73wH/t+X0HEsol4A9yxzALAnx8vyXCnw2s8zklQFi5ccf3fkwPG6cSKDl+zAO0elmSjhxOp5JfQ==} + + '@lexical/plain-text@0.27.2': + resolution: {integrity: sha512-/EygmUMFsH9WVkXl1/IwKJfJJAQy2pnxPx+bYz97hTXqh9CHkzn0N81gxjquRAPZkemoE7UoZsAbaw07BH+8hA==} + + '@lexical/react@0.27.2': + resolution: {integrity: sha512-azfF9kQ/LM47Gn0vV5xMkD2viEiAxmgRQQsDv8gOZcZY4CWtRth/uehW8nchmD4xIgK63LLjGRjYhShTufy0XA==} + peerDependencies: + react: '>=17.x' + react-dom: '>=17.x' + + '@lexical/rich-text@0.27.2': + resolution: {integrity: sha512-naWwPNbEJAue/R0pmZwqnTVkv3V2rzgzz+C6/J5tMOvN1Osth8OL3UD6K8NQX8rjdnXe4soVoH8XsNhU0Jv10w==} + + '@lexical/selection@0.27.2': + resolution: {integrity: sha512-9AJOfw1zMQ3PqGpovEuy6NjfWck/9KzxNPzXoGRZlJRvPexgZirentPWRhLHF3DMtnOML1+GCpj+5LOAYN2XbQ==} + + '@lexical/table@0.27.2': + resolution: {integrity: sha512-6G3jj7EyweviX3/AEZOr/XBTIQN5QCkJcg1Zw3I9Ga0F+CCDM5aeJWRv4hultP1nOz1xtYCDnezhaPV1Gef9dA==} + + '@lexical/text@0.27.2': + resolution: {integrity: sha512-Rx61l/Cbz2GGwZvtp56PMGB35X+VnZYhRlLJdZhQ+XTYbRmCTAh50mBcS3FzZrziq8vn07yEN/9FVb8HGTyN1A==} + + '@lexical/utils@0.27.2': + resolution: {integrity: sha512-tCEuKL5IXiJ12ZN/Ej37Q7PhcBntekLeQbGiYO4sgIAnR9qI6yYgVH7b1CC+Tf06UapUXjIDG0Uh5/u0W1+kOQ==} + + '@lexical/yjs@0.27.2': + resolution: {integrity: sha512-+twxPJNwN9VOe20dMKDbBfdZWCiTVM7RrezNZ984o8bJVx6dW80yM96zEyyQp1pmgi60lOYunKWD1B5/74Dq/w==} + peerDependencies: + yjs: '>=13.5.22' + '@lezer/common@1.2.3': resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} - '@lezer/css@1.1.11': - resolution: {integrity: sha512-FuAnusbLBl1SEAtfN8NdShxYJiESKw9LAFysfea1T96jD3ydBn12oYjaSG1a04BQRIUd93/0D8e5CV1cUMkmQg==} + '@lezer/cpp@1.1.3': + resolution: {integrity: sha512-ykYvuFQKGsRi6IcE+/hCSGUhb/I4WPjd3ELhEblm2wS2cOznDFzO+ubK2c+ioysOnlZ3EduV+MVQFCPzAIoY3w==} + + '@lezer/css@1.2.1': + resolution: {integrity: sha512-2F5tOqzKEKbCUNraIXc0f6HKeyKlmMWJnBB0i4XW6dJgssrZO/YlZ2pY5xgyqDleqqhiNJ3dQhbrV2aClZQMvg==} + + '@lezer/go@1.0.1': + resolution: {integrity: sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==} '@lezer/highlight@1.2.1': resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==} @@ -1154,15 +1300,39 @@ packages: '@lezer/html@1.3.10': resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==} + '@lezer/java@1.1.3': + resolution: {integrity: sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==} + '@lezer/javascript@1.5.1': resolution: {integrity: sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==} + '@lezer/json@1.0.3': + resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==} + '@lezer/lr@1.4.2': resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==} + '@lezer/markdown@1.4.3': + resolution: {integrity: sha512-kfw+2uMrQ/wy/+ONfrH83OkdFNM0ye5Xq96cLlaCy7h5UT9FO54DU4oRoIc0CSBh5NWmWuiIJA7NGLMJbQ+Oxg==} + + '@lezer/php@1.0.2': + resolution: {integrity: sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==} + '@lezer/python@1.1.18': resolution: {integrity: sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==} + '@lezer/rust@1.0.2': + resolution: {integrity: sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==} + + '@lezer/sass@1.1.0': + resolution: {integrity: sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==} + + '@lezer/xml@1.0.6': + resolution: {integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==} + + '@lezer/yaml@1.0.3': + resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==} + '@llama-flow/core@0.4.1': resolution: {integrity: sha512-xHhJMRmY16C1pYPWIonmLWPkkjTGuj1iVQCTXOM6sXajQ3r0+mEVERQCjPqf48tvX0K+szbdgxjg6wx+KwVqcg==} peerDependencies: @@ -1186,8 +1356,8 @@ packages: zod: optional: true - '@llamaindex/chat-ui@0.5.2': - resolution: {integrity: sha512-zIOaf5cuhDtllrcDEDaGNRq2bon8STUYoex4n+zzowR6eirRRYPYoUpRBNBK7fZi4BJhBPmqTS/tkXzjw908Gw==} + '@llamaindex/chat-ui@0.5.6': + resolution: {integrity: sha512-52JZiDjHOeJpHo8MB5cOR4433R7OWdaDHAZbgEX4K1TROpgUSLfCHsmiqygTXBdmM0D969k9n8PVFhsWeNX6CQ==} peerDependencies: react: ^18.2.0 || ^19.0.0 || ^19.0.0-rc @@ -1275,6 +1445,20 @@ packages: '@marijn/find-cluster-break@1.0.2': resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + '@mdxeditor/editor@3.35.0': + resolution: {integrity: sha512-BCVMenprkS3Fx2504vFp6AaqW7viM2LiSI9v5Jp4dcVbduljiLzJo46rzJk7BHkHaq+got09hrfd5muxlSW8fQ==} + engines: {node: '>=16'} + peerDependencies: + react: '>= 18 || >= 19' + react-dom: '>= 18 || >= 19' + + '@mdxeditor/gurx@1.2.3': + resolution: {integrity: sha512-5DQOlEx46oN9spggrC8husAGAhVoEFBGIYKN48es08XhRUbSU6l5bcIQYwRrQaY8clU1tExIcXzw8/fNnoxjpg==} + engines: {node: '>=16'} + peerDependencies: + react: '>= 18 || >= 19' + react-dom: '>= 18 || >= 19' + '@modelcontextprotocol/sdk@1.12.1': resolution: {integrity: sha512-KG1CZhZfWg+u8pxeM/mByJDScJSrjjxLc8fwQqbsS8xCjBmQfMNEBTotYdNanKekepnfRI85GtgQlctLFpcYPw==} engines: {node: '>=18'} @@ -1352,6 +1536,9 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + '@opentelemetry/api@1.9.0': resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} @@ -1365,6 +1552,9 @@ packages: engines: {node: '>=18'} hasBin: true + '@radix-ui/colors@3.0.0': + resolution: {integrity: sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg==} + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -1475,6 +1665,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-compose-refs@1.1.2': resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} peerDependencies: @@ -1720,6 +1923,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-progress@1.1.4': resolution: {integrity: sha512-8rl9w7lJdcVPor47Dhws9mUHRHLE+8JEgyJRdNWCpGPa6HIlr3eh+Yn9gyx1CnCLbw5naHsI2gaO9dBWO50vzw==} peerDependencies: @@ -1746,6 +1962,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-roving-focus@1.1.10': + resolution: {integrity: sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-roving-focus@1.1.7': resolution: {integrity: sha512-C6oAg451/fQT3EGbWHbCQjYTtbyjNO1uzQgMzwyivcHT3GKNEmu1q3UuREhN+HzHAVtv3ivMVK08QlC+PkYw9Q==} peerDependencies: @@ -1798,6 +2027,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-separator@1.1.7': + resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-slider@1.3.2': resolution: {integrity: sha512-oQnqfgSiYkxZ1MrF6672jw2/zZvpB+PJsrIc3Zm1zof1JHf/kj7WhmROw7JahLfOwYQ5/+Ip0rFORgF1tjSiaQ==} peerDependencies: @@ -1820,6 +2062,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-switch@1.2.2': resolution: {integrity: sha512-7Z8n6L+ifMIIYZ83f28qWSceUpkXuslI2FJ34+kDMTiyj91ENdpdQ7VCidrzj5JfwfZTeano/BnGBbu/jqa5rQ==} peerDependencies: @@ -1846,6 +2097,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-toggle-group@1.1.10': + resolution: {integrity: sha512-kiU694Km3WFLTC75DdqgM/3Jauf3rD9wxeS9XtyWFKsBUeZA337lC+6uUazT7I1DhanZ5gyD5Stf8uf2dbQxOQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-toggle-group@1.1.7': resolution: {integrity: sha512-GRaPJhxrRSOqAcmcX3MwRL/SZACkoYdmoY9/sg7Bd5DhBYsB2t4co0NxTvVW8H7jUmieQDQwRtUlZ5Ta8UbgJA==} peerDependencies: @@ -1872,6 +2136,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-toggle@1.1.9': + resolution: {integrity: sha512-ZoFkBBz9zv9GWer7wIjvdRxmh2wyc2oKWw6C6CseWd6/yq1DK/l5lJ+wnsmFwJZbBYqr02mrf8A2q/CVCuM3ZA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toolbar@1.1.10': + resolution: {integrity: sha512-jiwQsduEL++M4YBIurjSa+voD86OIytCod0/dbIxFZDLD8NfO1//keXYMfsW8BPcfqwoNjt+y06XcJqAb4KR7A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-tooltip@1.2.4': resolution: {integrity: sha512-DyW8VVeeMSSLFvAmnVnCwvI3H+1tpJFHT50r+tdOoMse9XqYDBCcyux8u3G2y+LOpt7fPQ6KKH0mhs+ce1+Z5w==} peerDependencies: @@ -1982,6 +2272,16 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@react-hook/intersection-observer@3.1.2': + resolution: {integrity: sha512-mWU3BMkmmzyYMSuhO9wu3eJVP21N8TcgYm9bZnTrMwuM818bEk+0NRM3hP+c/TqA9Ln5C7qE53p1H0QMtzYdvQ==} + peerDependencies: + react: '>=16.8' + + '@react-hook/passive-layout-effect@1.2.1': + resolution: {integrity: sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==} + peerDependencies: + react: '>=16.8' + '@rollup/plugin-commonjs@28.0.3': resolution: {integrity: sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==} engines: {node: '>=16.0.0 || 14 >= 14.17'} @@ -2175,6 +2475,9 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} + '@stitches/core@1.2.8': + resolution: {integrity: sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg==} + '@swc/core-darwin-arm64@1.11.22': resolution: {integrity: sha512-upSiFQfo1TE2QM3+KpBcp5SrOdKKjoc+oUoD1mmBDU2Wv4Bjjv16Z2I5ADvIqMV+b87AhYW+4Qu6iVrQD7j96Q==} engines: {node: '>=10'} @@ -2412,6 +2715,9 @@ packages: '@types/diff-match-patch@1.0.36': resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} @@ -2442,24 +2748,15 @@ packages: '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - '@types/linkify-it@5.0.0': - resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - '@types/lodash@4.17.16': resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} - '@types/markdown-it@14.1.2': - resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} - '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/mdurl@2.0.0': - resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -2775,6 +3072,9 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + anser@2.3.2: + resolution: {integrity: sha512-PMqBCBvrOVDRqLGooQb+z+t1Q0PiPyurUQeZRR5uHBOVZcW8B04KMmnT12USnhpNX2wCPagWzLVppQMUG3u0Dw==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -2944,6 +3244,9 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + builtins@1.0.3: resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} @@ -3034,9 +3337,18 @@ packages: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} @@ -3066,10 +3378,16 @@ packages: class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} + clean-set@1.1.2: + resolution: {integrity: sha512-cA8uCj0qSoG9e0kevyOWXwPaELRPVg5Pxp6WskLMwerx257Zfnh8Nl0JBH59d7wQzij2CK7qEfJQK3RjuKKIug==} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -3096,6 +3414,14 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + cm6-theme-basic-light@0.2.0: + resolution: {integrity: sha512-1prg2gv44sYfpHscP26uLT/ePrh0mlmVwMSoSd3zYKQ92Ab3jPRLzyCnpyOCQLJbK+YdNs4HvMRqMNYdy4pMhA==} + peerDependencies: + '@codemirror/language': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@codemirror/view': ^6.0.0 + '@lezer/highlight': ^1.0.0 + cmdk@1.1.1: resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==} peerDependencies: @@ -3155,6 +3481,9 @@ packages: compare-versions@6.1.1: resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + compute-scroll-into-view@2.0.4: + resolution: {integrity: sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -3245,6 +3574,10 @@ packages: resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} engines: {node: '>=12'} + d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} + damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} @@ -3402,6 +3735,11 @@ packages: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} + downshift@7.6.2: + resolution: {integrity: sha512-iOv+E1Hyt3JDdL9yYcOgW7nZ7GQ2Uz6YbggwXvKUSleetYhU2nXD482Rz6CzvM4lvI1At34BYruKAL4swRGxaA==} + peerDependencies: + react: '>=16.12.0' + duck-duck-scrape@2.2.7: resolution: {integrity: sha512-BEcglwnfx5puJl90KQfX+Q2q5vCguqyMpZcSRPBWk8OY55qWwV93+E+7DbIkrGDW4qkqPfUvtOUdi0lXz6lEMQ==} @@ -3509,9 +3847,20 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} + engines: {node: '>=0.10'} + es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + + es6-symbol@3.1.4: + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} + engines: {node: '>=0.12'} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -3526,6 +3875,9 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-carriage@1.3.1: + resolution: {integrity: sha512-GwBr6yViW3ttx1kb7/Oh+gKQ1/TrhYwxKqVmg5gS+BK+Qe2KrOa/Vh7w3HPBvgGf0LfcDGoY9I6NHKoA5Hozhw==} + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -3639,6 +3991,10 @@ packages: jiti: optional: true + esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} + engines: {node: '>=0.10'} + espree@10.3.0: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3660,6 +4016,12 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} @@ -3674,6 +4036,9 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -3714,6 +4079,9 @@ packages: resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} engines: {node: '>= 18'} + ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -3751,6 +4119,9 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fault@2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + fdir@6.4.4: resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} peerDependencies: @@ -3814,6 +4185,10 @@ packages: resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} + format@0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + formdata-node@4.4.1: resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} engines: {node: '>= 12.20'} @@ -4146,10 +4521,19 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + intersection-observer@0.10.0: + resolution: {integrity: sha512-fn4bQ0Xq8FTej09YC/jqKZwtijpvARlRp6wxL5WTA6yPe2YWSJ5RJh7Nm79rK2qB0wr6iDQzH60XGq5V/7u8YQ==} + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -4196,6 +4580,9 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -4224,6 +4611,9 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-interactive@2.0.0: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} @@ -4326,6 +4716,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isomorphic.js@0.2.5: + resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} + iterator.prototype@1.1.5: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} @@ -4425,6 +4818,14 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lexical@0.27.2: + resolution: {integrity: sha512-R255V+4VBqZmSMWeuMrCNHJZd3L+qBkYYFrxkiO3FLg/36HatZLUdZLRYx+fOMWeSddo0DP9EVl0GTZzNb7v0w==} + + lib0@0.2.108: + resolution: {integrity: sha512-+3eK/B0SqYoZiQu9fNk4VEc6EX8cb0Li96tPGKgugzoGj/OdRdREtuTLvUW+mtinoB2mFiJjSqOJBIaMkAGhxQ==} + engines: {node: '>=16'} + hasBin: true + lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} @@ -4496,9 +4897,6 @@ packages: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} - linkify-it@5.0.0: - resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - lint-staged@15.5.1: resolution: {integrity: sha512-6m7u8mue4Xn6wK6gZvSCQwBvMBR36xfY24nF5bMTf2MHDYG6S3yhJuOgdYVw99hsjyDt2d4z168b3naI8+NWtQ==} engines: {node: '>=18.12.0'} @@ -4574,6 +4972,10 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-bytes.js@1.12.1: resolution: {integrity: sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==} @@ -4595,10 +4997,6 @@ packages: engines: {node: '>=12.0.0'} hasBin: true - markdown-it@14.1.0: - resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} - hasBin: true - markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} @@ -4618,6 +5016,9 @@ packages: mdast-util-definitions@5.1.2: resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} + mdast-util-directive@3.1.0: + resolution: {integrity: sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==} + mdast-util-find-and-replace@2.2.2: resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==} @@ -4627,6 +5028,9 @@ packages: mdast-util-from-markdown@2.0.2: resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + mdast-util-frontmatter@2.0.1: + resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==} + mdast-util-gfm-autolink-literal@1.0.3: resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==} @@ -4636,18 +5040,39 @@ packages: mdast-util-gfm-strikethrough@1.0.3: resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==} + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + mdast-util-gfm-table@1.0.7: resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==} + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + mdast-util-gfm-task-list-item@1.0.2: resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==} + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + mdast-util-gfm@2.0.2: resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==} mdast-util-math@2.0.2: resolution: {integrity: sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==} + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.2.0: + resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} + + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + mdast-util-phrasing@3.0.1: resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==} @@ -4669,9 +5094,6 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} @@ -4704,6 +5126,12 @@ packages: micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + micromark-extension-directive@3.0.2: + resolution: {integrity: sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==} + + micromark-extension-frontmatter@2.0.0: + resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==} + micromark-extension-gfm-autolink-literal@1.0.5: resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==} @@ -4713,21 +5141,45 @@ packages: micromark-extension-gfm-strikethrough@1.0.7: resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==} + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + micromark-extension-gfm-table@1.0.7: resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==} + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + micromark-extension-gfm-tagfilter@1.0.2: resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==} micromark-extension-gfm-task-list-item@1.0.5: resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==} + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + micromark-extension-gfm@2.0.3: resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==} micromark-extension-math@2.1.2: resolution: {integrity: sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==} + micromark-extension-mdx-expression@3.0.1: + resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==} + + micromark-extension-mdx-jsx@3.0.2: + resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + micromark-factory-destination@1.1.0: resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==} @@ -4740,6 +5192,9 @@ packages: micromark-factory-label@2.0.1: resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + micromark-factory-mdx-expression@2.0.3: + resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} + micromark-factory-space@1.1.0: resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==} @@ -4800,6 +5255,9 @@ packages: micromark-util-encode@2.0.1: resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + micromark-util-events-to-acorn@2.0.3: + resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} + micromark-util-html-tag-name@1.2.0: resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} @@ -4975,6 +5433,9 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc + next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + next@15.3.1: resolution: {integrity: sha512-8+dDV0xNLOgHlyBxP1GwHGVaNXsmp+2NhZEYrXr24GWLHtt27YrBPbPuHvzlhi7kZNYjeJNR93IF5zfFu5UL0g==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} @@ -4996,8 +5457,8 @@ packages: sass: optional: true - node-abi@3.74.0: - resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} + node-abi@3.75.0: + resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==} engines: {node: '>=10'} node-addon-api@7.1.1: @@ -5137,9 +5598,6 @@ packages: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} - orderedmap@2.1.1: - resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} - os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -5147,6 +5605,9 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + outvariant@1.4.0: + resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} + own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} @@ -5219,6 +5680,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -5454,6 +5918,10 @@ packages: resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} engines: {node: '>= 0.8'} + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -5467,38 +5935,8 @@ packages: property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} - property-information@7.0.0: - resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==} - - prosemirror-commands@1.7.1: - resolution: {integrity: sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==} - - prosemirror-history@1.4.1: - resolution: {integrity: sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==} - - prosemirror-keymap@1.2.3: - resolution: {integrity: sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==} - - prosemirror-markdown@1.13.2: - resolution: {integrity: sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==} - - prosemirror-menu@1.2.5: - resolution: {integrity: sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==} - - prosemirror-model@1.25.1: - resolution: {integrity: sha512-AUvbm7qqmpZa5d9fPKMvH1Q5bqYQvAZWOGRvxsB6iFLyycvC9MwNemNVjHVrWgjaoxAfY8XVg7DbvQ/qxvI9Eg==} - - prosemirror-schema-basic@1.2.4: - resolution: {integrity: sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==} - - prosemirror-state@1.4.3: - resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} - - prosemirror-transform@1.10.4: - resolution: {integrity: sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw==} - - prosemirror-view@1.39.2: - resolution: {integrity: sha512-BmOkml0QWNob165gyUxXi5K5CVUgVPpqMEAAml/qzgKn9boLUWVPzQ6LtzXw8Cn1GtRQX4ELumPxqtLTDaAKtg==} + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} @@ -5513,10 +5951,6 @@ packages: pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} - punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} - engines: {node: '>=6'} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -5553,11 +5987,20 @@ packages: peerDependencies: react: '>=16.8.0' + react-devtools-inline@4.4.0: + resolution: {integrity: sha512-ES0GolSrKO8wsKbsEkVeiR/ZAaHQTY4zDh1UW8DImVmm8oaGLl3ijJDvSGe+qDRKPZdPRnDtWWnSvvrgxXdThQ==} + react-dom@19.1.0: resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} peerDependencies: react: ^19.1.0 + react-error-boundary@3.1.4: + resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==} + engines: {node: '>=10', npm: '>=6'} + peerDependencies: + react: '>=16.13.1' + react-hook-form@7.56.1: resolution: {integrity: sha512-qWAVokhSpshhcEuQDSANHx3jiAEFzu2HAaaQIzi/r9FNPm1ioAvuJSD4EuZzWd7Al7nTRKcKPnBKO7sRn+zavQ==} engines: {node: '>=18.0.0'} @@ -5572,6 +6015,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -5818,9 +6264,6 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rope-sequence@1.3.4: - resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} - router@2.2.0: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} @@ -6019,6 +6462,9 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + static-browser-server@1.0.3: + resolution: {integrity: sha512-ZUyfgGDdFRbZGGJQ1YhiM930Yczz5VlbJObrQLlk24+qNHVQx4OlLcYswEUo3bIyNAbQUIUR9Yr5/Hqjzqb4zA==} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -6034,6 +6480,9 @@ packages: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} + strict-event-emitter@0.4.6: + resolution: {integrity: sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -6079,6 +6528,9 @@ packages: string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -6157,8 +6609,8 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - tar-fs@2.1.2: - resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} + tar-fs@2.1.3: + resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==} tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} @@ -6293,6 +6745,9 @@ packages: resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} engines: {node: '>= 0.6'} + type@2.7.3: + resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -6321,9 +6776,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -6343,6 +6795,9 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + unidiff@1.0.4: + resolution: {integrity: sha512-ynU0vsAXw0ir8roa+xPCUHmnJ5goc5BTM2Kuc3IJd8UwgaeRs7VSD5+eeaQL+xp1JtB92hu/Zy/Lgy7RZcr1pQ==} + unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} @@ -6361,6 +6816,9 @@ packages: unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + unist-util-position@4.0.4: resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} @@ -6660,6 +7118,10 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yjs@13.6.27: + resolution: {integrity: sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -6945,75 +7407,238 @@ snapshots: '@codemirror/autocomplete@6.18.6': dependencies: - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 '@lezer/common': 1.2.3 '@codemirror/commands@6.8.1': dependencies: - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 '@lezer/common': 1.2.3 - '@codemirror/lang-css@6.3.1': + '@codemirror/lang-angular@0.1.4': + dependencies: + '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-javascript': 6.2.4 + '@codemirror/language': 6.11.1 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-cpp@6.0.2': + dependencies: + '@codemirror/language': 6.11.1 + '@lezer/cpp': 1.1.3 + + '@codemirror/lang-css@6.3.1': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@lezer/common': 1.2.3 + '@lezer/css': 1.2.1 + + '@codemirror/lang-go@6.0.1': dependencies: '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 - '@lezer/css': 1.1.11 + '@lezer/go': 1.0.1 '@codemirror/lang-html@6.4.9': dependencies: '@codemirror/autocomplete': 6.18.6 '@codemirror/lang-css': 6.3.1 - '@codemirror/lang-javascript': 6.2.3 - '@codemirror/language': 6.11.0 + '@codemirror/lang-javascript': 6.2.4 + '@codemirror/language': 6.11.1 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 '@lezer/common': 1.2.3 - '@lezer/css': 1.1.11 + '@lezer/css': 1.2.1 '@lezer/html': 1.3.10 - '@codemirror/lang-javascript@6.2.3': + '@codemirror/lang-java@6.0.1': + dependencies: + '@codemirror/language': 6.11.1 + '@lezer/java': 1.1.3 + + '@codemirror/lang-javascript@6.2.4': dependencies: '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/lint': 6.8.5 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 '@lezer/common': 1.2.3 '@lezer/javascript': 1.5.1 - '@codemirror/lang-python@6.2.0': + '@codemirror/lang-json@6.0.1': + dependencies: + '@codemirror/language': 6.11.1 + '@lezer/json': 1.0.3 + + '@codemirror/lang-less@6.0.2': + dependencies: + '@codemirror/lang-css': 6.3.1 + '@codemirror/language': 6.11.1 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-liquid@6.2.3': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/lang-html': 6.4.9 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.37.1 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-markdown@6.3.2': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/lang-html': 6.4.9 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.37.1 + '@lezer/common': 1.2.3 + '@lezer/markdown': 1.4.3 + + '@codemirror/lang-php@6.0.1': + dependencies: + '@codemirror/lang-html': 6.4.9 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@lezer/common': 1.2.3 + '@lezer/php': 1.0.2 + + '@codemirror/lang-python@6.2.1': dependencies: '@codemirror/autocomplete': 6.18.6 - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/state': 6.5.2 '@lezer/common': 1.2.3 '@lezer/python': 1.1.18 - '@codemirror/language@6.11.0': + '@codemirror/lang-rust@6.0.1': + dependencies: + '@codemirror/language': 6.11.1 + '@lezer/rust': 1.0.2 + + '@codemirror/lang-sass@6.0.2': + dependencies: + '@codemirror/lang-css': 6.3.1 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@lezer/common': 1.2.3 + '@lezer/sass': 1.1.0 + + '@codemirror/lang-sql@6.9.0': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-vue@0.1.3': + dependencies: + '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-javascript': 6.2.4 + '@codemirror/language': 6.11.1 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-wast@6.0.2': + dependencies: + '@codemirror/language': 6.11.1 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@codemirror/lang-xml@6.1.0': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.37.1 + '@lezer/common': 1.2.3 + '@lezer/xml': 1.0.6 + + '@codemirror/lang-yaml@6.1.2': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + '@lezer/yaml': 1.0.3 + + '@codemirror/language-data@6.5.1': + dependencies: + '@codemirror/lang-angular': 0.1.4 + '@codemirror/lang-cpp': 6.0.2 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-go': 6.0.1 + '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-java': 6.0.1 + '@codemirror/lang-javascript': 6.2.4 + '@codemirror/lang-json': 6.0.1 + '@codemirror/lang-less': 6.0.2 + '@codemirror/lang-liquid': 6.2.3 + '@codemirror/lang-markdown': 6.3.2 + '@codemirror/lang-php': 6.0.1 + '@codemirror/lang-python': 6.2.1 + '@codemirror/lang-rust': 6.0.1 + '@codemirror/lang-sass': 6.0.2 + '@codemirror/lang-sql': 6.9.0 + '@codemirror/lang-vue': 0.1.3 + '@codemirror/lang-wast': 6.0.2 + '@codemirror/lang-xml': 6.1.0 + '@codemirror/lang-yaml': 6.1.2 + '@codemirror/language': 6.11.1 + '@codemirror/legacy-modes': 6.5.1 + + '@codemirror/language@6.11.1': dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 '@lezer/common': 1.2.3 '@lezer/highlight': 1.2.1 '@lezer/lr': 1.4.2 style-mod: 4.1.2 + '@codemirror/legacy-modes@6.5.1': + dependencies: + '@codemirror/language': 6.11.1 + '@codemirror/lint@6.8.5': dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 crelt: 1.0.6 - '@codemirror/search@6.5.10': + '@codemirror/merge@6.10.1': + dependencies: + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.37.1 + '@lezer/highlight': 1.2.1 + style-mod: 4.1.2 + + '@codemirror/search@6.5.11': dependencies: '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 crelt: 1.0.6 '@codemirror/state@6.5.2': @@ -7022,17 +7647,56 @@ snapshots: '@codemirror/theme-one-dark@6.1.2': dependencies: - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 '@lezer/highlight': 1.2.1 - '@codemirror/view@6.36.7': + '@codemirror/view@6.37.1': dependencies: '@codemirror/state': 6.5.2 + crelt: 1.0.6 style-mod: 4.1.2 w3c-keyname: 2.2.8 + '@codesandbox/nodebox@0.1.8': + dependencies: + outvariant: 1.4.0 + strict-event-emitter: 0.4.6 + + '@codesandbox/sandpack-client@2.19.8': + dependencies: + '@codesandbox/nodebox': 0.1.8 + buffer: 6.0.3 + dequal: 2.0.3 + mime-db: 1.54.0 + outvariant: 1.4.0 + static-browser-server: 1.0.3 + + '@codesandbox/sandpack-react@2.20.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@codemirror/autocomplete': 6.18.6 + '@codemirror/commands': 6.8.1 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-html': 6.4.9 + '@codemirror/lang-javascript': 6.2.4 + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.37.1 + '@codesandbox/sandpack-client': 2.19.8 + '@lezer/highlight': 1.2.1 + '@react-hook/intersection-observer': 3.1.2(react@19.1.0) + '@stitches/core': 1.2.8 + anser: 2.3.2 + clean-set: 1.1.2 + dequal: 2.0.3 + escape-carriage: 1.3.1 + lz-string: 1.5.0 + react: 19.1.0 + react-devtools-inline: 4.4.0 + react-dom: 19.1.0(react@19.1.0) + react-is: 17.0.2 + '@connectrpc/connect-web@2.0.0-rc.3(@bufbuild/protobuf@2.3.0)(@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.3.0))': dependencies: '@bufbuild/protobuf': 2.3.0 @@ -7403,9 +8067,168 @@ snapshots: '@jsdevtools/ono@7.1.3': {} + '@lexical/clipboard@0.27.2': + dependencies: + '@lexical/html': 0.27.2 + '@lexical/list': 0.27.2 + '@lexical/selection': 0.27.2 + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/code@0.27.2': + dependencies: + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + prismjs: 1.30.0 + + '@lexical/devtools-core@0.27.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@lexical/html': 0.27.2 + '@lexical/link': 0.27.2 + '@lexical/mark': 0.27.2 + '@lexical/table': 0.27.2 + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + + '@lexical/dragon@0.27.2': + dependencies: + lexical: 0.27.2 + + '@lexical/hashtag@0.27.2': + dependencies: + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/history@0.27.2': + dependencies: + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/html@0.27.2': + dependencies: + '@lexical/selection': 0.27.2 + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/link@0.27.2': + dependencies: + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/list@0.27.2': + dependencies: + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/mark@0.27.2': + dependencies: + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/markdown@0.27.2': + dependencies: + '@lexical/code': 0.27.2 + '@lexical/link': 0.27.2 + '@lexical/list': 0.27.2 + '@lexical/rich-text': 0.27.2 + '@lexical/text': 0.27.2 + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/offset@0.27.2': + dependencies: + lexical: 0.27.2 + + '@lexical/overflow@0.27.2': + dependencies: + lexical: 0.27.2 + + '@lexical/plain-text@0.27.2': + dependencies: + '@lexical/clipboard': 0.27.2 + '@lexical/selection': 0.27.2 + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/react@0.27.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(yjs@13.6.27)': + dependencies: + '@lexical/clipboard': 0.27.2 + '@lexical/code': 0.27.2 + '@lexical/devtools-core': 0.27.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@lexical/dragon': 0.27.2 + '@lexical/hashtag': 0.27.2 + '@lexical/history': 0.27.2 + '@lexical/link': 0.27.2 + '@lexical/list': 0.27.2 + '@lexical/mark': 0.27.2 + '@lexical/markdown': 0.27.2 + '@lexical/overflow': 0.27.2 + '@lexical/plain-text': 0.27.2 + '@lexical/rich-text': 0.27.2 + '@lexical/selection': 0.27.2 + '@lexical/table': 0.27.2 + '@lexical/text': 0.27.2 + '@lexical/utils': 0.27.2 + '@lexical/yjs': 0.27.2(yjs@13.6.27) + lexical: 0.27.2 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-error-boundary: 3.1.4(react@19.1.0) + transitivePeerDependencies: + - yjs + + '@lexical/rich-text@0.27.2': + dependencies: + '@lexical/clipboard': 0.27.2 + '@lexical/selection': 0.27.2 + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/selection@0.27.2': + dependencies: + lexical: 0.27.2 + + '@lexical/table@0.27.2': + dependencies: + '@lexical/clipboard': 0.27.2 + '@lexical/utils': 0.27.2 + lexical: 0.27.2 + + '@lexical/text@0.27.2': + dependencies: + lexical: 0.27.2 + + '@lexical/utils@0.27.2': + dependencies: + '@lexical/list': 0.27.2 + '@lexical/selection': 0.27.2 + '@lexical/table': 0.27.2 + lexical: 0.27.2 + + '@lexical/yjs@0.27.2(yjs@13.6.27)': + dependencies: + '@lexical/offset': 0.27.2 + '@lexical/selection': 0.27.2 + lexical: 0.27.2 + yjs: 13.6.27 + '@lezer/common@1.2.3': {} - '@lezer/css@1.1.11': + '@lezer/cpp@1.1.3': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/css@1.2.1': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/go@1.0.1': dependencies: '@lezer/common': 1.2.3 '@lezer/highlight': 1.2.1 @@ -7421,22 +8244,69 @@ snapshots: '@lezer/highlight': 1.2.1 '@lezer/lr': 1.4.2 + '@lezer/java@1.1.3': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + '@lezer/javascript@1.5.1': dependencies: '@lezer/common': 1.2.3 '@lezer/highlight': 1.2.1 '@lezer/lr': 1.4.2 + '@lezer/json@1.0.3': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + '@lezer/lr@1.4.2': dependencies: '@lezer/common': 1.2.3 + '@lezer/markdown@1.4.3': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + + '@lezer/php@1.0.2': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + '@lezer/python@1.1.18': dependencies: '@lezer/common': 1.2.3 '@lezer/highlight': 1.2.1 '@lezer/lr': 1.4.2 + '@lezer/rust@1.0.2': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/sass@1.1.0': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/xml@1.0.6': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/yaml@1.0.3': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + '@llama-flow/core@0.4.1(@modelcontextprotocol/sdk@1.12.1)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(p-retry@6.2.1)(zod@3.24.3)': optionalDependencies: '@modelcontextprotocol/sdk': 1.12.1 @@ -7451,13 +8321,14 @@ snapshots: p-retry: 6.2.1 zod: 3.25.13 - '@llamaindex/chat-ui@0.5.2(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.7)(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@llamaindex/chat-ui@0.5.6(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.1)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.37.1)(@lezer/highlight@1.2.1)(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(yjs@13.6.27)': dependencies: '@codemirror/lang-css': 6.3.1 '@codemirror/lang-html': 6.4.9 - '@codemirror/lang-javascript': 6.2.3 - '@codemirror/lang-python': 6.2.0 + '@codemirror/lang-javascript': 6.2.4 + '@codemirror/lang-python': 6.2.1 '@llamaindex/pdf-viewer': 1.3.0(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@mdxeditor/editor': 3.35.0(@codemirror/language@6.11.1)(@lezer/highlight@1.2.1)(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(yjs@13.6.27) '@radix-ui/react-accordion': 1.2.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-collapsible': 1.1.8(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-hover-card': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -7465,23 +8336,15 @@ snapshots: '@radix-ui/react-popover': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-progress': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-select': 2.2.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.0(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.2)(react@19.1.0) '@radix-ui/react-tabs': 1.1.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@uiw/codemirror-theme-github': 4.23.12(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.7) - '@uiw/react-codemirror': 4.23.12(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.7)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@uiw/codemirror-theme-github': 4.23.12(@codemirror/language@6.11.1)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1) + '@uiw/react-codemirror': 4.23.12(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.1)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.37.1)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) class-variance-authority: 0.7.1 clsx: 2.1.1 highlight.js: 11.11.1 katex: 0.16.22 lucide-react: 0.453.0(react@19.1.0) - prosemirror-commands: 1.7.1 - prosemirror-history: 1.4.1 - prosemirror-keymap: 1.2.3 - prosemirror-markdown: 1.13.2 - prosemirror-menu: 1.2.5 - prosemirror-schema-basic: 1.2.4 - prosemirror-state: 1.4.3 - prosemirror-view: 1.39.2 react: 19.1.0 react-markdown: 8.0.7(@types/react@19.1.2)(react@19.1.0) rehype-katex: 7.0.1 @@ -7502,11 +8365,13 @@ snapshots: - '@codemirror/state' - '@codemirror/theme-one-dark' - '@codemirror/view' + - '@lezer/highlight' - '@types/react' - '@types/react-dom' - codemirror - react-dom - supports-color + - yjs '@llamaindex/cloud@4.0.9(@llama-flow/core@0.4.1(@modelcontextprotocol/sdk@1.12.1)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(p-retry@6.2.1)(zod@3.24.3))(@llamaindex/core@0.6.6)(@llamaindex/env@0.1.30)': dependencies: @@ -7665,6 +8530,77 @@ snapshots: '@marijn/find-cluster-break@1.0.2': {} + '@mdxeditor/editor@3.35.0(@codemirror/language@6.11.1)(@lezer/highlight@1.2.1)(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(yjs@13.6.27)': + dependencies: + '@codemirror/commands': 6.8.1 + '@codemirror/lang-markdown': 6.3.2 + '@codemirror/language-data': 6.5.1 + '@codemirror/merge': 6.10.1 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.37.1 + '@codesandbox/sandpack-react': 2.20.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@lexical/clipboard': 0.27.2 + '@lexical/link': 0.27.2 + '@lexical/list': 0.27.2 + '@lexical/markdown': 0.27.2 + '@lexical/plain-text': 0.27.2 + '@lexical/react': 0.27.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(yjs@13.6.27) + '@lexical/rich-text': 0.27.2 + '@lexical/selection': 0.27.2 + '@lexical/utils': 0.27.2 + '@mdxeditor/gurx': 1.2.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/colors': 3.0.0 + '@radix-ui/react-dialog': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-icons': 1.3.2(react@19.1.0) + '@radix-ui/react-popover': 1.1.11(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-popper': 1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-select': 2.2.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-toggle-group': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-toolbar': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-tooltip': 1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + classnames: 2.5.1 + cm6-theme-basic-light: 0.2.0(@codemirror/language@6.11.1)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1)(@lezer/highlight@1.2.1) + codemirror: 6.0.1 + downshift: 7.6.2(react@19.1.0) + js-yaml: 4.1.0 + lexical: 0.27.2 + mdast-util-directive: 3.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-frontmatter: 2.0.1 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-mdx: 3.0.0 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-to-markdown: 2.1.2 + micromark-extension-directive: 3.0.2 + micromark-extension-frontmatter: 2.0.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-extension-mdx-jsx: 3.0.2 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs: 3.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-hook-form: 7.56.1(react@19.1.0) + unidiff: 1.0.4 + transitivePeerDependencies: + - '@codemirror/language' + - '@lezer/highlight' + - '@types/react' + - '@types/react-dom' + - supports-color + - yjs + + '@mdxeditor/gurx@1.2.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + '@modelcontextprotocol/sdk@1.12.1': dependencies: ajv: 6.12.6 @@ -7732,6 +8668,8 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@open-draft/deferred-promise@2.2.0': {} + '@opentelemetry/api@1.9.0': {} '@pkgjs/parseargs@0.11.0': @@ -7741,6 +8679,8 @@ snapshots: dependencies: playwright: 1.52.0 + '@radix-ui/colors@3.0.0': {} + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.2': {} @@ -7851,6 +8791,18 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.2)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.2)(react@19.1.0)': dependencies: react: 19.1.0 @@ -8123,6 +9075,15 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.2)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-progress@1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) @@ -8151,6 +9112,23 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-roving-focus@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-roving-focus@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -8223,6 +9201,15 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-separator@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-slider@1.3.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/number': 1.1.1 @@ -8249,6 +9236,13 @@ snapshots: optionalDependencies: '@types/react': 19.1.2 + '@radix-ui/react-slot@1.2.3(@types/react@19.1.2)(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.2 + '@radix-ui/react-switch@1.2.2(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -8280,6 +9274,21 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-toggle-group@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-toggle': 1.1.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-toggle-group@1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -8306,6 +9315,32 @@ snapshots: '@types/react': 19.1.2 '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-toggle@1.1.9(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + '@types/react-dom': 19.1.2(@types/react@19.1.2) + + '@radix-ui/react-toolbar@1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.2)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-toggle-group': 1.1.10(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.2 + '@types/react-dom': 19.1.2(@types/react@19.1.2) + '@radix-ui/react-tooltip@1.2.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -8398,6 +9433,16 @@ snapshots: '@radix-ui/rect@1.1.1': {} + '@react-hook/intersection-observer@3.1.2(react@19.1.0)': + dependencies: + '@react-hook/passive-layout-effect': 1.2.1(react@19.1.0) + intersection-observer: 0.10.0 + react: 19.1.0 + + '@react-hook/passive-layout-effect@1.2.1(react@19.1.0)': + dependencies: + react: 19.1.0 + '@rollup/plugin-commonjs@28.0.3(rollup@4.40.0)': dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.40.0) @@ -8542,6 +9587,8 @@ snapshots: '@standard-schema/utils@0.3.0': {} + '@stitches/core@1.2.8': {} + '@swc/core-darwin-arm64@1.11.22': optional: true @@ -8755,6 +9802,10 @@ snapshots: '@types/diff-match-patch@1.0.36': {} + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.7 + '@types/estree@1.0.7': {} '@types/fs-extra@11.0.4': @@ -8786,15 +9837,8 @@ snapshots: dependencies: '@types/node': 20.17.30 - '@types/linkify-it@5.0.0': {} - '@types/lodash@4.17.16': {} - '@types/markdown-it@14.1.2': - dependencies: - '@types/linkify-it': 5.0.0 - '@types/mdurl': 2.0.0 - '@types/mdast@3.0.15': dependencies: '@types/unist': 2.0.11 @@ -8803,8 +9847,6 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/mdurl@2.0.0': {} - '@types/ms@2.1.0': {} '@types/node-fetch@2.6.12': @@ -8939,38 +9981,38 @@ snapshots: '@typescript-eslint/types': 8.31.0 eslint-visitor-keys: 4.2.0 - '@uiw/codemirror-extensions-basic-setup@4.23.12(@codemirror/autocomplete@6.18.6)(@codemirror/commands@6.8.1)(@codemirror/language@6.11.0)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/view@6.36.7)': + '@uiw/codemirror-extensions-basic-setup@4.23.12(@codemirror/autocomplete@6.18.6)(@codemirror/commands@6.8.1)(@codemirror/language@6.11.1)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1)': dependencies: '@codemirror/autocomplete': 6.18.6 '@codemirror/commands': 6.8.1 - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/lint': 6.8.5 - '@codemirror/search': 6.5.10 + '@codemirror/search': 6.5.11 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 - '@uiw/codemirror-theme-github@4.23.12(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.7)': + '@uiw/codemirror-theme-github@4.23.12(@codemirror/language@6.11.1)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1)': dependencies: - '@uiw/codemirror-themes': 4.23.12(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.7) + '@uiw/codemirror-themes': 4.23.12(@codemirror/language@6.11.1)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1) transitivePeerDependencies: - '@codemirror/language' - '@codemirror/state' - '@codemirror/view' - '@uiw/codemirror-themes@4.23.12(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.7)': + '@uiw/codemirror-themes@4.23.12(@codemirror/language@6.11.1)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1)': dependencies: - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 - '@uiw/react-codemirror@4.23.12(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.0)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.36.7)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@uiw/react-codemirror@4.23.12(@babel/runtime@7.27.0)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.1)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.37.1)(codemirror@6.0.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@babel/runtime': 7.27.0 '@codemirror/commands': 6.8.1 '@codemirror/state': 6.5.2 '@codemirror/theme-one-dark': 6.1.2 - '@codemirror/view': 6.36.7 - '@uiw/codemirror-extensions-basic-setup': 4.23.12(@codemirror/autocomplete@6.18.6)(@codemirror/commands@6.8.1)(@codemirror/language@6.11.0)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.10)(@codemirror/state@6.5.2)(@codemirror/view@6.36.7) + '@codemirror/view': 6.37.1 + '@uiw/codemirror-extensions-basic-setup': 4.23.12(@codemirror/autocomplete@6.18.6)(@codemirror/commands@6.8.1)(@codemirror/language@6.11.1)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1) codemirror: 6.0.1 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) @@ -9141,6 +10183,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + anser@2.3.2: {} + ansi-colors@4.1.3: {} ansi-escapes@5.0.0: @@ -9340,6 +10384,11 @@ snapshots: ieee754: 1.2.1 optional: true + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + builtins@1.0.3: {} bunchee@6.4.0(typescript@5.8.3): @@ -9460,8 +10509,14 @@ snapshots: chalk@5.4.1: {} + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + character-entities@2.0.2: {} + character-reference-invalid@2.0.1: {} + chardet@0.7.0: {} check-error@2.1.1: {} @@ -9491,10 +10546,14 @@ snapshots: dependencies: clsx: 2.1.1 + classnames@2.5.1: {} + clean-css@5.3.3: dependencies: source-map: 0.6.1 + clean-set@1.1.2: {} + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -9520,6 +10579,13 @@ snapshots: clsx@2.1.1: {} + cm6-theme-basic-light@0.2.0(@codemirror/language@6.11.1)(@codemirror/state@6.5.2)(@codemirror/view@6.37.1)(@lezer/highlight@1.2.1): + dependencies: + '@codemirror/language': 6.11.1 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.37.1 + '@lezer/highlight': 1.2.1 + cmdk@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0) @@ -9536,11 +10602,11 @@ snapshots: dependencies: '@codemirror/autocomplete': 6.18.6 '@codemirror/commands': 6.8.1 - '@codemirror/language': 6.11.0 + '@codemirror/language': 6.11.1 '@codemirror/lint': 6.8.5 - '@codemirror/search': 6.5.10 + '@codemirror/search': 6.5.11 '@codemirror/state': 6.5.2 - '@codemirror/view': 6.36.7 + '@codemirror/view': 6.37.1 color-convert@2.0.1: dependencies: @@ -9583,6 +10649,8 @@ snapshots: compare-versions@6.1.1: {} + compute-scroll-into-view@2.0.4: {} + concat-map@0.0.1: {} console-control-strings@1.1.0: @@ -9661,6 +10729,11 @@ snapshots: d3-timer@3.0.1: {} + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + damerau-levenshtein@1.0.8: {} data-view-buffer@1.0.2: @@ -9798,6 +10871,15 @@ snapshots: dotenv@16.5.0: {} + downshift@7.6.2(react@19.1.0): + dependencies: + '@babel/runtime': 7.27.0 + compute-scroll-into-view: 2.0.4 + prop-types: 15.8.1 + react: 19.1.0 + react-is: 17.0.2 + tslib: 2.8.1 + duck-duck-scrape@2.2.7: dependencies: html-entities: 2.6.0 @@ -9968,8 +11050,26 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + es6-error@4.1.1: {} + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -10026,6 +11126,8 @@ snapshots: escalade@3.2.0: {} + escape-carriage@1.3.1: {} + escape-html@1.0.3: {} escape-string-regexp@4.0.0: {} @@ -10215,6 +11317,13 @@ snapshots: transitivePeerDependencies: - supports-color + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + espree@10.3.0: dependencies: acorn: 8.14.1 @@ -10233,6 +11342,13 @@ snapshots: estraverse@5.3.0: {} + estree-util-is-identifier-name@3.0.0: {} + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 + estree-walker@2.0.2: {} estree-walker@3.0.3: @@ -10243,6 +11359,11 @@ snapshots: etag@1.8.1: {} + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-target-shim@5.0.1: {} eventemitter3@4.0.7: {} @@ -10308,6 +11429,10 @@ snapshots: transitivePeerDependencies: - supports-color + ext@1.7.0: + dependencies: + type: 2.7.3 + extend@3.0.2: {} extendable-error@0.1.7: {} @@ -10348,6 +11473,10 @@ snapshots: dependencies: reusify: 1.1.0 + fault@2.0.1: + dependencies: + format: 0.2.2 + fdir@6.4.4(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 @@ -10410,6 +11539,8 @@ snapshots: es-set-tostringtag: 2.1.0 mime-types: 2.1.35 + format@0.2.2: {} + formdata-node@4.4.1: dependencies: node-domexception: 1.0.0 @@ -10682,7 +11813,7 @@ snapshots: '@types/unist': 3.0.3 devlop: 1.1.0 hastscript: 9.0.1 - property-information: 7.0.0 + property-information: 7.1.0 vfile: 6.0.3 vfile-location: 5.0.3 web-namespaces: 2.0.1 @@ -10709,7 +11840,7 @@ snapshots: '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 hast-util-parse-selector: 4.0.0 - property-information: 7.0.0 + property-information: 7.1.0 space-separated-tokens: 2.0.2 highlight.js@11.11.1: {} @@ -10772,8 +11903,7 @@ snapshots: dependencies: safer-buffer: 2.1.2 - ieee754@1.2.1: - optional: true + ieee754@1.2.1: {} ignore-by-default@1.0.1: {} @@ -10817,8 +11947,17 @@ snapshots: internmap@2.0.3: {} + intersection-observer@0.10.0: {} + ipaddr.js@1.9.1: {} + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -10872,6 +12011,8 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-decimal@2.0.1: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -10897,6 +12038,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-hexadecimal@2.0.1: {} + is-interactive@2.0.0: {} is-map@2.0.3: {} @@ -10979,6 +12122,8 @@ snapshots: isexe@2.0.0: {} + isomorphic.js@0.2.5: {} + iterator.prototype@1.1.5: dependencies: define-data-property: 1.1.4 @@ -11084,6 +12229,12 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lexical@0.27.2: {} + + lib0@0.2.108: + dependencies: + isomorphic.js: 0.2.5 + lie@3.3.0: dependencies: immediate: 3.0.6 @@ -11135,10 +12286,6 @@ snapshots: lilconfig@3.1.3: {} - linkify-it@5.0.0: - dependencies: - uc.micro: 2.1.0 - lint-staged@15.5.1: dependencies: chalk: 5.4.1 @@ -11260,6 +12407,8 @@ snapshots: dependencies: react: 19.1.0 + lz-string@1.5.0: {} + magic-bytes.js@1.12.1: {} magic-string@0.30.17: @@ -11288,15 +12437,6 @@ snapshots: underscore: 1.13.7 xmlbuilder: 10.1.1 - markdown-it@14.1.0: - dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.0 - mdurl: 2.0.0 - punycode.js: 2.3.1 - uc.micro: 2.1.0 - markdown-table@3.0.4: {} marked@14.1.4: {} @@ -11313,6 +12453,20 @@ snapshots: '@types/unist': 2.0.11 unist-util-visit: 4.1.2 + mdast-util-directive@3.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-visit-parents: 6.0.1 + transitivePeerDependencies: + - supports-color + mdast-util-find-and-replace@2.2.2: dependencies: '@types/mdast': 3.0.15 @@ -11354,6 +12508,17 @@ snapshots: transitivePeerDependencies: - supports-color + mdast-util-frontmatter@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + escape-string-regexp: 5.0.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + micromark-extension-frontmatter: 2.0.0 + transitivePeerDependencies: + - supports-color + mdast-util-gfm-autolink-literal@1.0.3: dependencies: '@types/mdast': 3.0.15 @@ -11372,6 +12537,14 @@ snapshots: '@types/mdast': 3.0.15 mdast-util-to-markdown: 1.5.0 + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + mdast-util-gfm-table@1.0.7: dependencies: '@types/mdast': 3.0.15 @@ -11381,11 +12554,30 @@ snapshots: transitivePeerDependencies: - supports-color + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + mdast-util-gfm-task-list-item@1.0.2: dependencies: '@types/mdast': 3.0.15 mdast-util-to-markdown: 1.5.0 + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + mdast-util-gfm@2.0.2: dependencies: mdast-util-from-markdown: 1.3.1 @@ -11404,6 +12596,55 @@ snapshots: longest-streak: 3.1.0 mdast-util-to-markdown: 1.5.0 + mdast-util-mdx-expression@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.2.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.2 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + mdast-util-phrasing@3.0.1: dependencies: '@types/mdast': 3.0.15 @@ -11456,8 +12697,6 @@ snapshots: dependencies: '@types/mdast': 4.0.4 - mdurl@2.0.0: {} - media-typer@1.1.0: {} memoize-one@5.2.1: {} @@ -11510,6 +12749,23 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 + micromark-extension-directive@3.0.2: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + parse-entities: 4.0.2 + + micromark-extension-frontmatter@2.0.0: + dependencies: + fault: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + micromark-extension-gfm-autolink-literal@1.0.5: dependencies: micromark-util-character: 1.2.0 @@ -11537,6 +12793,15 @@ snapshots: micromark-util-types: 1.1.0 uvu: 0.5.6 + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + micromark-extension-gfm-table@1.0.7: dependencies: micromark-factory-space: 1.1.0 @@ -11545,6 +12810,14 @@ snapshots: micromark-util-types: 1.1.0 uvu: 0.5.6 + micromark-extension-gfm-table@2.1.1: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + micromark-extension-gfm-tagfilter@1.0.2: dependencies: micromark-util-types: 1.1.0 @@ -11557,6 +12830,14 @@ snapshots: micromark-util-types: 1.1.0 uvu: 0.5.6 + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + micromark-extension-gfm@2.0.3: dependencies: micromark-extension-gfm-autolink-literal: 1.0.5 @@ -11578,6 +12859,57 @@ snapshots: micromark-util-types: 1.1.0 uvu: 0.5.6 + micromark-extension-mdx-expression@3.0.1: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-jsx@3.0.2: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.2 + + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-mdxjs-esm@3.0.0: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + + micromark-extension-mdxjs@3.0.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + micromark-extension-mdx-expression: 3.0.1 + micromark-extension-mdx-jsx: 3.0.2 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + micromark-factory-destination@1.1.0: dependencies: micromark-util-character: 1.2.0 @@ -11604,6 +12936,18 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 + micromark-factory-mdx-expression@2.0.3: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + micromark-factory-space@1.1.0: dependencies: micromark-util-character: 1.2.0 @@ -11708,6 +13052,16 @@ snapshots: micromark-util-encode@2.0.1: {} + micromark-util-events-to-acorn@2.0.3: + dependencies: + '@types/estree': 1.0.7 + '@types/unist': 3.0.3 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.2 + micromark-util-html-tag-name@1.2.0: {} micromark-util-html-tag-name@2.0.1: {} @@ -11895,6 +13249,8 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) + next-tick@1.1.0: {} + next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@next/env': 15.3.1 @@ -11922,7 +13278,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - node-abi@3.74.0: + node-abi@3.75.0: dependencies: semver: 7.7.1 optional: true @@ -12083,12 +13439,12 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.0 - orderedmap@2.1.1: {} - os-tmpdir@1.0.2: {} outdent@0.5.0: {} + outvariant@1.4.0: {} + own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 @@ -12153,6 +13509,16 @@ snapshots: dependencies: callsites: 3.1.0 + parse-entities@4.0.2: + dependencies: + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.1.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + parse5@7.3.0: dependencies: entities: 6.0.0 @@ -12278,11 +13644,11 @@ snapshots: minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 2.0.0 - node-abi: 3.74.0 + node-abi: 3.75.0 pump: 3.0.2 rc: 1.2.8 simple-get: 4.0.1 - tar-fs: 2.1.2 + tar-fs: 2.1.3 tunnel-agent: 0.6.0 optional: true @@ -12307,6 +13673,8 @@ snapshots: pretty-hrtime@1.0.3: {} + prismjs@1.30.0: {} + process-nextick-args@2.0.1: {} prompts@2.4.2: @@ -12322,62 +13690,7 @@ snapshots: property-information@6.5.0: {} - property-information@7.0.0: {} - - prosemirror-commands@1.7.1: - dependencies: - prosemirror-model: 1.25.1 - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - - prosemirror-history@1.4.1: - dependencies: - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - prosemirror-view: 1.39.2 - rope-sequence: 1.3.4 - - prosemirror-keymap@1.2.3: - dependencies: - prosemirror-state: 1.4.3 - w3c-keyname: 2.2.8 - - prosemirror-markdown@1.13.2: - dependencies: - '@types/markdown-it': 14.1.2 - markdown-it: 14.1.0 - prosemirror-model: 1.25.1 - - prosemirror-menu@1.2.5: - dependencies: - crelt: 1.0.6 - prosemirror-commands: 1.7.1 - prosemirror-history: 1.4.1 - prosemirror-state: 1.4.3 - - prosemirror-model@1.25.1: - dependencies: - orderedmap: 2.1.1 - - prosemirror-schema-basic@1.2.4: - dependencies: - prosemirror-model: 1.25.1 - - prosemirror-state@1.4.3: - dependencies: - prosemirror-model: 1.25.1 - prosemirror-transform: 1.10.4 - prosemirror-view: 1.39.2 - - prosemirror-transform@1.10.4: - dependencies: - prosemirror-model: 1.25.1 - - prosemirror-view@1.39.2: - dependencies: - prosemirror-model: 1.25.1 - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 + property-information@7.1.0: {} proxy-addr@2.0.7: dependencies: @@ -12393,8 +13706,6 @@ snapshots: end-of-stream: 1.4.4 once: 1.4.0 - punycode.js@2.3.1: {} - punycode@2.3.1: {} qs@6.14.0: @@ -12430,11 +13741,20 @@ snapshots: date-fns-jalali: 4.1.0-0 react: 19.1.0 + react-devtools-inline@4.4.0: + dependencies: + es6-symbol: 3.1.4 + react-dom@19.1.0(react@19.1.0): dependencies: react: 19.1.0 scheduler: 0.26.0 + react-error-boundary@3.1.4(react@19.1.0): + dependencies: + '@babel/runtime': 7.27.0 + react: 19.1.0 + react-hook-form@7.56.1(react@19.1.0): dependencies: react: 19.1.0 @@ -12445,6 +13765,8 @@ snapshots: react-is@16.13.1: {} + react-is@17.0.2: {} + react-is@18.3.1: {} react-markdown@8.0.7(@types/react@19.1.2)(react@19.1.0): @@ -12804,8 +14126,6 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.40.0 fsevents: 2.3.3 - rope-sequence@1.3.4: {} - router@2.2.0: dependencies: debug: 4.4.0(supports-color@5.5.0) @@ -13060,6 +14380,13 @@ snapshots: stackback@0.0.2: {} + static-browser-server@1.0.3: + dependencies: + '@open-draft/deferred-promise': 2.2.0 + dotenv: 16.5.0 + mime-db: 1.54.0 + outvariant: 1.4.0 + statuses@2.0.1: {} std-env@3.9.0: {} @@ -13068,6 +14395,8 @@ snapshots: streamsearch@1.1.0: {} + strict-event-emitter@0.4.6: {} + string-argv@0.3.2: {} string-width@4.2.3: @@ -13147,6 +14476,11 @@ snapshots: safe-buffer: 5.2.1 optional: true + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -13205,7 +14539,7 @@ snapshots: tapable@2.2.1: {} - tar-fs@2.1.2: + tar-fs@2.1.3: dependencies: chownr: 1.1.4 mkdirp-classic: 0.5.3 @@ -13338,6 +14672,8 @@ snapshots: media-typer: 1.1.0 mime-types: 3.0.1 + type@2.7.3: {} + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -13383,8 +14719,6 @@ snapshots: typescript@5.8.3: {} - uc.micro@2.1.0: {} - unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -13402,6 +14736,10 @@ snapshots: undici-types@6.21.0: {} + unidiff@1.0.4: + dependencies: + diff: 5.2.0 + unified@10.1.2: dependencies: '@types/unist': 2.0.11 @@ -13437,6 +14775,10 @@ snapshots: dependencies: '@types/unist': 3.0.3 + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-position@4.0.4: dependencies: '@types/unist': 2.0.11 @@ -13830,6 +15172,10 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yjs@13.6.27: + dependencies: + lib0: 0.2.108 + yocto-queue@0.1.0: {} zod-to-json-schema@3.24.5(zod@3.24.3): diff --git a/python/llama-index-server/README.md b/python/llama-index-server/README.md index ebf312356..9c362481a 100644 --- a/python/llama-index-server/README.md +++ b/python/llama-index-server/README.md @@ -78,6 +78,7 @@ The LlamaIndexServer accepts the following configuration parameters: - `env`: Environment setting ('dev' enables CORS and UI by default) - `ui_config`: UI configuration as a dictionary or UIConfig object with options: - `enabled`: Whether to enable the chat UI (default: True) + - `enable_file_upload`: Whether to enable file upload in the chat UI (default: False). Check [How to get the uploaded files in your workflow](https://github.com/run-llama/create-llama/blob/main/python/llama-index-server/examples/private_file/README.md#how-to-get-the-uploaded-files-in-your-workflow) for more details. - `starter_questions`: List of starter questions for the chat UI (default: None) - `ui_path`: Path for downloaded UI static files (default: ".ui") - `component_dir`: The directory for custom UI components rendering events emitted by the workflow. The default is None, which does not render custom UI components. @@ -161,6 +162,7 @@ app = LlamaIndexServer( The server provides the following default endpoints: - `/api/chat`: Chat interaction endpoint +- `/api/chat/file`: File upload endpoint (only available when `enable_file_upload` in `ui_config` is True) - `/api/files/data/*`: Access to data directory files - `/api/files/output/*`: Access to output directory files diff --git a/python/llama-index-server/examples/artifact/main.py b/python/llama-index-server/examples/artifact/main.py index d32bafe90..5d40c4799 100644 --- a/python/llama-index-server/examples/artifact/main.py +++ b/python/llama-index-server/examples/artifact/main.py @@ -1,9 +1,8 @@ +from code_workflow import ArtifactWorkflow from fastapi import FastAPI -from examples.artifact.code_workflow import ArtifactWorkflow - # To use document artifact workflow, uncomment the following line -# from examples.artifact.document_workflow import ArtifactWorkflow +# from document_workflow import ArtifactWorkflow from llama_index.core.workflow import Workflow from llama_index.llms.openai import OpenAI from llama_index.server import LlamaIndexServer, UIConfig diff --git a/python/llama-index-server/examples/private_file/README.md b/python/llama-index-server/examples/private_file/README.md new file mode 100644 index 000000000..c9ffd3337 --- /dev/null +++ b/python/llama-index-server/examples/private_file/README.md @@ -0,0 +1,102 @@ +# Uploaded File + +This example shows how to use the uploaded file (private file) from the user in the workflow. + +## Prerequisites + +Please follow the setup instructions in the [examples README](../README.md). + +You will also need: +- An OpenAI API key +- Text files for processing (the examples are optimized for smaller text files) + +## How to get the uploaded files in your workflow: + +The uploaded file information is included in the annotations of a [ChatAPIMessage](../../llama_index/server/models/chat.py#66). You can manually access it through the `chat_request` parameter in the workflow factory. We already provided a [get_file_attachments](../../llama_index/server/utils/chat_attachments.py) helper function to get the uploaded files from the chat request easier. + +```python +from llama_index.server.api.utils.chat_attachments import get_file_attachments + +def create_workflow(chat_request: ChatRequest) -> Workflow: + uploaded_files = get_file_attachments(chat_request.messages) + ... +``` + +Each uploaded file item is a [ServerFile](../../llama_index/server/models/chat.py#9) object, which includes the file id, type, size, and url of the uploaded file. The `url` is an access url to the uploaded file that can be used to download or display the file from the browser, the `id` is used to manage the file in the server through the [FileService](../../llama_index/server/services/file.py). + + +## Examples: + +### For agent workflow: + - We create a simple file reader tool that can read the uploaded file content. + + ```python + def create_file_tool(chat_request: ChatRequest) -> Optional[FunctionTool]: + """ + Create a tool to read file if the user uploads a file. + """ + file_ids = [] + # Get the uploaded file ids from the the chat messages + for file in get_file_attachments(chat_request.messages): + file_ids.append(file.id) + if len(file_ids) == 0: + return None + + # Create a tool description that includes the file ids so the LLM knows which file it can access + file_tool_description = ( + "Use this tool with a file id to read the content of the file." + f"\nYou only have access to the following file ids: {json.dumps(file_ids)}" + ) + + def read_file(file_id: str) -> str: + file_path = FileService.get_file_path(file_id) + try: + with open(file_path, "r") as file: + return file.read() + except Exception as e: + return f"Error reading file {file_path}: {e}" + + # Create the tool + return FunctionTool.from_defaults( + fn=read_file, + name="read_file", + description=file_tool_description, + ) + ``` + - Check out the [agent-workflow.py](agent-workflow.py) for more details. + + - You can run the agent workflow with file tool by running the following command: + ```bash + export OPENAI_API_KEY=your_openai_api_key_here + uv run agent-workflow.py + ``` + then go to the UI at `http://localhost:8000` and upload the [example.txt](example.txt) file. + +### For custom workflow: + - The attachments are included in the `attachments` parameter of the `StartEvent` so you can easily access them in the workflow. + + ```python + class MyWorkflow(Workflow): + @step + async def start_event_handler(self, ctx: Context, ev: StartEvent) -> StopEvent: + # Get attachments from the start event + attachments = ev.attachments + # Do something with the attachments + # e.g. read the file content + last_file = attachments[-1] + if last_file: + with open(last_file.path, "r") as f: + file_content = f.read() + ... + # or save it to the context for later use + await ctx.set("file_content", file_content) + return StopEvent() + ``` + - Check out the [custom-workflow.py](custom-workflow.py) for more details. + + - You can run the custom workflow by running the following command: + ```bash + export OPENAI_API_KEY=your_openai_api_key_here + uv run custom-workflow.py + ``` + then go to the UI at `http://localhost:8000` and upload the [example.txt](example.txt) file. \ No newline at end of file diff --git a/python/llama-index-server/examples/private_file/agent-workflow.py b/python/llama-index-server/examples/private_file/agent-workflow.py new file mode 100644 index 000000000..00a60a18c --- /dev/null +++ b/python/llama-index-server/examples/private_file/agent-workflow.py @@ -0,0 +1,78 @@ +import json +from typing import List, Optional + +from fastapi import FastAPI + +from llama_index.core.agent.workflow import AgentWorkflow +from llama_index.core.tools import FunctionTool +from llama_index.llms.openai import OpenAI +from llama_index.server import LlamaIndexServer, UIConfig +from llama_index.server.api.utils.chat_attachments import get_file_attachments +from llama_index.server.models.chat import ChatRequest +from llama_index.server.models.file import ServerFile +from llama_index.server.services.file import FileService + + +def create_file_tool(file_attachments: List[ServerFile]) -> Optional[FunctionTool]: + """ + Create a tool to read file if the user uploads a file. + """ + file_ids = [] + for file in file_attachments: + file_ids.append(file.id) + if len(file_ids) == 0: + return None + + file_tool_description = ( + "Use this tool with a file id to read the content of the file." + f"\nYou only have access to the following file ids: {json.dumps(file_ids)}" + ) + + def read_file(file_id: str) -> str: + # Validate if the file id is in the list of file ids + if file_id not in file_ids: + raise ValueError(f"I don't have access to file id {file_id}") + + file_path = FileService.get_file_path(file_id) + try: + with open(file_path, "r") as file: + return file.read() + except Exception as e: + return f"Error reading file {file_path}: {e}" + + return FunctionTool.from_defaults( + fn=read_file, + name="read_file", + description=file_tool_description, + ) + + +def create_workflow(chat_request: ChatRequest) -> AgentWorkflow: + file_attachments = get_file_attachments(chat_request.messages) + file_tool = create_file_tool(file_attachments) + return AgentWorkflow.from_tools_or_functions( + tools_or_functions=[file_tool] if file_tool else [], + llm=OpenAI(model="gpt-4.1-mini"), + system_prompt="You are a helpful assistant that can help users with their uploaded files.", + ) + + +def create_app() -> FastAPI: + app = LlamaIndexServer( + workflow_factory=create_workflow, + suggest_next_questions=False, + ui_config=UIConfig( + enable_file_upload=True, + component_dir="components", + ), + ) + return app + + +app = create_app() + + +if __name__ == "__main__": + import uvicorn + + uvicorn.run("agent-workflow:app", host="0.0.0.0", port=8000, reload=True) diff --git a/python/llama-index-server/examples/private_file/custom-workflow.py b/python/llama-index-server/examples/private_file/custom-workflow.py new file mode 100644 index 000000000..d472b1a46 --- /dev/null +++ b/python/llama-index-server/examples/private_file/custom-workflow.py @@ -0,0 +1,126 @@ +from typing import Any, List + +from fastapi import FastAPI + +from llama_index.core.agent.workflow.workflow_events import AgentStream +from llama_index.core.llms import LLM +from llama_index.core.prompts import PromptTemplate +from llama_index.core.workflow import ( + Context, + Event, + StartEvent, + StopEvent, + Workflow, + WorkflowRuntimeError, + step, +) +from llama_index.llms.openai import OpenAI +from llama_index.server import LlamaIndexServer, UIConfig +from llama_index.server.api.utils.chat_attachments import get_file_attachments +from llama_index.server.models.chat import ChatRequest +from llama_index.server.models.file import ServerFile + + +class FileHelpEvent(Event): + """ + The event for helping the user with the an uploaded file. + """ + + file_content: str + user_request: str + + +class FileHelpWorkflow(Workflow): + """ + A simple workflow that helps the user with the an uploaded file. + Note: The workflow just simply feed all the file content to the LLM so it won't work for large files. + The purpose is just for demo how a workflow can work with the uploaded file from the user. + """ + + def __init__( + self, + llm: LLM, + file_attachments: List[ServerFile], + **kwargs: Any, + ): + super().__init__(**kwargs) + self.llm = llm + self.file_attachments = file_attachments + + @step + async def read_files(self, ctx: Context, ev: StartEvent) -> FileHelpEvent: + user_msg = ev.user_msg + if len(self.file_attachments) == 0: + raise WorkflowRuntimeError("Please upload one file to start") + + # Read the file content + last_file = self.file_attachments[-1] + with open(last_file.path, "r") as f: + file_content = f.read() + + return FileHelpEvent( + file_content=file_content, + user_request=user_msg, + ) + + @step + async def help_user(self, ctx: Context, ev: FileHelpEvent) -> StopEvent: + default_prompt = PromptTemplate(""" + You are a writing assistant. + You are given a file content and a user request. + Your task is to help the user with the file content. + + User request: {user_msg} + + File content: + {file_content} + """) + prompt = default_prompt.format( + user_msg=ev.user_request, + file_content=ev.file_content, + ) + stream = await self.llm.astream_complete(prompt) + async for chunk in stream: + ctx.write_event_to_stream( + AgentStream( + response=chunk.text, + delta=chunk.delta or "", + current_agent_name="agent", + tool_calls=[], + raw=chunk.raw, + ) + ) + + return StopEvent( + content=True, + ) + + +def create_workflow(chat_request: ChatRequest) -> Workflow: + # Use get_file_attachments to get the file attachments from the chat messages + file_attachments = get_file_attachments(chat_request.messages) + return FileHelpWorkflow( + llm=OpenAI(model="gpt-4.1-mini"), + file_attachments=file_attachments, + ) + + +def create_app() -> FastAPI: + app = LlamaIndexServer( + workflow_factory=create_workflow, + suggest_next_questions=False, + ui_config=UIConfig( + enable_file_upload=True, + component_dir="components", + ), + ) + return app + + +app = create_app() + + +if __name__ == "__main__": + import uvicorn + + uvicorn.run("custom-workflow:app", host="0.0.0.0", port=8000, reload=True) diff --git a/python/llama-index-server/examples/private_file/example.txt b/python/llama-index-server/examples/private_file/example.txt new file mode 100644 index 000000000..0e5dac6fa --- /dev/null +++ b/python/llama-index-server/examples/private_file/example.txt @@ -0,0 +1,142 @@ +# ACME Vendor Agreement + +**Effective Date:** January 1, 2024 + +## Parties: + +- **Client:** LlamaCo ("Client") +- **Vendor:** ACME Office Supply, Inc. ("Vendor") + +## 1. Overview + +This Vendor Agreement ("Agreement") sets forth the terms and conditions under which ACME Office Supply, Inc. will provide office supplies, consumables, related goods ("Products"), and associated data processing services to LlamaCo. + +## 2. Definitions + +- **Personal Data:** Any information relating to an identified or identifiable natural person ('data subject'). +- **Processing:** Any operation performed on Personal Data, including collection, storage, modification, transfer, or deletion. +- **Data Controller:** LlamaCo, who determines the purposes and means of processing Personal Data. +- **Data Processor:** ACME Office Supply, Inc., who processes Personal Data on behalf of the Controller. + +## 3. Data Protection and Privacy + +### 3.1 Scope of Processing + +Vendor shall process Personal Data only: + +- To fulfill orders and manage deliveries +- To provide customer support services +- To maintain business records +- To comply with legal obligations + +### 3.2 Data Subject Rights + +Vendor shall: + +- Respond to data subject requests within 30 days +- Provide data in a structured, commonly used format +- Implement measures to facilitate data portability +- Assist with data subject rights requests at no additional cost + +### 3.3 Data Transfers and Storage + +- Vendor maintains primary data centers in the United States +- Vendor may transfer data to any country where it maintains operations +- No prior notification required for new data storage locations +- Vendor will rely on its standard data transfer mechanisms +- Data may be processed by staff operating outside the EEA + +### 3.4 Subprocessors + +- Vendor may engage subprocessors without prior Client approval +- Subprocessors may be located in any jurisdiction globally +- Notice of new subprocessors provided within 30 days of engagement +- Client has no right to object to new subprocessors + +## 4. Security Measures + +### 4.1 Technical and Organizational Measures + +Vendor shall implement appropriate measures including: + +- Encryption of Personal Data in transit and at rest +- Access controls and authentication +- Regular security testing and assessments +- Employee training on data protection +- Incident response procedures + +### 4.2 Data Breaches + +Vendor shall: + +- Notify Client of any Personal Data breach within 72 hours +- Provide details necessary to meet regulatory requirements +- Cooperate with Client's breach investigation +- Maintain records of all data breaches + +## 5. Data Retention + +### 5.1 Retention Period + +- Personal Data retained only as long as necessary +- Standard retention period of 3 years after last transaction +- Deletion of Personal Data upon written request +- Backup copies retained for maximum of 6 months + +### 5.2 Termination + +Upon termination of services: + +- Return all Personal Data in standard format +- Delete existing copies within 30 days +- Provide written confirmation of deletion +- Cease all processing activities + +## 6. Compliance and Audit + +### 6.1 Documentation + +Vendor shall maintain: + +- Records of all processing activities +- Security measure documentation +- Data transfer mechanisms +- Subprocessor agreements + +### 6.2 Audits + +- Annual compliance audits permitted +- 30 days notice required for audits +- Vendor to provide necessary documentation +- Client bears reasonable audit costs + +## 7. Liability and Indemnification + +### 7.1 Liability + +- Vendor liable for data protection violations +- Reasonable compensation for damages +- Coverage for regulatory fines where applicable +- Joint liability as required by law + +## 8. Governing Law + +This Agreement shall be governed by the laws of Ireland, without regard to its conflict of laws principles. + +--- + +IN WITNESS WHEREOF, the parties have executed this Agreement as of the Effective Date. + +**LlamaCo** + +By: **_ +Name: [Authorized Representative] +Title: [Title] +Date: _** + +**ACME Office Supply, Inc.** + +By: **_ +Name: [Authorized Representative] +Title: [Title] +Date: _** diff --git a/python/llama-index-server/examples/simple-agent/app/workflow.py b/python/llama-index-server/examples/simple-agent/app/workflow.py index fe949ea40..6e8827528 100644 --- a/python/llama-index-server/examples/simple-agent/app/workflow.py +++ b/python/llama-index-server/examples/simple-agent/app/workflow.py @@ -1,7 +1,6 @@ from typing import Optional from llama_index.core.agent.workflow import AgentWorkflow -from llama_index.core.settings import Settings from llama_index.llms.openai import OpenAI from llama_index.server.models import ChatRequest @@ -9,6 +8,6 @@ def create_workflow(chat_request: Optional[ChatRequest] = None) -> AgentWorkflow: return AgentWorkflow.from_tools_or_functions( tools_or_functions=[], - llm=Settings.llm or OpenAI(model="gpt-4o-mini"), + llm=OpenAI(model="gpt-4o-mini"), system_prompt="You are a helpful assistant that can tell a joke about Llama.", ) diff --git a/python/llama-index-server/llama_index/server/api/routers/chat.py b/python/llama-index-server/llama_index/server/api/routers/chat.py index 8ccf207bd..7e417fb92 100644 --- a/python/llama-index-server/llama_index/server/api/routers/chat.py +++ b/python/llama-index-server/llama_index/server/api/routers/chat.py @@ -6,6 +6,7 @@ from fastapi import APIRouter, BackgroundTasks, HTTPException from fastapi.responses import StreamingResponse + from llama_index.core.agent.workflow.workflow_events import ( AgentInput, AgentSetup, @@ -25,8 +26,14 @@ ) from llama_index.server.api.callbacks.stream_handler import StreamHandler from llama_index.server.api.utils.vercel_stream import VercelStreamResponse -from llama_index.server.models.chat import ChatRequest +from llama_index.server.models.chat import ( + ChatRequest, + FileUpload, + MessageRole, +) +from llama_index.server.models.file import ServerFileResponse from llama_index.server.models.hitl import HumanInputEvent +from llama_index.server.services.file import FileService from llama_index.server.services.llamacloud import LlamaCloudFileService from llama_index.server.services.workflow import HITLWorkflowService @@ -45,7 +52,8 @@ async def chat( ) -> StreamingResponse: try: last_message = request.messages[-1] - user_message = last_message.to_llamaindex_message() + if last_message.role != MessageRole.USER: + raise ValueError("Last message must be from user") chat_history = [ message.to_llamaindex_message() for message in request.messages[:-1] ] @@ -67,7 +75,7 @@ async def chat( workflow_handler = workflow.run(ctx=ctx) else: workflow_handler = workflow.run( - user_msg=user_message.content, + user_msg=last_message.content, chat_history=chat_history, ) @@ -95,6 +103,21 @@ async def chat( logger.error(e) raise HTTPException(status_code=500, detail=str(e)) + # we just simply save the file to the server and don't index it + @router.post("/file") + async def upload_file(request: FileUpload) -> ServerFileResponse: + """ + Upload a file to the server to be used in the chat session. + """ + try: + save_dir = os.path.join("output", "private") + content, _ = FileService._preprocess_base64_file(request.base64) + file = FileService.save_file(content, request.name, save_dir) + return file.to_server_file_response() + except Exception: + raise HTTPException(status_code=500, detail="Error uploading file") + + # Specific to LlamaCloud if LlamaCloudFileService.is_configured(): @router.get("/config/llamacloud") diff --git a/python/llama-index-server/llama_index/server/api/utils/chat_attachments.py b/python/llama-index-server/llama_index/server/api/utils/chat_attachments.py new file mode 100644 index 000000000..f28941e26 --- /dev/null +++ b/python/llama-index-server/llama_index/server/api/utils/chat_attachments.py @@ -0,0 +1,40 @@ +from typing import List + +from llama_index.core.types import MessageRole +from llama_index.server.models.chat import ChatAPIMessage, FileAnnotation +from llama_index.server.models.file import ServerFile +from llama_index.server.services.file import FileService + + +def get_file_attachments(messages: List[ChatAPIMessage]) -> List[ServerFile]: + """ + Extract all file attachments from user messages. + + Args: + messages (List[ChatAPIMessage]): The list of messages. + + Returns: + List[ServerFile]: The list of private files. + """ + user_message_annotations = [ + message.annotations + for message in messages + if message.annotations and message.role == MessageRole.USER + ] + files: List[ServerFile] = [] + for annotation in user_message_annotations: + if isinstance(annotation, list): + for item in annotation: + if isinstance(item, FileAnnotation): + server_files = [ + ServerFile( + id=file.id, + type=file.type, + size=file.size, + url=file.url, + path=FileService.get_file_path(file.id), + ) + for file in item.data.files + ] + files.extend(server_files) + return files diff --git a/python/llama-index-server/llama_index/server/models/chat.py b/python/llama-index-server/llama_index/server/models/chat.py index 442b49160..d5d311f52 100644 --- a/python/llama-index-server/llama_index/server/models/chat.py +++ b/python/llama-index-server/llama_index/server/models/chat.py @@ -1,17 +1,72 @@ import re -from typing import Any, List, Optional +from typing import Any, List, Literal, Optional, Union -from pydantic import BaseModel, field_validator +from pydantic import BaseModel, Field, field_validator from llama_index.core.types import ChatMessage, MessageRole +from llama_index.server.models.file import ServerFileResponse + + +class FileData(BaseModel): + """ + The data of a file. + """ + + files: List[ServerFileResponse] + + +class FileAnnotation(BaseModel): + """ + The annotation of a file. + """ + + type: Literal["document_file"] + data: FileData + + +class FileUpload(BaseModel): + """ + The file to be uploaded to the chat. + """ + + name: str + base64: str + params: Any = None + + +class LlamaCloudPipeline(BaseModel): + """ + The selected LlamaCloud pipeline to use for the chat. + (Only available when the app is configured to use LlamaCloud) + """ + + pipeline: str + project: str + + +class ChatData(BaseModel): + """ + The data of a chat. + """ + + llama_cloud_pipeline: Optional[LlamaCloudPipeline] = Field( + default=None, + description="The selected LlamaCloud pipeline to use for the chat", + alias="llamaCloudPipeline", + serialization_alias="llamaCloudPipeline", + ) class ChatAPIMessage(BaseModel): role: MessageRole content: str - annotations: Optional[List[Any]] = None + annotations: Optional[List[Union[FileAnnotation, Any]]] = None def to_llamaindex_message(self) -> ChatMessage: + """ + Simply convert text content of API message to llama_index's ChatMessage. + Annotations are not included. + """ return ChatMessage(role=self.role, content=self.content) @property @@ -27,9 +82,16 @@ def human_response(self) -> Optional[Any]: class ChatRequest(BaseModel): + """ + The request to the chat API. + """ + id: str # see https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat#id - constant for the same chat session messages: List[ChatAPIMessage] - data: Optional[Any] = None + data: Optional[ChatData] = Field( + default=None, + description="The data of the chat", + ) @field_validator("messages") def validate_messages(cls, v: List[ChatAPIMessage]) -> List[ChatAPIMessage]: diff --git a/python/llama-index-server/llama_index/server/models/file.py b/python/llama-index-server/llama_index/server/models/file.py new file mode 100644 index 000000000..74372a70a --- /dev/null +++ b/python/llama-index-server/llama_index/server/models/file.py @@ -0,0 +1,26 @@ +from typing import Optional + +from pydantic import BaseModel, Field + + +class ServerFileResponse(BaseModel): + id: str + type: Optional[str] = None + size: Optional[int] = None + url: Optional[str] = None + + +class ServerFile(BaseModel): + id: str + path: str = Field(description="The path of the file in the server") + type: Optional[str] = None + size: Optional[int] = None + url: Optional[str] = None + + def to_server_file_response(self) -> ServerFileResponse: + return ServerFileResponse( + id=self.id, + type=self.type, + size=self.size, + url=self.url, + ) diff --git a/python/llama-index-server/llama_index/server/server.py b/python/llama-index-server/llama_index/server/server.py index 8a4351ad2..3d497e77c 100644 --- a/python/llama-index-server/llama_index/server/server.py +++ b/python/llama-index-server/llama_index/server/server.py @@ -7,8 +7,6 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.routing import Mount from fastapi.staticfiles import StaticFiles -from pydantic import BaseModel, Field - from llama_index.core.workflow import Workflow from llama_index.server.api.routers import ( chat_router, @@ -18,6 +16,7 @@ ) from llama_index.server.chat_ui import copy_bundled_chat_ui from llama_index.server.settings import server_settings +from pydantic import BaseModel, Field class UIConfig(BaseModel): @@ -29,6 +28,10 @@ class UIConfig(BaseModel): default=False, description="Whether to show the LlamaCloud index selector in the chat UI (need to set the LLAMA_CLOUD_API_KEY environment variable)", ) + enable_file_upload: bool = Field( + default=False, + description="Whether to enable file upload in the chat UI", + ) ui_path: str = Field( default=".ui", description="The path that stores static files for the chat UI" ) @@ -47,6 +50,11 @@ def get_config_content(self) -> str: return json.dumps( { "CHAT_API": f"{server_settings.api_url}/chat", + "UPLOAD_API": ( + f"{server_settings.api_url}/chat/file" + if self.enable_file_upload + else None + ), "STARTER_QUESTIONS": self.starter_questions or [], "LLAMA_CLOUD_API": ( f"{server_settings.api_url}/chat/config/llamacloud" diff --git a/python/llama-index-server/llama_index/server/services/file.py b/python/llama-index-server/llama_index/server/services/file.py index d715d86c8..00e66f29e 100644 --- a/python/llama-index-server/llama_index/server/services/file.py +++ b/python/llama-index-server/llama_index/server/services/file.py @@ -1,39 +1,23 @@ +import base64 import logging +import mimetypes import os import re import uuid from pathlib import Path -from typing import List, Optional, Union +from typing import Optional, Tuple, Union +from llama_index.server.models.file import ServerFile from llama_index.server.settings import server_settings -from pydantic import BaseModel, Field logger = logging.getLogger(__name__) -PRIVATE_STORE_PATH = str(Path("output", "uploaded")) -TOOL_STORE_PATH = str(Path("output", "tools")) -LLAMA_CLOUD_STORE_PATH = str(Path("output", "llamacloud")) - - -class DocumentFile(BaseModel): - id: str - name: str # Stored file name - type: Optional[str] = None - size: Optional[int] = None - url: Optional[str] = None - path: Optional[str] = Field( - None, - description="The stored file path. Used internally in the server.", - exclude=True, - ) - refs: Optional[List[str]] = Field( - None, description="The document ids in the index." - ) +PRIVATE_STORE_PATH = str(Path("output", "private")) class FileService: """ - To store the files uploaded by the user. + Store files to server """ @classmethod @@ -42,38 +26,31 @@ def save_file( content: Union[bytes, str], file_name: str, save_dir: Optional[str] = None, - ) -> DocumentFile: + ) -> ServerFile: """ Save the content to a file in the local file server (accessible via URL). Args: content (bytes | str): The content to save, either bytes or string. file_name (str): The original name of the file. - save_dir (Optional[str]): The relative path from the current working directory. Defaults to the `output/uploaded` directory. - + save_dir (Optional[str]): The path to store the file. Defaults is set to PRIVATE_STORE_PATH (output/private) if not provided. Returns: The metadata of the saved file. """ if save_dir is None: - save_dir = os.path.join("output", "uploaded") + save_dir = PRIVATE_STORE_PATH - file_id = str(uuid.uuid4()) - name, extension = os.path.splitext(file_name) - extension = extension.lstrip(".") - sanitized_name = _sanitize_file_name(name) - if extension == "": - raise ValueError("File is not supported!") - new_file_name = f"{sanitized_name}_{file_id}.{extension}" - - file_path = os.path.join(save_dir, new_file_name) - - if isinstance(content, str): - content = content.encode() + file_id, extension = cls._process_file_name(file_name) + file_path = os.path.join(save_dir, file_id) + # Write the file directly, handling both str and bytes try: os.makedirs(os.path.dirname(file_path), exist_ok=True) - with open(file_path, "wb") as file: - file.write(content) + with open(file_path, "wb") as f: + if isinstance(content, str): + f.write(content.encode()) + else: + f.write(content) except PermissionError as e: logger.error(f"Permission denied when writing to file {file_path}: {e!s}") raise @@ -87,31 +64,90 @@ def save_file( logger.info(f"Saved file to {file_path}") file_size = os.path.getsize(file_path) - file_url = ( - f"{server_settings.file_server_url_prefix}/{save_dir}/{new_file_name}" - ) - return DocumentFile( + file_url = cls._get_file_url(file_id, save_dir) + return ServerFile( id=file_id, - name=new_file_name, type=extension, size=file_size, - path=file_path, url=file_url, - refs=None, + path=file_path, ) @classmethod - def get_file_url(cls, file_name: str, save_dir: Optional[str] = None) -> str: + def _process_file_name(cls, file_name: str) -> tuple[str, str]: + """ + Process original file name to generate a unique file id and extension. + """ + _id = str(uuid.uuid4()) + name, extension = os.path.splitext(file_name) + extension = extension.lstrip(".") + if extension == "": + raise ValueError("File name is not valid! It must have an extension.") + # sanitize the name + name = re.sub(r"[^a-zA-Z0-9.]", "_", name) + file_id = f"{name}_{_id}.{extension}" + return file_id, extension + + @classmethod + def _get_file_url(cls, file_id: str, save_dir: Optional[str] = None) -> str: """ Get the URL of a file. """ if save_dir is None: - save_dir = os.path.join("output", "uploaded") - return f"{server_settings.file_server_url_prefix}/{save_dir}/{file_name}" + save_dir = PRIVATE_STORE_PATH + # Ensure the path uses forward slashes for URLs + url_path = f"{save_dir}/{file_id}".replace("\\", "/") + return f"{server_settings.file_server_url_prefix}/{url_path}" + @classmethod + def get_file_path(cls, file_id: str, save_dir: Optional[str] = None) -> str: + """ + Get the path of a private file. -def _sanitize_file_name(file_name: str) -> str: - """ - Sanitize the file name by replacing all non-alphanumeric characters with underscores. - """ - return re.sub(r"[^a-zA-Z0-9.]", "_", file_name) + Args: + file_id (str): The ID of the file. + save_dir (Optional[str]): The path where the file is stored. Defaults to output/private if not provided. + + Returns: + str: The full path to the file. + """ + if save_dir is None: + save_dir = PRIVATE_STORE_PATH + return os.path.join(save_dir, file_id) + + @classmethod + def get_file(cls, file_id: str, save_dir: Optional[str] = None) -> bytes: + """ + Read and return the content of a file. + + Args: + file_id (str): The ID of the file. + save_dir (Optional[str]): The path where the file is stored. Defaults to output/private if not provided. + + Returns: + bytes: The content of the file. + + Raises: + FileNotFoundError: If the file does not exist. + """ + file_path = cls.get_file_path(file_id, save_dir) + + try: + with open(file_path, "rb") as f: + return f.read() + except FileNotFoundError as e: + logger.error(f"File not found: {file_path}") + raise FileNotFoundError(f"File with ID '{file_id}' not found") from e + except Exception as e: + logger.error(f"Unexpected error when reading file {file_path}: {e!s}") + raise + + @staticmethod + def _preprocess_base64_file(base64_content: str) -> Tuple[bytes, str]: + header, data = base64_content.split(",", 1) + mime_type = header.split(";")[0].split(":", 1)[1] + extension = mimetypes.guess_extension(mime_type) + if extension is None: + raise ValueError(f"Unsupported file type: {mime_type}") + extension = extension.lstrip(".") + return base64.b64decode(data), extension diff --git a/python/llama-index-server/llama_index/server/services/llamacloud/index.py b/python/llama-index-server/llama_index/server/services/llamacloud/index.py index d21c7cd4b..fc81ca65a 100644 --- a/python/llama-index-server/llama_index/server/services/llamacloud/index.py +++ b/python/llama-index-server/llama_index/server/services/llamacloud/index.py @@ -92,14 +92,14 @@ def to_index_kwargs(self) -> dict: def from_default(cls, chat_request: Optional[ChatRequest] = None) -> "IndexConfig": default_config = cls() if chat_request is not None and chat_request.data is not None: - llamacloud_config = chat_request.data.get("llamaCloudPipeline") + llamacloud_config = chat_request.data.llama_cloud_pipeline if llamacloud_config is not None: - default_config.llama_cloud_pipeline_config.pipeline = llamacloud_config[ - "pipeline" - ] - default_config.llama_cloud_pipeline_config.project = llamacloud_config[ - "project" - ] + default_config.llama_cloud_pipeline_config.pipeline = ( + llamacloud_config.pipeline + ) + default_config.llama_cloud_pipeline_config.project = ( + llamacloud_config.project + ) return default_config diff --git a/python/llama-index-server/llama_index/server/tools/interpreter.py b/python/llama-index-server/llama_index/server/tools/interpreter.py index be0c349e7..a239bbd28 100644 --- a/python/llama-index-server/llama_index/server/tools/interpreter.py +++ b/python/llama-index-server/llama_index/server/tools/interpreter.py @@ -4,10 +4,12 @@ import uuid from typing import Any, List, Optional -from llama_index.core.tools import FunctionTool -from llama_index.server.services.file import DocumentFile, FileService from pydantic import BaseModel +from llama_index.core.tools import FunctionTool +from llama_index.server.models.file import ServerFile +from llama_index.server.services.file import FileService + logger = logging.getLogger("uvicorn") @@ -87,7 +89,7 @@ def _init_interpreter(self, sandbox_files: List[str] = []) -> None: self.interpreter.files.write(file_path, content) logger.info(f"Uploaded {len(sandbox_files)} files to sandbox") - def _save_to_disk(self, base64_data: str, ext: str) -> DocumentFile: + def _save_to_disk(self, base64_data: str, ext: str) -> ServerFile: buffer = base64.b64decode(base64_data) # Output from e2b doesn't have a name. Create a random name for it. @@ -117,7 +119,7 @@ def _parse_result(self, result: Any) -> List[InterpreterExtraResult]: output.append( InterpreterExtraResult( type=ext, - filename=document_file.name, + filename=document_file.id, url=document_file.url, ) ) diff --git a/python/llama-index-server/tests/api/test_chat_api.py b/python/llama-index-server/tests/api/test_chat_api.py index 4cd250beb..8e01a4faf 100644 --- a/python/llama-index-server/tests/api/test_chat_api.py +++ b/python/llama-index-server/tests/api/test_chat_api.py @@ -90,7 +90,6 @@ async def test_chat_router( # Verify the workflow was called with the correct arguments call_args = mock_workflow.run.call_args[1] - assert call_args["user_msg"] == "Hello, how are you?" assert isinstance(call_args["chat_history"], list) assert len(call_args["chat_history"]) == 0 # No history for first message @@ -153,6 +152,5 @@ def workflow_factory(verbose: bool = False) -> MagicMock: # Verify the workflow was called with the correct arguments call_args = mock_workflow.run.call_args[1] - assert call_args["user_msg"] == "What's the weather in New York?" assert isinstance(call_args["chat_history"], list) assert len(call_args["chat_history"]) == 0 # No history for first message diff --git a/python/llama-index-server/tests/services/test_file_service.py b/python/llama-index-server/tests/services/test_file_service.py index 79b096fdb..55d2f21d4 100644 --- a/python/llama-index-server/tests/services/test_file_service.py +++ b/python/llama-index-server/tests/services/test_file_service.py @@ -1,35 +1,24 @@ import os import uuid -from unittest.mock import mock_open, patch +from unittest.mock import MagicMock, mock_open, patch import pytest -from llama_index.server.services.file import FileService, _sanitize_file_name +from llama_index.server.services.file import FileService -class TestFileService: - def test_sanitize_file_name(self): - # Test with normal alphanumeric name - assert _sanitize_file_name("test123") == "test123" - - # Test with spaces - assert _sanitize_file_name("test file") == "test_file" - - # Test with special characters - assert _sanitize_file_name("test@file!name") == "test_file_name" - - # Test with path-like characters - assert _sanitize_file_name("test/file/name") == "test_file_name" - - # Test with dots (should be preserved) - assert _sanitize_file_name("test.file.name") == "test.file.name" +class TestFileService: @patch("uuid.uuid4") @patch("os.path.getsize") @patch("builtins.open", new_callable=mock_open) @patch("os.makedirs") def test_save_file_string_content( - self, mock_makedirs, mock_file_open, mock_getsize, mock_uuid - ): + self, + mock_makedirs: MagicMock, + mock_file_open: MagicMock, + mock_getsize: MagicMock, + mock_uuid: MagicMock, + ) -> None: # Setup test_uuid = "12345678-1234-5678-1234-567812345678" mock_uuid.return_value = uuid.UUID(test_uuid) @@ -48,21 +37,23 @@ def test_save_file_string_content( mock_file_open.assert_called_once_with(expected_path, "wb") mock_file_open().write.assert_called_once_with(b"Hello World") - assert result.id == test_uuid - assert result.name == f"test_{test_uuid}.txt" + assert result.id == f"test_{test_uuid}.txt" assert result.type == "txt" assert result.size == 11 assert result.path == expected_path assert result.url.endswith(expected_path.replace(os.path.sep, "/")) - assert result.refs is None @patch("uuid.uuid4") @patch("os.path.getsize") @patch("builtins.open", new_callable=mock_open) @patch("os.makedirs") def test_save_file_bytes_content( - self, mock_makedirs, mock_file_open, mock_getsize, mock_uuid - ): + self, + mock_makedirs: MagicMock, + mock_file_open: MagicMock, + mock_getsize: MagicMock, + mock_uuid: MagicMock, + ) -> None: # Setup test_uuid = "12345678-1234-5678-1234-567812345678" mock_uuid.return_value = uuid.UUID(test_uuid) @@ -81,6 +72,7 @@ def test_save_file_bytes_content( mock_file_open.assert_called_once_with(expected_path, "wb") mock_file_open().write.assert_called_once_with(b"Hello World") assert result.path == expected_path + assert result.url.endswith(expected_path.replace(os.path.sep, "/")) assert result.type == "txt" @patch("uuid.uuid4") @@ -88,8 +80,12 @@ def test_save_file_bytes_content( @patch("builtins.open", new_callable=mock_open) @patch("os.makedirs") def test_save_file_with_special_characters( - self, mock_makedirs, mock_file_open, mock_getsize, mock_uuid - ): + self, + mock_makedirs: MagicMock, + mock_file_open: MagicMock, + mock_getsize: MagicMock, + mock_uuid: MagicMock, + ) -> None: # Setup test_uuid = "12345678-1234-5678-1234-567812345678" mock_uuid.return_value = uuid.UUID(test_uuid) @@ -107,15 +103,19 @@ def test_save_file_with_special_characters( ) mock_file_open.assert_called_once_with(expected_path, "wb") assert result.path == expected_path - assert result.name == f"test_file__{test_uuid}.txt" + assert result.url.endswith(expected_path.replace(os.path.sep, "/")) @patch("uuid.uuid4") @patch("os.path.getsize") @patch("builtins.open", new_callable=mock_open) @patch("os.makedirs") def test_save_file_default_directory( - self, mock_makedirs, mock_file_open, mock_getsize, mock_uuid - ): + self, + mock_makedirs: MagicMock, + mock_file_open: MagicMock, + mock_getsize: MagicMock, + mock_uuid: MagicMock, + ) -> None: # Setup test_uuid = "12345678-1234-5678-1234-567812345678" mock_uuid.return_value = uuid.UUID(test_uuid) @@ -125,11 +125,12 @@ def test_save_file_default_directory( result = FileService.save_file(content="Hello World", file_name="test.txt") # Assert - expected_path = os.path.join("output", "uploaded", f"test_{test_uuid}.txt") + expected_path = os.path.join("output", "private", f"test_{test_uuid}.txt") mock_makedirs.assert_called_once_with( os.path.dirname(expected_path), exist_ok=True ) assert result.path == expected_path + assert result.url.endswith(expected_path.replace(os.path.sep, "/")) @patch("uuid.uuid4") @patch("os.getenv") @@ -137,8 +138,13 @@ def test_save_file_default_directory( @patch("builtins.open", new_callable=mock_open) @patch("os.makedirs") def test_save_file_custom_url_prefix( - self, mock_makedirs, mock_file_open, mock_getsize, mock_getenv, mock_uuid - ): + self, + mock_makedirs: MagicMock, + mock_file_open: MagicMock, + mock_getsize: MagicMock, + mock_getenv: MagicMock, + mock_uuid: MagicMock, + ) -> None: # Setup test_uuid = "12345678-1234-5678-1234-567812345678" mock_uuid.return_value = uuid.UUID(test_uuid) @@ -157,13 +163,11 @@ def test_save_file_custom_url_prefix( ) mock_file_open.assert_called_once_with(expected_path, "wb") assert result.path == expected_path - # URL paths must use forward slashes, even on Windows - expected_url = f"/api/files/test_dir/test_{test_uuid}.txt" - assert result.url == expected_url + assert result.url.endswith(expected_path.replace(os.path.sep, "/")) - def test_save_file_no_extension(self): + def test_save_file_no_extension(self) -> None: # Test that saving a file without extension raises ValueError - with pytest.raises(ValueError, match="File is not supported!"): + with pytest.raises(ValueError, match="File name is not valid!"): FileService.save_file( content="Hello World", file_name="test", save_dir="test_dir" ) @@ -173,8 +177,12 @@ def test_save_file_no_extension(self): @patch("builtins.open") @patch("os.makedirs") def test_save_file_permission_error( - self, mock_makedirs, mock_file_open, mock_getsize, mock_uuid - ): + self, + mock_makedirs: MagicMock, + mock_file_open: MagicMock, + mock_getsize: MagicMock, + mock_uuid: MagicMock, + ) -> None: # Setup test_uuid = "12345678-1234-5678-1234-567812345678" mock_uuid.return_value = uuid.UUID(test_uuid) @@ -191,8 +199,12 @@ def test_save_file_permission_error( @patch("builtins.open") @patch("os.makedirs") def test_save_file_io_error( - self, mock_makedirs, mock_file_open, mock_getsize, mock_uuid - ): + self, + mock_makedirs: MagicMock, + mock_file_open: MagicMock, + mock_getsize: MagicMock, + mock_uuid: MagicMock, + ) -> None: # Setup test_uuid = "12345678-1234-5678-1234-567812345678" mock_uuid.return_value = uuid.UUID(test_uuid)