mirror of
https://github.com/run-llama/create-llama.git
synced 2026-07-19 23:13:36 -04:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c1de3c3ee | |||
| a3dd3c1f0d | |||
| 4dca89ddb4 | |||
| e20f198707 | |||
| eff763191e | |||
| 27de9418ff | |||
| 31cc131eb2 | |||
| cded3ae414 | |||
| 980f212d54 | |||
| 3ac65caa2e | |||
| d8668bfaaf | |||
| 37d52368de | |||
| 1c598071dc | |||
| 1f0f01a15d | |||
| 41898dcf10 | |||
| 844c2974ca | |||
| 2165247dab | |||
| bdd624242f | |||
| 75409c9106 | |||
| f59b46df62 | |||
| 0d7a32f421 | |||
| dc73a34f61 | |||
| 472dbc4c21 | |||
| e3187fac1a | |||
| b493548a13 | |||
| 4be5c0e1ca | |||
| b9f61c77e9 | |||
| b2f804c8af | |||
| 03c7c4505d | |||
| e4ada3cad2 |
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"create-llama": patch
|
||||
"@llamaindex/server": patch
|
||||
"@create-llama/llama-index-server": patch
|
||||
---
|
||||
|
||||
feat: bump chat-ui with inline artifact
|
||||
+1
-14
@@ -1,4 +1,4 @@
|
||||
import { extractLastArtifact } from "@llamaindex/server";
|
||||
import { artifactEvent, extractLastArtifact } from "@llamaindex/server";
|
||||
import { ChatMemoryBuffer, MessageContent, Settings } from "llamaindex";
|
||||
|
||||
import {
|
||||
@@ -52,19 +52,6 @@ const synthesizeAnswerEvent = workflowEvent<object>();
|
||||
|
||||
const uiEvent = workflowEvent<UIEvent>();
|
||||
|
||||
const artifactEvent = workflowEvent<{
|
||||
type: "artifact";
|
||||
data: {
|
||||
type: "code";
|
||||
created_at: number;
|
||||
data: {
|
||||
language: string;
|
||||
file_name: string;
|
||||
code: string;
|
||||
};
|
||||
};
|
||||
}>();
|
||||
|
||||
export function workflowFactory(reqBody: any) {
|
||||
const llm = Settings.llm;
|
||||
|
||||
|
||||
+1
-14
@@ -1,4 +1,4 @@
|
||||
import { extractLastArtifact } from "@llamaindex/server";
|
||||
import { artifactEvent, extractLastArtifact } from "@llamaindex/server";
|
||||
import { ChatMemoryBuffer, MessageContent, Settings } from "llamaindex";
|
||||
|
||||
import {
|
||||
@@ -55,19 +55,6 @@ const synthesizeAnswerEvent = workflowEvent<{
|
||||
|
||||
const uiEvent = workflowEvent<UIEvent>();
|
||||
|
||||
const artifactEvent = workflowEvent<{
|
||||
type: "artifact";
|
||||
data: {
|
||||
type: "document";
|
||||
created_at: number;
|
||||
data: {
|
||||
title: string;
|
||||
content: string;
|
||||
type: "markdown" | "html";
|
||||
};
|
||||
};
|
||||
}>();
|
||||
|
||||
export function workflowFactory(reqBody: any) {
|
||||
const llm = Settings.llm;
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
This example demonstrates how to use the code generation workflow.
|
||||
|
||||
```ts
|
||||
new LlamaIndexServer({
|
||||
workflow: workflowFactory,
|
||||
uiConfig: {
|
||||
starterQuestions: [
|
||||
"Generate a calculator app",
|
||||
"Create a simple todo list app",
|
||||
],
|
||||
componentsDir: "components",
|
||||
},
|
||||
port: 3000,
|
||||
}).start();
|
||||
```
|
||||
|
||||
Export OpenAI API key and start the server in dev mode.
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=<your-openai-api-key>
|
||||
npx nodemon --exec tsx index.ts
|
||||
```
|
||||
@@ -0,0 +1,132 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Progress } from "@/components/ui/progress";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Markdown } from "@llamaindex/chat-ui/widgets";
|
||||
import { ListChecks, Loader2, Wand2 } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const STAGE_META = {
|
||||
plan: {
|
||||
icon: ListChecks,
|
||||
badgeText: "Step 1/2: Planning",
|
||||
gradient: "from-blue-100 via-blue-50 to-white",
|
||||
progress: 33,
|
||||
iconBg: "bg-blue-100 text-blue-600",
|
||||
badge: "bg-blue-100 text-blue-700",
|
||||
},
|
||||
generate: {
|
||||
icon: Wand2,
|
||||
badgeText: "Step 2/2: Generating",
|
||||
gradient: "from-violet-100 via-violet-50 to-white",
|
||||
progress: 66,
|
||||
iconBg: "bg-violet-100 text-violet-600",
|
||||
badge: "bg-violet-100 text-violet-700",
|
||||
},
|
||||
};
|
||||
|
||||
function ArtifactWorkflowCard({ event }) {
|
||||
const [visible, setVisible] = useState(event?.state !== "completed");
|
||||
const [fade, setFade] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (event?.state === "completed") {
|
||||
setVisible(false);
|
||||
} else {
|
||||
setVisible(true);
|
||||
setFade(false);
|
||||
}
|
||||
}, [event?.state]);
|
||||
|
||||
if (!event || !visible) return null;
|
||||
|
||||
const { state, requirement } = event;
|
||||
const meta = STAGE_META[state];
|
||||
|
||||
if (!meta) return null;
|
||||
|
||||
return (
|
||||
<div className="flex min-h-[180px] w-full items-center justify-center py-2">
|
||||
<Card
|
||||
className={cn(
|
||||
"w-full rounded-xl shadow-md transition-all duration-500",
|
||||
"border-0",
|
||||
fade && "pointer-events-none opacity-0",
|
||||
`bg-gradient-to-br ${meta.gradient}`,
|
||||
)}
|
||||
style={{
|
||||
boxShadow:
|
||||
"0 2px 12px 0 rgba(80, 80, 120, 0.08), 0 1px 3px 0 rgba(80, 80, 120, 0.04)",
|
||||
}}
|
||||
>
|
||||
<CardHeader className="flex flex-row items-center gap-2 px-3 pb-1 pt-2">
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-center rounded-full p-1",
|
||||
meta.iconBg,
|
||||
)}
|
||||
>
|
||||
<meta.icon className="h-5 w-5" />
|
||||
</div>
|
||||
<CardTitle className="flex items-center gap-2 text-base font-semibold">
|
||||
<Badge className={cn("ml-1", meta.badge, "px-2 py-0.5 text-xs")}>
|
||||
{meta.badgeText}
|
||||
</Badge>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="px-3 py-1">
|
||||
{state === "plan" && (
|
||||
<div className="flex flex-col items-center gap-2 py-2">
|
||||
<Loader2 className="mb-1 h-6 w-6 animate-spin text-blue-400" />
|
||||
<div className="text-center text-sm font-medium text-blue-900">
|
||||
Analyzing your request...
|
||||
</div>
|
||||
<Skeleton className="mt-1 h-3 w-1/2 rounded-full" />
|
||||
</div>
|
||||
)}
|
||||
{state === "generate" && (
|
||||
<div className="flex flex-col gap-2 py-2">
|
||||
<div className="flex items-center gap-1">
|
||||
<Loader2 className="h-4 w-4 animate-spin text-violet-400" />
|
||||
<span className="text-sm font-medium text-violet-900">
|
||||
Working on the requirement:
|
||||
</span>
|
||||
</div>
|
||||
<div className="max-h-24 overflow-auto rounded-lg border border-violet-200 bg-violet-50 px-2 py-1 text-xs">
|
||||
{requirement ? (
|
||||
<Markdown content={requirement} />
|
||||
) : (
|
||||
<span className="italic text-violet-400">
|
||||
No requirements available yet.
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
<div className="px-3 pb-2 pt-1">
|
||||
<Progress
|
||||
value={meta.progress}
|
||||
className={cn(
|
||||
"h-1 rounded-full bg-gray-200",
|
||||
state === "plan" && "bg-blue-200",
|
||||
state === "generate" && "bg-violet-200",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Component({ events }) {
|
||||
const aggregateEvents = () => {
|
||||
if (!events || events.length === 0) return null;
|
||||
return events[events.length - 1];
|
||||
};
|
||||
|
||||
const event = aggregateEvents();
|
||||
|
||||
return <ArtifactWorkflowCard event={event} />;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { OpenAI } from "@llamaindex/openai";
|
||||
import { LlamaIndexServer } from "@llamaindex/server";
|
||||
import { Settings } from "llamaindex";
|
||||
import { workflowFactory } from "./src/app/workflow";
|
||||
|
||||
Settings.llm = new OpenAI({
|
||||
model: "gpt-4o-mini",
|
||||
});
|
||||
|
||||
new LlamaIndexServer({
|
||||
workflow: workflowFactory,
|
||||
uiConfig: {
|
||||
starterQuestions: [
|
||||
"Generate a calculator app",
|
||||
"Create a simple todo list app",
|
||||
],
|
||||
componentsDir: "components",
|
||||
},
|
||||
port: 3000,
|
||||
}).start();
|
||||
@@ -0,0 +1,337 @@
|
||||
import { artifactEvent, extractLastArtifact } from "@llamaindex/server";
|
||||
import { ChatMemoryBuffer, MessageContent, Settings } from "llamaindex";
|
||||
|
||||
import {
|
||||
agentStreamEvent,
|
||||
createStatefulMiddleware,
|
||||
createWorkflow,
|
||||
startAgentEvent,
|
||||
stopAgentEvent,
|
||||
workflowEvent,
|
||||
} from "@llamaindex/workflow";
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
export const RequirementSchema = z.object({
|
||||
next_step: z.enum(["answering", "coding"]),
|
||||
language: z.string().nullable().optional(),
|
||||
file_name: z.string().nullable().optional(),
|
||||
requirement: z.string(),
|
||||
});
|
||||
|
||||
export type Requirement = z.infer<typeof RequirementSchema>;
|
||||
|
||||
export const UIEventSchema = z.object({
|
||||
type: z.literal("ui_event"),
|
||||
data: z.object({
|
||||
state: z
|
||||
.enum(["plan", "generate", "completed"])
|
||||
.describe(
|
||||
"The current state of the workflow: 'plan', 'generate', or 'completed'.",
|
||||
),
|
||||
requirement: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"An optional requirement creating or updating a code, if applicable.",
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
export type UIEvent = z.infer<typeof UIEventSchema>;
|
||||
const planEvent = workflowEvent<{
|
||||
userInput: MessageContent;
|
||||
context?: string | undefined;
|
||||
}>();
|
||||
|
||||
const generateArtifactEvent = workflowEvent<{
|
||||
requirement: Requirement;
|
||||
}>();
|
||||
|
||||
const synthesizeAnswerEvent = workflowEvent<object>();
|
||||
|
||||
const uiEvent = workflowEvent<UIEvent>();
|
||||
|
||||
export function workflowFactory(reqBody: unknown) {
|
||||
const llm = Settings.llm;
|
||||
|
||||
const { withState, getContext } = createStatefulMiddleware(() => {
|
||||
return {
|
||||
memory: new ChatMemoryBuffer({ llm }),
|
||||
lastArtifact: extractLastArtifact(reqBody),
|
||||
};
|
||||
});
|
||||
const workflow = withState(createWorkflow());
|
||||
|
||||
workflow.handle([startAgentEvent], async ({ data }) => {
|
||||
const { userInput, chatHistory = [] } = data;
|
||||
// Prepare chat history
|
||||
const { state } = getContext();
|
||||
// Put user input to the memory
|
||||
if (!userInput) {
|
||||
throw new Error("Missing user input to start the workflow");
|
||||
}
|
||||
state.memory.set(chatHistory);
|
||||
state.memory.put({ role: "user", content: userInput });
|
||||
|
||||
return planEvent.with({
|
||||
userInput: userInput,
|
||||
context: state.lastArtifact
|
||||
? JSON.stringify(state.lastArtifact)
|
||||
: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
workflow.handle([planEvent], async ({ data: planData }) => {
|
||||
const { sendEvent } = getContext();
|
||||
const { state } = getContext();
|
||||
sendEvent(
|
||||
uiEvent.with({
|
||||
type: "ui_event",
|
||||
data: {
|
||||
state: "plan",
|
||||
},
|
||||
}),
|
||||
);
|
||||
const user_msg = planData.userInput;
|
||||
const context = planData.context
|
||||
? `## The context is: \n${planData.context}\n`
|
||||
: "";
|
||||
const prompt = `
|
||||
You are a product analyst responsible for analyzing the user's request and providing the next step for code or document generation.
|
||||
You are helping user with their code artifact. To update the code, you need to plan a coding step.
|
||||
|
||||
Follow these instructions:
|
||||
1. Carefully analyze the conversation history and the user's request to determine what has been done and what the next step should be.
|
||||
2. The next step must be one of the following two options:
|
||||
- "coding": To make the changes to the current code.
|
||||
- "answering": If you don't need to update the current code or need clarification from the user.
|
||||
Important: Avoid telling the user to update the code themselves, you are the one who will update the code (by planning a coding step).
|
||||
3. If the next step is "coding", you may specify the language ("typescript" or "python") and file_name if known, otherwise set them to null.
|
||||
4. The requirement must be provided clearly what is the user request and what need to be done for the next step in details
|
||||
as precise and specific as possible, don't be stingy with in the requirement.
|
||||
5. If the next step is "answering", set language and file_name to null, and the requirement should describe what to answer or explain to the user.
|
||||
6. Be concise; only return the requirements for the next step.
|
||||
7. The requirements must be in the following format:
|
||||
\`\`\`json
|
||||
{
|
||||
"next_step": "answering" | "coding",
|
||||
"language": "typescript" | "python" | null,
|
||||
"file_name": string | null,
|
||||
"requirement": string
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Example 1:
|
||||
User request: Create a calculator app.
|
||||
You should return:
|
||||
\`\`\`json
|
||||
{
|
||||
"next_step": "coding",
|
||||
"language": "typescript",
|
||||
"file_name": "calculator.tsx",
|
||||
"requirement": "Generate code for a calculator app that has a simple UI with a display and button layout. The display should show the current input and the result. The buttons should include basic operators, numbers, clear, and equals. The calculation should work correctly."
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Example 2:
|
||||
User request: Explain how the game loop works.
|
||||
Context: You have already generated the code for a snake game.
|
||||
You should return:
|
||||
\`\`\`json
|
||||
{
|
||||
"next_step": "answering",
|
||||
"language": null,
|
||||
"file_name": null,
|
||||
"requirement": "The user is asking about the game loop. Explain how the game loop works."
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
${context}
|
||||
|
||||
Now, plan the user's next step for this request:
|
||||
${user_msg}
|
||||
`;
|
||||
|
||||
const response = await llm.complete({
|
||||
prompt,
|
||||
});
|
||||
// parse the response to Requirement
|
||||
// 1. use regex to find the json block
|
||||
const jsonBlock = response.text.match(/```json\s*([\s\S]*?)\s*```/);
|
||||
if (!jsonBlock) {
|
||||
throw new Error("No JSON block found in the response.");
|
||||
}
|
||||
const requirement = RequirementSchema.parse(JSON.parse(jsonBlock[1]));
|
||||
state.memory.put({
|
||||
role: "assistant",
|
||||
content: `The plan for next step: \n${response.text}`,
|
||||
});
|
||||
|
||||
if (requirement.next_step === "coding") {
|
||||
return generateArtifactEvent.with({
|
||||
requirement,
|
||||
});
|
||||
} else {
|
||||
return synthesizeAnswerEvent.with({});
|
||||
}
|
||||
});
|
||||
|
||||
workflow.handle([generateArtifactEvent], async ({ data: planData }) => {
|
||||
const { sendEvent } = getContext();
|
||||
const { state } = getContext();
|
||||
|
||||
sendEvent(
|
||||
uiEvent.with({
|
||||
type: "ui_event",
|
||||
data: {
|
||||
state: "generate",
|
||||
requirement: planData.requirement.requirement,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const previousArtifact = state.lastArtifact
|
||||
? JSON.stringify(state.lastArtifact)
|
||||
: "There is no previous artifact";
|
||||
const requirementText = planData.requirement.requirement;
|
||||
|
||||
const prompt = `
|
||||
You are a skilled developer who can help user with coding.
|
||||
You are given a task to generate or update a code for a given requirement.
|
||||
|
||||
## Follow these instructions:
|
||||
**1. Carefully read the user's requirements.**
|
||||
If any details are ambiguous or missing, make reasonable assumptions and clearly reflect those in your output.
|
||||
If the previous code is provided:
|
||||
+ Carefully analyze the code with the request to make the right changes.
|
||||
+ Avoid making a lot of changes from the previous code if the request is not to write the code from scratch again.
|
||||
**2. For code requests:**
|
||||
- If the user does not specify a framework or language, default to a React component using the Next.js framework.
|
||||
- For Next.js, use Shadcn UI components, Typescript, @types/node, @types/react, @types/react-dom, PostCSS, and TailwindCSS.
|
||||
The import pattern should be:
|
||||
\`\`\`typescript
|
||||
import { ComponentName } from "@/components/ui/component-name"
|
||||
import { Markdown } from "@llamaindex/chat-ui"
|
||||
import { cn } from "@/lib/utils"
|
||||
\`\`\`
|
||||
- Ensure the code is idiomatic, production-ready, and includes necessary imports.
|
||||
- Only generate code relevant to the user's request—do not add extra boilerplate.
|
||||
**3. Don't be verbose on response**
|
||||
- No other text or comments only return the code which wrapped by \`\`\`language\`\`\` block.
|
||||
- If the user's request is to update the code, only return the updated code.
|
||||
**4. Only the following languages are allowed: "typescript", "python".**
|
||||
**5. If there is no code to update, return the reason without any code block.**
|
||||
|
||||
## Example:
|
||||
\`\`\`typescript
|
||||
import React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export default function MyComponent() {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-screen">
|
||||
<Button>Click me</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
The previous code is:
|
||||
{previousArtifact}
|
||||
|
||||
Now, i have to generate the code for the following requirement:
|
||||
{requirement}
|
||||
`
|
||||
.replace("{previousArtifact}", previousArtifact)
|
||||
.replace("{requirement}", requirementText);
|
||||
|
||||
const response = await llm.complete({
|
||||
prompt,
|
||||
});
|
||||
|
||||
// Extract the code from the response
|
||||
const codeMatch = response.text.match(/```(\w+)([\s\S]*)```/);
|
||||
if (!codeMatch) {
|
||||
return synthesizeAnswerEvent.with({});
|
||||
}
|
||||
|
||||
const code = codeMatch[2].trim();
|
||||
|
||||
// Put the generated code to the memory
|
||||
state.memory.put({
|
||||
role: "assistant",
|
||||
content: `Updated the code: \n${response.text}`,
|
||||
});
|
||||
|
||||
// To show the Canvas panel for the artifact
|
||||
sendEvent(
|
||||
artifactEvent.with({
|
||||
type: "artifact",
|
||||
data: {
|
||||
type: "code",
|
||||
created_at: Date.now(),
|
||||
data: {
|
||||
language: planData.requirement.language || "",
|
||||
file_name: planData.requirement.file_name || "",
|
||||
code,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
return synthesizeAnswerEvent.with({});
|
||||
});
|
||||
|
||||
workflow.handle([synthesizeAnswerEvent], async () => {
|
||||
const { sendEvent } = getContext();
|
||||
const { state } = getContext();
|
||||
|
||||
const chatHistory = await state.memory.getMessages();
|
||||
const messages = [
|
||||
...chatHistory,
|
||||
{
|
||||
role: "system" as const,
|
||||
content: `
|
||||
You are a helpful assistant who is responsible for explaining the work to the user.
|
||||
Based on the conversation history, provide an answer to the user's question.
|
||||
The user has access to the code so avoid mentioning the whole code again in your response.
|
||||
`,
|
||||
},
|
||||
];
|
||||
|
||||
const responseStream = await llm.chat({
|
||||
messages,
|
||||
stream: true,
|
||||
});
|
||||
|
||||
sendEvent(
|
||||
uiEvent.with({
|
||||
type: "ui_event",
|
||||
data: {
|
||||
state: "completed",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
let response = "";
|
||||
for await (const chunk of responseStream) {
|
||||
response += chunk.delta;
|
||||
sendEvent(
|
||||
agentStreamEvent.with({
|
||||
delta: chunk.delta,
|
||||
response: "",
|
||||
currentAgentName: "assistant",
|
||||
raw: chunk,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return stopAgentEvent.with({
|
||||
result: response,
|
||||
});
|
||||
});
|
||||
|
||||
return workflow;
|
||||
}
|
||||
@@ -19,7 +19,6 @@ export function ChatMessageContent({
|
||||
<ToolAnnotations />
|
||||
<ChatMessage.Content.Image />
|
||||
<DynamicEvents componentDefs={componentDefs} appendError={appendError} />
|
||||
<ChatMessage.Content.Artifact />
|
||||
<ChatMessage.Content.Markdown />
|
||||
<ChatMessage.Content.DocumentFile />
|
||||
<ChatMessage.Content.Source />
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"@babel/traverse": "^7.27.0",
|
||||
"@babel/types": "^7.27.0",
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@llamaindex/chat-ui": "0.4.9",
|
||||
"@llamaindex/chat-ui": "0.5.2",
|
||||
"@radix-ui/react-accordion": "^1.2.3",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.7",
|
||||
"@radix-ui/react-aspect-ratio": "^1.1.3",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"@babel/traverse": "^7.27.0",
|
||||
"@babel/types": "^7.27.0",
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@llamaindex/chat-ui": "0.4.9",
|
||||
"@llamaindex/chat-ui": "0.5.2",
|
||||
"@llamaindex/env": "~0.1.30",
|
||||
"@llamaindex/openai": "~0.4.0",
|
||||
"@llamaindex/readers": "~3.1.4",
|
||||
|
||||
@@ -2,4 +2,5 @@ export * from "./server";
|
||||
export * from "./types";
|
||||
export * from "./utils/events";
|
||||
export { generateEventComponent } from "./utils/gen-ui";
|
||||
export * from "./utils/inline";
|
||||
export * from "./utils/prompts";
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import { randomUUID } from "@llamaindex/env";
|
||||
import { workflowEvent } from "@llamaindex/workflow";
|
||||
import type { Message } from "ai";
|
||||
import { MetadataMode, type Metadata, type NodeWithScore } from "llamaindex";
|
||||
import {
|
||||
MetadataMode,
|
||||
type ChatMessage,
|
||||
type Metadata,
|
||||
type NodeWithScore,
|
||||
} from "llamaindex";
|
||||
import { z } from "zod";
|
||||
import { getInlineAnnotations } from "./inline";
|
||||
|
||||
// Events that appended to stream as annotations
|
||||
export type SourceEventNode = {
|
||||
@@ -148,24 +153,22 @@ export const artifactAnnotationSchema = z.object({
|
||||
data: artifactSchema,
|
||||
});
|
||||
|
||||
export function extractAllArtifacts(messages: Message[]): Artifact[] {
|
||||
const allArtifacts: Artifact[] = [];
|
||||
export function extractArtifactsFromMessage(message: ChatMessage): Artifact[] {
|
||||
const inlineAnnotations = getInlineAnnotations(message);
|
||||
const artifacts = inlineAnnotations.filter(
|
||||
(annotation): annotation is z.infer<typeof artifactAnnotationSchema> => {
|
||||
return artifactAnnotationSchema.safeParse(annotation).success;
|
||||
},
|
||||
);
|
||||
return artifacts.map((artifact) => artifact.data);
|
||||
}
|
||||
|
||||
for (const message of messages) {
|
||||
const artifacts =
|
||||
message.annotations
|
||||
?.filter(
|
||||
(
|
||||
annotation,
|
||||
): annotation is z.infer<typeof artifactAnnotationSchema> =>
|
||||
artifactAnnotationSchema.safeParse(annotation).success,
|
||||
)
|
||||
.map((annotation) => annotation.data as Artifact) ?? [];
|
||||
|
||||
allArtifacts.push(...artifacts);
|
||||
}
|
||||
|
||||
return allArtifacts;
|
||||
export function extractArtifactsFromAllMessages(
|
||||
messages: ChatMessage[],
|
||||
): Artifact[] {
|
||||
return messages
|
||||
.flatMap((message) => extractArtifactsFromMessage(message))
|
||||
.sort((a, b) => a.created_at - b.created_at);
|
||||
}
|
||||
|
||||
export function extractLastArtifact(
|
||||
@@ -187,10 +190,10 @@ export function extractLastArtifact(
|
||||
requestBody: unknown,
|
||||
type?: ArtifactType,
|
||||
): CodeArtifact | DocumentArtifact | Artifact | undefined {
|
||||
const { messages } = (requestBody as { messages?: Message[] }) ?? {};
|
||||
const { messages } = (requestBody as { messages?: ChatMessage[] }) ?? {};
|
||||
if (!messages) return undefined;
|
||||
|
||||
const artifacts = extractAllArtifacts(messages);
|
||||
const artifacts = extractArtifactsFromAllMessages(messages);
|
||||
if (!artifacts.length) return undefined;
|
||||
|
||||
if (type) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export * from "./events";
|
||||
export * from "./file";
|
||||
export * from "./gen-ui";
|
||||
export * from "./inline";
|
||||
export * from "./prompts";
|
||||
export * from "./request";
|
||||
export * from "./stream";
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import { agentStreamEvent, type WorkflowEventData } from "@llamaindex/workflow";
|
||||
import { type ChatMessage } from "llamaindex";
|
||||
import { z } from "zod";
|
||||
|
||||
const INLINE_ANNOTATION_KEY = "annotation"; // the language key to detect inline annotation code in markdown
|
||||
|
||||
export const AnnotationSchema = z.object({
|
||||
type: z.string(),
|
||||
data: z.any(),
|
||||
});
|
||||
|
||||
export type Annotation = z.infer<typeof AnnotationSchema>;
|
||||
|
||||
export function getInlineAnnotations(message: ChatMessage): Annotation[] {
|
||||
const markdownContent = getMessageMarkdownContent(message);
|
||||
|
||||
const inlineAnnotations: Annotation[] = [];
|
||||
|
||||
// Regex to match annotation code blocks
|
||||
// Matches ```annotation followed by content until closing ```
|
||||
const annotationRegex = new RegExp(
|
||||
`\`\`\`${INLINE_ANNOTATION_KEY}\\s*\\n([\\s\\S]*?)\\n\`\`\``,
|
||||
"g",
|
||||
);
|
||||
|
||||
let match;
|
||||
while ((match = annotationRegex.exec(markdownContent)) !== null) {
|
||||
const jsonContent = match[1]?.trim();
|
||||
|
||||
if (!jsonContent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// Parse the JSON content
|
||||
const parsed = JSON.parse(jsonContent);
|
||||
|
||||
// Validate against the annotation schema
|
||||
const validated = AnnotationSchema.parse(parsed);
|
||||
|
||||
// Extract the artifact data
|
||||
inlineAnnotations.push(validated);
|
||||
} catch (error) {
|
||||
// Skip invalid annotations - they might be malformed JSON or invalid schema
|
||||
console.warn("Failed to parse annotation:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return inlineAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* To append inline annotations to the stream, we need to wrap the annotation in a code block with the language key.
|
||||
* The language key is `annotation` and the code block is wrapped in backticks.
|
||||
*
|
||||
* \`\`\`annotation
|
||||
* \{
|
||||
* "type": "artifact",
|
||||
* "data": \{...\}
|
||||
* \}
|
||||
* \`\`\`
|
||||
*/
|
||||
export function toInlineAnnotation(item: unknown) {
|
||||
return `\n\`\`\`${INLINE_ANNOTATION_KEY}\n${JSON.stringify(item)}\n\`\`\`\n`;
|
||||
}
|
||||
|
||||
export function toInlineAnnotationEvent(event: WorkflowEventData<unknown>) {
|
||||
return agentStreamEvent.with({
|
||||
delta: toInlineAnnotation(event.data),
|
||||
response: "",
|
||||
currentAgentName: "assistant",
|
||||
raw: event.data,
|
||||
});
|
||||
}
|
||||
|
||||
function getMessageMarkdownContent(message: ChatMessage): string {
|
||||
let markdownContent = "";
|
||||
|
||||
if (typeof message.content === "string") {
|
||||
markdownContent = message.content;
|
||||
} else {
|
||||
message.content.forEach((item) => {
|
||||
if (item.type === "text") {
|
||||
markdownContent += item.text;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return markdownContent;
|
||||
}
|
||||
@@ -15,12 +15,14 @@ import {
|
||||
type NodeWithScore,
|
||||
} from "llamaindex";
|
||||
import {
|
||||
artifactEvent,
|
||||
sourceEvent,
|
||||
toAgentRunEvent,
|
||||
toSourceEvent,
|
||||
type SourceEventNode,
|
||||
} from "./events";
|
||||
import { downloadFile } from "./file";
|
||||
import { toInlineAnnotationEvent } from "./inline";
|
||||
|
||||
export async function runWorkflow(
|
||||
workflow: Workflow,
|
||||
@@ -74,6 +76,10 @@ function processWorkflowStream(
|
||||
transformedEvent = toSourceEvent(sourceNodes);
|
||||
}
|
||||
}
|
||||
// Handle artifact events, transform to agentStreamEvent
|
||||
else if (artifactEvent.include(event)) {
|
||||
transformedEvent = toInlineAnnotationEvent(event);
|
||||
}
|
||||
// Post-process for llama-cloud files
|
||||
if (sourceEvent.include(transformedEvent)) {
|
||||
const sourceNodesForDownload = transformedEvent.data.data.nodes; // These are SourceEventNode[]
|
||||
|
||||
Generated
+299
-19
@@ -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.4.9
|
||||
version: 0.4.9(@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.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)
|
||||
'@llamaindex/env':
|
||||
specifier: ~0.1.30
|
||||
version: 0.1.30
|
||||
@@ -1186,8 +1186,8 @@ packages:
|
||||
zod:
|
||||
optional: true
|
||||
|
||||
'@llamaindex/chat-ui@0.4.9':
|
||||
resolution: {integrity: sha512-KEdydC+aJ22VK/TltxIHlMWbWLfh6I0YkyVd1D/CS3FRfLt8l9jfQ/YjY10MiEd8oc1fFfk6ek/FhVWe9Szstg==}
|
||||
'@llamaindex/chat-ui@0.5.2':
|
||||
resolution: {integrity: sha512-zIOaf5cuhDtllrcDEDaGNRq2bon8STUYoex4n+zzowR6eirRRYPYoUpRBNBK7fZi4BJhBPmqTS/tkXzjw908Gw==}
|
||||
peerDependencies:
|
||||
react: ^18.2.0 || ^19.0.0 || ^19.0.0-rc
|
||||
|
||||
@@ -2454,6 +2454,9 @@ packages:
|
||||
'@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==}
|
||||
|
||||
@@ -4621,6 +4624,9 @@ packages:
|
||||
mdast-util-from-markdown@1.3.1:
|
||||
resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==}
|
||||
|
||||
mdast-util-from-markdown@2.0.2:
|
||||
resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
|
||||
|
||||
mdast-util-gfm-autolink-literal@1.0.3:
|
||||
resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==}
|
||||
|
||||
@@ -4645,15 +4651,24 @@ packages:
|
||||
mdast-util-phrasing@3.0.1:
|
||||
resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==}
|
||||
|
||||
mdast-util-phrasing@4.1.0:
|
||||
resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
|
||||
|
||||
mdast-util-to-hast@12.3.0:
|
||||
resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==}
|
||||
|
||||
mdast-util-to-markdown@1.5.0:
|
||||
resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==}
|
||||
|
||||
mdast-util-to-markdown@2.1.2:
|
||||
resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
|
||||
|
||||
mdast-util-to-string@3.2.0:
|
||||
resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==}
|
||||
|
||||
mdast-util-to-string@4.0.0:
|
||||
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
|
||||
|
||||
mdurl@2.0.0:
|
||||
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
|
||||
|
||||
@@ -4686,6 +4701,9 @@ packages:
|
||||
micromark-core-commonmark@1.1.0:
|
||||
resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==}
|
||||
|
||||
micromark-core-commonmark@2.0.3:
|
||||
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
|
||||
|
||||
micromark-extension-gfm-autolink-literal@1.0.5:
|
||||
resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==}
|
||||
|
||||
@@ -4713,63 +4731,123 @@ packages:
|
||||
micromark-factory-destination@1.1.0:
|
||||
resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==}
|
||||
|
||||
micromark-factory-destination@2.0.1:
|
||||
resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
|
||||
|
||||
micromark-factory-label@1.1.0:
|
||||
resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==}
|
||||
|
||||
micromark-factory-label@2.0.1:
|
||||
resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
|
||||
|
||||
micromark-factory-space@1.1.0:
|
||||
resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==}
|
||||
|
||||
micromark-factory-space@2.0.1:
|
||||
resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
|
||||
|
||||
micromark-factory-title@1.1.0:
|
||||
resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==}
|
||||
|
||||
micromark-factory-title@2.0.1:
|
||||
resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
|
||||
|
||||
micromark-factory-whitespace@1.1.0:
|
||||
resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==}
|
||||
|
||||
micromark-factory-whitespace@2.0.1:
|
||||
resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
|
||||
|
||||
micromark-util-character@1.2.0:
|
||||
resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==}
|
||||
|
||||
micromark-util-character@2.1.1:
|
||||
resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
|
||||
|
||||
micromark-util-chunked@1.1.0:
|
||||
resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==}
|
||||
|
||||
micromark-util-chunked@2.0.1:
|
||||
resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
|
||||
|
||||
micromark-util-classify-character@1.1.0:
|
||||
resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==}
|
||||
|
||||
micromark-util-classify-character@2.0.1:
|
||||
resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
|
||||
|
||||
micromark-util-combine-extensions@1.1.0:
|
||||
resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==}
|
||||
|
||||
micromark-util-combine-extensions@2.0.1:
|
||||
resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
|
||||
|
||||
micromark-util-decode-numeric-character-reference@1.1.0:
|
||||
resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==}
|
||||
|
||||
micromark-util-decode-numeric-character-reference@2.0.2:
|
||||
resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
|
||||
|
||||
micromark-util-decode-string@1.1.0:
|
||||
resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==}
|
||||
|
||||
micromark-util-decode-string@2.0.1:
|
||||
resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
|
||||
|
||||
micromark-util-encode@1.1.0:
|
||||
resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==}
|
||||
|
||||
micromark-util-encode@2.0.1:
|
||||
resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
|
||||
|
||||
micromark-util-html-tag-name@1.2.0:
|
||||
resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==}
|
||||
|
||||
micromark-util-html-tag-name@2.0.1:
|
||||
resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
|
||||
|
||||
micromark-util-normalize-identifier@1.1.0:
|
||||
resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==}
|
||||
|
||||
micromark-util-normalize-identifier@2.0.1:
|
||||
resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
|
||||
|
||||
micromark-util-resolve-all@1.1.0:
|
||||
resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==}
|
||||
|
||||
micromark-util-resolve-all@2.0.1:
|
||||
resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
|
||||
|
||||
micromark-util-sanitize-uri@1.2.0:
|
||||
resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==}
|
||||
|
||||
micromark-util-sanitize-uri@2.0.1:
|
||||
resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
|
||||
|
||||
micromark-util-subtokenize@1.1.0:
|
||||
resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==}
|
||||
|
||||
micromark-util-subtokenize@2.1.0:
|
||||
resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
|
||||
|
||||
micromark-util-symbol@1.1.0:
|
||||
resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==}
|
||||
|
||||
micromark-util-symbol@2.0.1:
|
||||
resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
|
||||
|
||||
micromark-util-types@1.1.0:
|
||||
resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==}
|
||||
|
||||
micromark-util-types@2.0.2:
|
||||
resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
|
||||
|
||||
micromark@3.2.0:
|
||||
resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==}
|
||||
|
||||
micromark@4.0.2:
|
||||
resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
|
||||
|
||||
micromatch@4.0.8:
|
||||
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||
engines: {node: '>=8.6'}
|
||||
@@ -5634,14 +5712,17 @@ packages:
|
||||
remark-parse@10.0.2:
|
||||
resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==}
|
||||
|
||||
remark-parse@11.0.0:
|
||||
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
|
||||
|
||||
remark-rehype@10.1.0:
|
||||
resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==}
|
||||
|
||||
remark-stringify@10.0.3:
|
||||
resolution: {integrity: sha512-koyOzCMYoUHudypbj4XpnAKFbkddRMYZHwghnxd7ue5210WzGw6kOBwauJTRUMq16jsovXx8dYNvSSWP89kZ3A==}
|
||||
remark-stringify@11.0.0:
|
||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
||||
|
||||
remark@14.0.3:
|
||||
resolution: {integrity: sha512-bfmJW1dmR2LvaMJuAnE88pZP9DktIFYXazkTfOIKZzi3Knk9lT0roItIA24ydOucI3bV/g/tXBA6hzqq3FV9Ew==}
|
||||
remark@15.0.1:
|
||||
resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==}
|
||||
|
||||
require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
@@ -6265,6 +6346,9 @@ packages:
|
||||
unified@10.1.2:
|
||||
resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==}
|
||||
|
||||
unified@11.0.5:
|
||||
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
|
||||
|
||||
unist-util-find-after@5.0.0:
|
||||
resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
|
||||
|
||||
@@ -7367,7 +7451,7 @@ snapshots:
|
||||
p-retry: 6.2.1
|
||||
zod: 3.25.13
|
||||
|
||||
'@llamaindex/chat-ui@0.4.9(@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.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)':
|
||||
dependencies:
|
||||
'@codemirror/lang-css': 6.3.1
|
||||
'@codemirror/lang-html': 6.4.9
|
||||
@@ -7401,11 +7485,13 @@ snapshots:
|
||||
react: 19.1.0
|
||||
react-markdown: 8.0.7(@types/react@19.1.2)(react@19.1.0)
|
||||
rehype-katex: 7.0.1
|
||||
remark: 14.0.3
|
||||
remark: 15.0.1
|
||||
remark-code-import: 1.2.0
|
||||
remark-gfm: 3.0.1
|
||||
remark-math: 5.1.1
|
||||
remark-parse: 11.0.0
|
||||
tailwind-merge: 2.6.0
|
||||
unist-util-visit: 5.0.0
|
||||
vaul: 0.9.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)
|
||||
transitivePeerDependencies:
|
||||
- '@babel/runtime'
|
||||
@@ -8713,6 +8799,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 2.0.11
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
'@types/mdurl@2.0.0': {}
|
||||
|
||||
'@types/ms@2.1.0': {}
|
||||
@@ -11247,6 +11337,23 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
mdast-util-from-markdown@2.0.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
'@types/unist': 3.0.3
|
||||
decode-named-character-reference: 1.1.0
|
||||
devlop: 1.1.0
|
||||
mdast-util-to-string: 4.0.0
|
||||
micromark: 4.0.2
|
||||
micromark-util-decode-numeric-character-reference: 2.0.2
|
||||
micromark-util-decode-string: 2.0.1
|
||||
micromark-util-normalize-identifier: 2.0.1
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
unist-util-stringify-position: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
mdast-util-gfm-autolink-literal@1.0.3:
|
||||
dependencies:
|
||||
'@types/mdast': 3.0.15
|
||||
@@ -11302,6 +11409,11 @@ snapshots:
|
||||
'@types/mdast': 3.0.15
|
||||
unist-util-is: 5.2.1
|
||||
|
||||
mdast-util-phrasing@4.1.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
unist-util-is: 6.0.0
|
||||
|
||||
mdast-util-to-hast@12.3.0:
|
||||
dependencies:
|
||||
'@types/hast': 2.3.10
|
||||
@@ -11324,10 +11436,26 @@ snapshots:
|
||||
unist-util-visit: 4.1.2
|
||||
zwitch: 2.0.4
|
||||
|
||||
mdast-util-to-markdown@2.1.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
'@types/unist': 3.0.3
|
||||
longest-streak: 3.1.0
|
||||
mdast-util-phrasing: 4.1.0
|
||||
mdast-util-to-string: 4.0.0
|
||||
micromark-util-classify-character: 2.0.1
|
||||
micromark-util-decode-string: 2.0.1
|
||||
unist-util-visit: 5.0.0
|
||||
zwitch: 2.0.4
|
||||
|
||||
mdast-util-to-string@3.2.0:
|
||||
dependencies:
|
||||
'@types/mdast': 3.0.15
|
||||
|
||||
mdast-util-to-string@4.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
||||
mdurl@2.0.0: {}
|
||||
|
||||
media-typer@1.1.0: {}
|
||||
@@ -11363,6 +11491,25 @@ snapshots:
|
||||
micromark-util-types: 1.1.0
|
||||
uvu: 0.5.6
|
||||
|
||||
micromark-core-commonmark@2.0.3:
|
||||
dependencies:
|
||||
decode-named-character-reference: 1.1.0
|
||||
devlop: 1.1.0
|
||||
micromark-factory-destination: 2.0.1
|
||||
micromark-factory-label: 2.0.1
|
||||
micromark-factory-space: 2.0.1
|
||||
micromark-factory-title: 2.0.1
|
||||
micromark-factory-whitespace: 2.0.1
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-chunked: 2.0.1
|
||||
micromark-util-classify-character: 2.0.1
|
||||
micromark-util-html-tag-name: 2.0.1
|
||||
micromark-util-normalize-identifier: 2.0.1
|
||||
micromark-util-resolve-all: 2.0.1
|
||||
micromark-util-subtokenize: 2.1.0
|
||||
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
|
||||
@@ -11437,6 +11584,12 @@ snapshots:
|
||||
micromark-util-symbol: 1.1.0
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-factory-destination@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-factory-label@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-character: 1.2.0
|
||||
@@ -11444,11 +11597,23 @@ snapshots:
|
||||
micromark-util-types: 1.1.0
|
||||
uvu: 0.5.6
|
||||
|
||||
micromark-factory-label@2.0.1:
|
||||
dependencies:
|
||||
devlop: 1.1.0
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-factory-space@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-character: 1.2.0
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-factory-space@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-factory-title@1.1.0:
|
||||
dependencies:
|
||||
micromark-factory-space: 1.1.0
|
||||
@@ -11456,6 +11621,13 @@ snapshots:
|
||||
micromark-util-symbol: 1.1.0
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-factory-title@2.0.1:
|
||||
dependencies:
|
||||
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-factory-whitespace@1.1.0:
|
||||
dependencies:
|
||||
micromark-factory-space: 1.1.0
|
||||
@@ -11463,30 +11635,61 @@ snapshots:
|
||||
micromark-util-symbol: 1.1.0
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-factory-whitespace@2.0.1:
|
||||
dependencies:
|
||||
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-util-character@1.2.0:
|
||||
dependencies:
|
||||
micromark-util-symbol: 1.1.0
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-util-character@2.1.1:
|
||||
dependencies:
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-util-chunked@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-symbol: 1.1.0
|
||||
|
||||
micromark-util-chunked@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-symbol: 2.0.1
|
||||
|
||||
micromark-util-classify-character@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-character: 1.2.0
|
||||
micromark-util-symbol: 1.1.0
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-util-classify-character@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-util-combine-extensions@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-chunked: 1.1.0
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-util-combine-extensions@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-chunked: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-util-decode-numeric-character-reference@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-symbol: 1.1.0
|
||||
|
||||
micromark-util-decode-numeric-character-reference@2.0.2:
|
||||
dependencies:
|
||||
micromark-util-symbol: 2.0.1
|
||||
|
||||
micromark-util-decode-string@1.1.0:
|
||||
dependencies:
|
||||
decode-named-character-reference: 1.1.0
|
||||
@@ -11494,24 +11697,49 @@ snapshots:
|
||||
micromark-util-decode-numeric-character-reference: 1.1.0
|
||||
micromark-util-symbol: 1.1.0
|
||||
|
||||
micromark-util-decode-string@2.0.1:
|
||||
dependencies:
|
||||
decode-named-character-reference: 1.1.0
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-decode-numeric-character-reference: 2.0.2
|
||||
micromark-util-symbol: 2.0.1
|
||||
|
||||
micromark-util-encode@1.1.0: {}
|
||||
|
||||
micromark-util-encode@2.0.1: {}
|
||||
|
||||
micromark-util-html-tag-name@1.2.0: {}
|
||||
|
||||
micromark-util-html-tag-name@2.0.1: {}
|
||||
|
||||
micromark-util-normalize-identifier@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-symbol: 1.1.0
|
||||
|
||||
micromark-util-normalize-identifier@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-symbol: 2.0.1
|
||||
|
||||
micromark-util-resolve-all@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-types: 1.1.0
|
||||
|
||||
micromark-util-resolve-all@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-util-sanitize-uri@1.2.0:
|
||||
dependencies:
|
||||
micromark-util-character: 1.2.0
|
||||
micromark-util-encode: 1.1.0
|
||||
micromark-util-symbol: 1.1.0
|
||||
|
||||
micromark-util-sanitize-uri@2.0.1:
|
||||
dependencies:
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-encode: 2.0.1
|
||||
micromark-util-symbol: 2.0.1
|
||||
|
||||
micromark-util-subtokenize@1.1.0:
|
||||
dependencies:
|
||||
micromark-util-chunked: 1.1.0
|
||||
@@ -11519,10 +11747,21 @@ snapshots:
|
||||
micromark-util-types: 1.1.0
|
||||
uvu: 0.5.6
|
||||
|
||||
micromark-util-subtokenize@2.1.0:
|
||||
dependencies:
|
||||
devlop: 1.1.0
|
||||
micromark-util-chunked: 2.0.1
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
|
||||
micromark-util-symbol@1.1.0: {}
|
||||
|
||||
micromark-util-symbol@2.0.1: {}
|
||||
|
||||
micromark-util-types@1.1.0: {}
|
||||
|
||||
micromark-util-types@2.0.2: {}
|
||||
|
||||
micromark@3.2.0:
|
||||
dependencies:
|
||||
'@types/debug': 4.1.12
|
||||
@@ -11545,6 +11784,28 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
micromark@4.0.2:
|
||||
dependencies:
|
||||
'@types/debug': 4.1.12
|
||||
debug: 4.4.0(supports-color@5.5.0)
|
||||
decode-named-character-reference: 1.1.0
|
||||
devlop: 1.1.0
|
||||
micromark-core-commonmark: 2.0.3
|
||||
micromark-factory-space: 2.0.1
|
||||
micromark-util-character: 2.1.1
|
||||
micromark-util-chunked: 2.0.1
|
||||
micromark-util-combine-extensions: 2.0.1
|
||||
micromark-util-decode-numeric-character-reference: 2.0.2
|
||||
micromark-util-encode: 2.0.1
|
||||
micromark-util-normalize-identifier: 2.0.1
|
||||
micromark-util-resolve-all: 2.0.1
|
||||
micromark-util-sanitize-uri: 2.0.1
|
||||
micromark-util-subtokenize: 2.1.0
|
||||
micromark-util-symbol: 2.0.1
|
||||
micromark-util-types: 2.0.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
micromatch@4.0.8:
|
||||
dependencies:
|
||||
braces: 3.0.3
|
||||
@@ -12401,6 +12662,15 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
remark-parse@11.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-from-markdown: 2.0.2
|
||||
micromark-util-types: 2.0.2
|
||||
unified: 11.0.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
remark-rehype@10.1.0:
|
||||
dependencies:
|
||||
'@types/hast': 2.3.10
|
||||
@@ -12408,18 +12678,18 @@ snapshots:
|
||||
mdast-util-to-hast: 12.3.0
|
||||
unified: 10.1.2
|
||||
|
||||
remark-stringify@10.0.3:
|
||||
remark-stringify@11.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 3.0.15
|
||||
mdast-util-to-markdown: 1.5.0
|
||||
unified: 10.1.2
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-to-markdown: 2.1.2
|
||||
unified: 11.0.5
|
||||
|
||||
remark@14.0.3:
|
||||
remark@15.0.1:
|
||||
dependencies:
|
||||
'@types/mdast': 3.0.15
|
||||
remark-parse: 10.0.2
|
||||
remark-stringify: 10.0.3
|
||||
unified: 10.1.2
|
||||
'@types/mdast': 4.0.4
|
||||
remark-parse: 11.0.0
|
||||
remark-stringify: 11.0.0
|
||||
unified: 11.0.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -13142,6 +13412,16 @@ snapshots:
|
||||
trough: 2.2.0
|
||||
vfile: 5.3.7
|
||||
|
||||
unified@11.0.5:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
bail: 2.0.2
|
||||
devlop: 1.1.0
|
||||
extend: 3.0.2
|
||||
is-plain-obj: 4.1.0
|
||||
trough: 2.2.0
|
||||
vfile: 6.0.3
|
||||
|
||||
unist-util-find-after@5.0.0:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
from llama_index.server.api.callbacks.agent_call_tool import AgentCallTool
|
||||
from llama_index.server.api.callbacks.artifact_transform import (
|
||||
InlineAnnotationTransformer,
|
||||
)
|
||||
from llama_index.server.api.callbacks.base import EventCallback
|
||||
from llama_index.server.api.callbacks.llamacloud import LlamaCloudFileDownload
|
||||
from llama_index.server.api.callbacks.source_nodes import SourceNodesFromToolCall
|
||||
@@ -12,4 +15,5 @@ __all__ = [
|
||||
"SuggestNextQuestions",
|
||||
"LlamaCloudFileDownload",
|
||||
"AgentCallTool",
|
||||
"InlineAnnotationTransformer",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from llama_index.server.api.callbacks.base import EventCallback
|
||||
from llama_index.server.models.artifacts import ArtifactEvent
|
||||
from llama_index.server.utils.inline import to_inline_annotation_event
|
||||
|
||||
logger = logging.getLogger("uvicorn")
|
||||
|
||||
|
||||
class InlineAnnotationTransformer(EventCallback):
|
||||
"""
|
||||
Transforms an event to AgentStream with inline annotation format.
|
||||
"""
|
||||
|
||||
async def run(self, event: Any) -> Any:
|
||||
# handle for ArtifactEvent specifically as it's only supported by inline annotation
|
||||
if isinstance(event, ArtifactEvent):
|
||||
return to_inline_annotation_event(event)
|
||||
return event
|
||||
|
||||
@classmethod
|
||||
def from_default(cls, *args: Any, **kwargs: Any) -> "InlineAnnotationTransformer":
|
||||
return cls()
|
||||
@@ -18,6 +18,7 @@ from llama_index.core.workflow import (
|
||||
from llama_index.server.api.callbacks import (
|
||||
AgentCallTool,
|
||||
EventCallback,
|
||||
InlineAnnotationTransformer,
|
||||
LlamaCloudFileDownload,
|
||||
SourceNodesFromToolCall,
|
||||
SuggestNextQuestions,
|
||||
@@ -72,6 +73,7 @@ def chat_router(
|
||||
|
||||
callbacks: list[EventCallback] = [
|
||||
AgentCallTool(),
|
||||
InlineAnnotationTransformer(),
|
||||
SourceNodesFromToolCall(),
|
||||
LlamaCloudFileDownload(background_tasks),
|
||||
]
|
||||
|
||||
@@ -5,6 +5,7 @@ from typing import Literal, Optional, Union
|
||||
from llama_index.core.workflow.events import Event
|
||||
from llama_index.server.models.chat import ChatAPIMessage
|
||||
from pydantic import BaseModel
|
||||
from llama_index.server.utils.inline import get_inline_annotations
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -33,10 +34,9 @@ class Artifact(BaseModel):
|
||||
|
||||
@classmethod
|
||||
def from_message(cls, message: ChatAPIMessage) -> Optional["Artifact"]:
|
||||
if not message.annotations or not isinstance(message.annotations, list):
|
||||
return None
|
||||
inline_annotations = get_inline_annotations(message)
|
||||
|
||||
for annotation in message.annotations:
|
||||
for annotation in inline_annotations:
|
||||
if isinstance(annotation, dict) and annotation.get("type") == "artifact":
|
||||
try:
|
||||
artifact = cls.model_validate(annotation.get("data"))
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import json
|
||||
import re
|
||||
from typing import Any, List
|
||||
|
||||
from pydantic import ValidationError
|
||||
|
||||
from llama_index.core.workflow.events import Event
|
||||
from llama_index.server.models.chat import ChatAPIMessage
|
||||
from llama_index.core.agent.workflow.workflow_events import AgentStream
|
||||
|
||||
INLINE_ANNOTATION_KEY = (
|
||||
"annotation" # the language key to detect inline annotation code in markdown
|
||||
)
|
||||
|
||||
|
||||
def get_inline_annotations(message: ChatAPIMessage) -> List[Any]:
|
||||
"""Extract inline annotations from a chat message."""
|
||||
markdown_content = message.content
|
||||
|
||||
inline_annotations: List[Any] = []
|
||||
|
||||
# Regex to match annotation code blocks
|
||||
# Matches ```annotation followed by content until closing ```
|
||||
annotation_regex = re.compile(
|
||||
rf"```{re.escape(INLINE_ANNOTATION_KEY)}\s*\n([\s\S]*?)\n```", re.MULTILINE
|
||||
)
|
||||
|
||||
for match in annotation_regex.finditer(markdown_content):
|
||||
json_content = match.group(1).strip() if match.group(1) else None
|
||||
|
||||
if not json_content:
|
||||
continue
|
||||
|
||||
try:
|
||||
# Parse the JSON content
|
||||
parsed = json.loads(json_content)
|
||||
|
||||
# Check for required fields in the parsed annotation
|
||||
if (
|
||||
not isinstance(parsed, dict)
|
||||
or "type" not in parsed
|
||||
or "data" not in parsed
|
||||
):
|
||||
continue
|
||||
|
||||
# Extract the annotation data
|
||||
inline_annotations.append(parsed)
|
||||
except (json.JSONDecodeError, ValidationError) as error:
|
||||
# Skip invalid annotations - they might be malformed JSON or invalid schema
|
||||
print(f"Failed to parse annotation: {error}")
|
||||
|
||||
return inline_annotations
|
||||
|
||||
|
||||
def to_inline_annotation(item: dict) -> str:
|
||||
"""
|
||||
To append inline annotations to the stream, we need to wrap the annotation in a code block with the language key.
|
||||
The language key is `annotation` and the code block is wrapped in backticks.
|
||||
|
||||
```annotation
|
||||
{
|
||||
"type": "artifact",
|
||||
"data": {...}
|
||||
}
|
||||
```
|
||||
"""
|
||||
return f"\n```{INLINE_ANNOTATION_KEY}\n{json.dumps(item)}\n```\n"
|
||||
|
||||
|
||||
def to_inline_annotation_event(event: Event) -> AgentStream:
|
||||
"""
|
||||
Convert an event to an AgentStream with inline annotation format.
|
||||
"""
|
||||
event_dict = event.model_dump()
|
||||
return AgentStream(
|
||||
delta=to_inline_annotation(event_dict),
|
||||
response="",
|
||||
current_agent_name="assistant",
|
||||
tool_calls=[],
|
||||
raw=event_dict,
|
||||
)
|
||||
Reference in New Issue
Block a user