Compare commits

...

22 Commits

Author SHA1 Message Date
Marcus Schiesser f463efd8a5 docs: fix agentic rag tutorial 2025-04-22 12:13:06 +02:00
Alex Yang cf95af40d9 make docs great again - 2nd time (#1876) 2025-04-21 15:07:16 -07:00
Alex Yang ddc910dc73 docs: no validate links 2025-04-21 12:50:10 -07:00
Alex Yang f12af27760 docs: fix turbo.json 2025-04-21 12:35:31 -07:00
Alex Yang ffdbc8f5e8 docs: disable typedoc 2025-04-21 12:27:08 -07:00
Alex Yang ea8817f7e4 fix(docs): search page id (#1875) 2025-04-21 12:10:42 -07:00
Alex Yang 359698d04b docs: remove links on docs detail page 2025-04-21 09:53:26 -07:00
Huu Le b49fb24948 docs: fix search function on the documentation site is not working. (#1872) 2025-04-21 09:49:48 -07:00
Alex Yang 78841495aa docs: fix meta.json 2025-04-21 09:43:28 -07:00
Alex Yang c81dd21472 chore: bump llama-flow docs 2025-04-21 09:38:14 -07:00
Alex Yang 52868ea0f9 docs: remove llamacloud section (#1851) 2025-04-21 09:37:40 -07:00
Logan e0a730e44e docs: replace with llama-flow docs (#1874)
Co-authored-by: Alex Yang <himself65@outlook.com>
2025-04-21 09:37:27 -07:00
Alex Yang eda486bb52 chore: bump pnpm (#1871) 2025-04-21 09:25:48 -07:00
Alex Yang 10d9c708db ci: enable turbo cache (#1873) 2025-04-21 09:25:38 -07:00
Alex Yang 556027705e chore(docs): fix inputs 2025-04-21 04:13:46 -07:00
github-actions[bot] 588cd0f0b9 Release 0.10.2 (#1861)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: marcusschiesser <17126+marcusschiesser@users.noreply.github.com>
2025-04-18 17:14:21 +07:00
Huu Le 7ca9ddff86 feat: Add generate UI workflow to server (#1862)
Co-authored-by: Marcus Schiesser <mail@marcusschiesser.de>
Co-authored-by: Thuc Pham <51660321+thucpn@users.noreply.github.com>
2025-04-18 16:59:44 +07:00
Thuc Pham 3310eaae29 chore: bump chat-ui 0.4.0 (#1868) 2025-04-18 15:33:08 +07:00
Peter Goldstein 96dac4ddfd feat: Add Gemini 2.5 Flash Preview (#1866) 2025-04-18 15:30:06 +07:00
Logan f9ee683593 docs: remove fake chat (#1867) 2025-04-17 17:14:38 -07:00
Peter Goldstein e5c3f95c6e Update o4-mini to allow reasoning parameters and exclude temperature (#1859) 2025-04-17 13:51:27 +07:00
Thuc Pham b155c8cf2c chore: make llamaindex as peer deps of server (#1860) 2025-04-17 13:50:28 +07:00
92 changed files with 1161 additions and 995 deletions
@@ -8,6 +8,11 @@ on:
branches:
- main
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_REMOTE_ONLY: true
jobs:
lint:
runs-on: ubuntu-latest
+5
View File
@@ -1,6 +1,11 @@
name: Publish Preview
on: [pull_request]
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
TURBO_REMOTE_ONLY: true
jobs:
pre_release:
name: Pre Release
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/doc
## 0.2.13
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
- llamaindex@0.10.2
## 0.2.12
### Patch Changes
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/doc",
"version": "0.2.12",
"version": "0.2.13",
"private": true,
"scripts": {
"postinstall": "fumadocs-mdx",
@@ -15,7 +15,7 @@
"dependencies": {
"@huggingface/transformers": "^3.5.0",
"@icons-pack/react-simple-icons": "^10.1.0",
"@llama-flow/docs": "0.0.3",
"@llama-flow/docs": "0.0.5",
"@llamaindex/chat-ui": "0.2.0",
"@llamaindex/cloud": "workspace:*",
"@llamaindex/core": "workspace:*",
@@ -90,9 +90,9 @@
"remark-stringify": "^11.0.0",
"tailwindcss": "^4.0.9",
"tsx": "^4.19.3",
"typedoc": "0.28.2",
"typedoc": "0.28.3",
"typedoc-plugin-markdown": "^4.6.2",
"typedoc-plugin-merge-modules": "^7.0.0",
"typedoc-plugin-merge-modules": " ^7.0.0",
"typescript": "^5.7.3"
}
}
+12 -16
View File
@@ -1,4 +1,3 @@
import { generateFiles as openapiGenerateFiles } from "fumadocs-openapi";
import {
createGenerator,
generateFiles as typescriptGenerateFiles,
@@ -14,18 +13,12 @@ const apiRefOut = "./src/content/docs/api";
// clean generated files
rimrafSync(out, {
filter(v) {
return !v.endsWith("index.mdx") && !v.endsWith("meta.json");
return !v.endsWith("index.md") && !v.endsWith("meta.json");
},
});
void openapiGenerateFiles({
input: ["../../packages/cloud/openapi.json"],
output: "./src/content/docs/cloud/api",
groupBy: "tag",
});
void typescriptGenerateFiles(generator, {
input: ["./src/content/docs/api/**/*.mdx"],
input: ["./src/content/docs/api/**/*.md"],
output: (file) => path.resolve(path.dirname(file), path.basename(file)),
transformOutput,
});
@@ -34,19 +27,22 @@ function transformOutput(filePath: string, content: string) {
const fileName = path.basename(filePath);
let title = fileName.split(".")[0];
if (title === "index") title = "LlamaIndex API Reference";
return `---\ntitle: ${title}\n---\n\n${transformAbsoluteUrl(content, filePath)}`;
return `---\ntitle: ${title}\n---\n\n${transformAbsoluteUrl(
content.replace(/(?<!\\)\{([^}]+)(?<!\\)}/g, "\\{$1\\}"),
filePath,
)}`;
}
/**
* Transforms the content by converting relative MDX links to absolute docs API links
* Example: [text](../type-aliases/TaskHandler.mdx) -> [text](/docs/api/type-aliases/TaskHandler)
* [text](BaseChatEngine.mdx) -> [text](/docs/api/classes/BaseChatEngine)
* [text](BaseVectorStore.mdx#constructors) -> [text](/docs/api/classes/BaseVectorStore#constructors)
* [text](TaskStep.mdx) -> [text](/docs/api/type-aliases/TaskStep)
* Transforms the content by converting relative MD links to absolute docs API links
* Example: [text](../type-aliases/TaskHandler.md) -> [text](/docs/api/type-aliases/TaskHandler)
* [text](BaseChatEngine.md) -> [text](/docs/api/classes/BaseChatEngine)
* [text](BaseVectorStore.md#constructors) -> [text](/docs/api/classes/BaseVectorStore#constructors)
* [text](TaskStep.md) -> [text](/docs/api/type-aliases/TaskStep)
*/
function transformAbsoluteUrl(content: string, filePath: string) {
const group = path.dirname(filePath).split(path.sep).pop();
return content.replace(/\]\(([^)]+)\.mdx([^)]*)\)/g, (_, slug, anchor) => {
return content.replace(/\]\(([^)]+)\.md([^)]*)\)/g, (_, slug, anchor) => {
const slugParts = slug.split("/");
const fileName = slugParts[slugParts.length - 1];
const fileGroup = slugParts[slugParts.length - 2] ?? group;
+4 -4
View File
@@ -28,14 +28,14 @@ interface RelativeLinkResult {
* Get all valid documentation routes from the content directory
*/
async function getValidRoutes(): Promise<Set<string>> {
const mdxFiles = await glob("**/*.mdx", { cwd: CONTENT_DIR });
const mdxFiles = await glob("**/*.mdx?", { cwd: CONTENT_DIR });
const routes = new Set<string>();
// Add each MDX file as a valid route
for (const file of mdxFiles) {
// Remove .mdx extension and normalize to route format
let route = file.replace(/\.mdx$/, "");
let route = file.replace(/\.mdx?$/, "");
// Handle index files
if (route.endsWith("/index")) {
@@ -131,7 +131,7 @@ function findRelativeLinksInFile(
* Find relative links in all MDX files
*/
async function findRelativeLinks(): Promise<RelativeLinkResult[]> {
const mdxFiles = await glob("**/*.mdx", { cwd: CONTENT_DIR });
const mdxFiles = await glob("**/*.mdx?", { cwd: CONTENT_DIR });
const results: RelativeLinkResult[] = [];
for (const file of mdxFiles) {
@@ -150,7 +150,7 @@ async function findRelativeLinks(): Promise<RelativeLinkResult[]> {
}
async function validateLinks(): Promise<LinkValidationResult[]> {
const mdxFiles = await glob("**/*.mdx", { cwd: CONTENT_DIR });
const mdxFiles = await glob("**/*.mdx?", { cwd: CONTENT_DIR });
const validRoutes = await getValidRoutes();
const results: LinkValidationResult[] = [];
+6 -7
View File
@@ -1,8 +1,10 @@
import { rehypeCodeDefaultOptions } from "fumadocs-core/mdx-plugins";
import {
rehypeCodeDefaultOptions,
remarkStructure,
} from "fumadocs-core/mdx-plugins";
import { fileGenerator, remarkDocGen, remarkInstall } from "fumadocs-docgen";
import { defineConfig, defineDocs } from "fumadocs-mdx/config";
import { transformerTwoslash } from "fumadocs-twoslash";
import { createFileSystemTypesCache } from "fumadocs-twoslash/cache-fs";
import rehypeKatex from "rehype-katex";
import remarkMath from "remark-math";
@@ -24,11 +26,7 @@ export default defineConfig({
},
transformers: [
...(rehypeCodeDefaultOptions.transformers ?? []),
transformerTwoslash({
typesCache: createFileSystemTypesCache({
dir: ".next/cache/twoslash",
}),
}),
transformerTwoslash(),
{
name: "transformers:remove-notation-escape",
code(hast) {
@@ -49,6 +47,7 @@ export default defineConfig({
],
},
remarkPlugins: [
remarkStructure,
remarkMath,
[remarkInstall, { persist: { id: "package-manager" } }],
[remarkDocGen, { generators: [fileGenerator()] }],
+1 -1
View File
@@ -4,7 +4,7 @@ import { createFromSource } from "fumadocs-core/search/server";
// TODO: migrate to another search service, I don't think Vercel can handle that many of documents.
export const { GET } = createFromSource(source, (page) => ({
id: page.url,
id: page.file.path,
title: page.data.title,
description: page.data.description,
url: page.url,
+1 -19
View File
@@ -1,11 +1,7 @@
import { baseOptions } from "@/app/layout.config";
import { AITrigger } from "@/components/ai-chat";
import { buttonVariants } from "@/components/ui/button";
import { source } from "@/lib/source";
import { cn } from "@/lib/utils";
import "fumadocs-twoslash/twoslash.css";
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import { MessageCircle } from "lucide-react";
import type { ReactNode } from "react";
export default function Layout({ children }: { children: ReactNode }) {
@@ -13,23 +9,9 @@ export default function Layout({ children }: { children: ReactNode }) {
<DocsLayout
tree={source.pageTree}
{...baseOptions}
links={[]}
nav={{
...baseOptions.nav,
children: (
<AITrigger
className={cn(
buttonVariants({
variant: "secondary",
size: "xs",
className:
"text-fd-muted-foreground ms-2 gap-1.5 rounded-full px-2 md:flex-1",
}),
)}
>
<MessageCircle className="size-3" />
Ask LlamaCloud
</AITrigger>
),
}}
>
{children}
+11 -1
View File
@@ -27,9 +27,19 @@ export const baseOptions: BaseLayoutProps = {
githubUrl: "https://github.com/run-llama/LlamaIndexTS",
links: [
{
text: "Docs",
text: "TypeScript",
url: DOCUMENT_URL,
active: "nested-url",
},
{
text: "Python",
url: "https://docs.llamaindex.ai",
active: "url",
},
{
text: "LlamaCloud",
url: "https://docs.cloud.llamaindex.ai/",
active: "url",
},
],
};
+1 -5
View File
@@ -13,11 +13,7 @@ import remarkStringify from "remark-stringify";
export const revalidate = false;
export async function GET() {
const files = await fg([
"./src/content/docs/**/*.mdx",
// remove generated openapi files
"!./src/content/docs/cloud/api/**/*",
]);
const files = await fg(["./src/content/docs/**/*.mdx"]);
const scan = files.map(async (file) => {
const fileContent = await fs.readFile(file);
@@ -1,8 +0,0 @@
---
title: LlamaCloud
description: LlamaCloud is a new generation of managed parsing, ingestion, and retrieval services, designed to bring production-grade context-augmentation to your LLM and RAG applications.
---
This is TypeScript binding for LlamaCloud API. It provides a simple way to interact with LlamaCloud API.
If you are looking for the official documentation, please visit the [Official Document](https://docs.cloud.llamaindex.ai/)
@@ -1,6 +0,0 @@
{
"title": "LlamaCloud",
"description": "The Cloud framework for LLM",
"root": true,
"pages": ["---Guide---", "index", "..."]
}
@@ -112,6 +112,3 @@ The returned `imageDocs` have the alt text assigned as text and the image path a
You can see the full example file [here](https://github.com/run-llama/LlamaIndexTS/blob/main/examples/readers/src/llamaparse-json.ts).
## API Reference
- [LlamaParseReader](/docs/api/classes/LlamaParseReader)
@@ -32,7 +32,7 @@ They can be divided into two groups.
#### Advanced params:
- `resultType` can be set to `markdown`, `text` or `json`. Defaults to `text`. More information about `json` mode on the next pages.
- `language` primarily helps with OCR recognition. Defaults to `en`. Click [here](/docs/api/type-aliases/Language) for a list of supported languages.
- `language` primarily helps with OCR recognition. Defaults to `en`.
- `parsingInstructions?` Optional. Can help with complicated document structures. See this [LlamaIndex Blog Post](https://www.llamaindex.ai/blog/launching-the-first-genai-native-document-parsing-platform) for an example.
- `skipDiagonalText?` Optional. Set to true to ignore diagonal text. (Text that is not rotated 0, 90, 180 or 270 degrees)
- `invalidateCache?` Optional. Set to true to ignore the LlamaCloud cache. All document are kept in cache for 48hours after the job was completed to avoid processing the same document twice. Can be useful for testing when trying to re-parse the same document with, e.g. different `parsingInstructions`.
@@ -61,4 +61,3 @@ Below a full example of `LlamaParse` integrated in `SimpleDirectoryReader` with
## API Reference
- [SimpleDirectoryReader](/docs/api/classes/SimpleDirectoryReader)
- [LlamaParseReader](/docs/api/classes/LlamaParseReader)
@@ -98,5 +98,4 @@ You can assign any other values of the JSON response to the Document as needed.
## API Reference
- [LlamaParseReader](/docs/api/classes/LlamaParseReader)
- [SimpleDirectoryReader](/docs/api/classes/SimpleDirectoryReader)
@@ -22,7 +22,7 @@ npm i @llamaindex/server
## Quick Start
Create index.ts file and add the following code:
Create an `index.ts` file and add the following code:
```ts
import { LlamaIndexServer } from "@llamaindex/server";
@@ -43,20 +43,20 @@ new LlamaIndexServer({
In the same directory as `index.ts`, run the following command to start the server:
```bash
tsx index.ts
```
```bash
tsx index.ts
```
The server will start at `http://localhost:3000`
You can also make a request to the server:
```bash
curl -X POST "http://localhost:3000/api/chat" -H "Content-Type: application/json" -d '{"message": "Who is the first president of the United States?"}'
```
```bash
curl -X POST "http://localhost:3000/api/chat" -H "Content-Type: application/json" -d '{"message": "Who is the first president of the United States?"}'
```
## Configuration Options
The LlamaIndexServer accepts the following configuration
The `LlamaIndexServer` accepts the following configuration options:
- `workflow`: A callable function that creates a workflow instance for each request
- `uiConfig`: An object to configure the chat UI containing the following properties:
@@ -68,6 +68,72 @@ The LlamaIndexServer accepts the following configuration
LlamaIndexServer accepts all the configuration options from Nextjs Custom Server such as `port`, `hostname`, `dev`, etc.
See all Nextjs Custom Server options [here](https://nextjs.org/docs/app/building-your-application/configuring/custom-server).
## AI-generated UI Components
The LlamaIndex server provides support for rendering workflow events using custom UI components, allowing you to extend and customize the chat interface.
These components can be auto-generated using an LLM by providing a JSON schema of the workflow event.
### UI Event Schema
To display custom UI components, your workflow needs to emit UI events that have an event type for identification and a data object:
```typescript
class UIEvent extends WorkflowEvent<{
type: "ui_event";
data: UIEventData;
}> {}
```
The `data` object can be any JSON object. To enable AI generation of the UI component, you need to provide a schema for that data (here we're using Zod):
```typescript
const MyEventDataSchema = z.object({
stage: z.enum(["retrieve", "analyze", "answer"]).describe("The current stage the workflow process is in."),
progress: z.number().min(0).max(1).describe("The progress in percent of the current stage"),
}).describe("WorkflowStageProgress");
type UIEventData = z.infer<typeof MyEventDataSchema>;
```
### Generate UI Components
The `generateEventComponent` function uses an LLM to generate a custom UI component based on the JSON schema of a workflow event. The schema should contain accurate descriptions of each field so that the LLM can generate matching components for your use case. We've done this for you in the example above using the `describe` function from Zod:
```typescript
import { OpenAI } from "llamaindex";
import { generateEventComponent } from "@llamaindex/server";
import { MyEventDataSchema } from "./your-workflow";
// Also works well with Claude 3.5 Sonnet and Google Gemini 2.5 Pro
const llm = new OpenAI({ model: "gpt-4.1" });
const code = generateEventComponent(MyEventDataSchema, llm);
```
After generating the code, we need to save it to a file. The file name must match the event type from your workflow (e.g., `ui_event.jsx` for handling events with `ui_event` type):
```ts
fs.writeFileSync("components/ui_event.jsx", code);
```
Feel free to modify the generated code to match your needs. If you're not satisfied with the generated code, we suggest improving the provided JSON schema first or trying another LLM.
> Note that `generateEventComponent` is generating JSX code, but you can also provide a TSX file.
### Server Setup
To use the generated UI components, you need to initialize the LlamaIndex server with the `componentsDir` that contains your custom UI components:
```ts
new LlamaIndexServer({
workflow: createWorkflow,
uiConfig: {
appTitle: "LlamaIndex App",
componentsDir: "components",
},
}).start();
```
## Default Endpoints and Features
### Chat Endpoint
@@ -85,69 +151,19 @@ The server always provides a chat interface at the root path (`/`) with:
### Static File Serving
- The server automatically mounts the `data` and `output` folders at `{server_url}{api_prefix}/files/data` (default: `/api/files/data`) and `{server_url}{api_prefix}/files/output` (default: `/api/files/output`) respectively.
- Your workflows can use both folders to store and access files. As a convention, the `data` folder is used for documents that are ingested and the `output` folder is used for documents that are generated by the workflow.
- Your workflows can use both folders to store and access files. By convention, the `data` folder is used for documents that are ingested, and the `output` folder is used for documents generated by the workflow.
## Custom UI Components
The LlamaIndex server provides support for rendering workflow events using custom UI components, allowing you to extend and customize the chat interface.
### Overview
Custom UI components are a powerful feature that enables you to:
- Add custom interface elements to the chat UI using React JSX or TSX files
- Extend the default chat interface functionality
- Create specialized visualizations or interactions
### Configuration
Your workflow must emit events that fit this structure, allowing the LlamaIndex server to display the right UI components based on the event type.
```json
{
"type": "<event_name>",
"data": <data model>
}
```
### Server Setup
1. Initialize the LlamaIndex server with a component directory:
```ts
new LlamaIndexServer({
workflow: createWorkflow,
uiConfig: {
appTitle: "LlamaIndex App",
componentsDir: "components",
},
}).start();
```
2. Add the custom component code to the directory following the naming pattern:
- File Extension: `.jsx` and `.tsx` for React components
- File Name: Should match the event type from your workflow (e.g., `deep_research_event.jsx` for handling `deep_research_event` type that you defined in your workflow). If there are TSX and JSX files with the same name, the TSX file will be used.
- Component Name: Export a default React component named `Component` that receives props from the event data
Example component structure:
```jsx
function Component({ events }) {
// Your component logic here
return (
// Your UI code here
);
}
```
## Best Practices
1. Always provide a workflow factory that creates fresh workflow instances
2. Use environment variables for sensitive configuration
3. Use starter questions to guide users in the chat UI
1. Always provide a workflow factory that creates a fresh workflow instance for each request.
2. Use environment variables for sensitive configuration (e.g., API keys).
3. Use starter questions to guide users in the chat UI.
## Getting Started with a New Project
Want to start a new project with LlamaIndexServer? Check out our [create-llama](https://github.com/run-llama/create-llama) tool to quickly generate a new project with LlamaIndexServer.
Want to start a new project with LlamaIndexServer? Check out our [create-llama](https://github.com/run-llama/create-llama) tool to quickly generate a new project with LlamaIndexServer.
## API Reference
- [LlamaIndexServer](/docs/api/classes/LlamaIndexServer)
@@ -58,25 +58,9 @@ We will convert our text into embeddings using the `VectorStoreIndex` class thro
const index = await VectorStoreIndex.fromDocuments(documents);
```
### Configure a retriever
Before LlamaIndex can send a query to the LLM, it needs to find the most relevant chunks to send. That's the purpose of a `Retriever`. We're going to get `VectorStoreIndex` to act as a retriever for us
```javascript
const retriever = await index.asRetriever();
```
### Configure how many documents to retrieve
By default LlamaIndex will retrieve just the 2 most relevant chunks of text. This document is complex though, so we'll ask for more context.
```javascript
retriever.similarityTopK = 10;
```
### Use index.queryTool
`index.queryTool` creates a `QueryEngineTool` that can be used be an agent to query data from the index.
`index.queryTool` creates a `QueryEngineTool` that can be used be an agent to query data from the index:
```javascript
const tools = [
@@ -85,9 +69,17 @@ const tools = [
name: "san_francisco_budget_tool",
description: `This tool can answer detailed questions about the individual components of the budget of San Francisco in 2023-2024.`,
},
options: { similarityTopK: 10 },
}),
];
```
The `metadata` that we're setting helps the agent to decide when to use the tool.
Note that by default LlamaIndex will retrieve just the 2 most relevant chunks of text. This document is complex though, so we'll ask for more context by setting `similarityTopK` to 10.
Now, we can create an agent using the `QueryEngineTool`:
```javascript
// Create an agent using the tools array
const ragAgent = agent({ tools });
@@ -12,6 +12,7 @@ const tools = [
name: "san_francisco_budget_tool",
description: `This tool can answer detailed questions about the individual components of the budget of San Francisco in 2023-2024.`,
},
options: { similarityTopK: 10 },
}),
tool({
name: "sumNumbers",
@@ -4,7 +4,7 @@
"basic_agent",
"rag",
"agents",
"workflow",
"../../llamaflow",
"local_llm",
"chatbot",
"structured_data_extraction"
@@ -1,224 +0,0 @@
---
title: Inputs / Outputs
description: Learn how to use different inputs and outputs in your workflows.
---
Inputs and outputs are the way to communicate between steps in a workflow. In the previous example,
we used `StartEvent` and `StopEvent` to communicate between steps. However, you can use any type of event to communicate between steps.
## Multiple inputs
You can define multiple inputs for a step.
In the following example, we define a complex workflow with multiple inputs and outputs.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
```
First, let's define the events that we will use in the workflow.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
const aEvent = await context.requireEvent(AEvent);
const bEvent = await context.requireEvent(BEvent);
const a = aEvent.data;
const b = bEvent.data;
return new StopEvent(`Hello, ${input}! A: ${a}, B: ${b}`);
});
// ---cut---
workflow.addStep({
inputs: [AEvent, BEvent],
outputs: [ResultEvent]
}, async (
context,
aEvent,
bEvent
) => {
const a = aEvent.data;
const b = bEvent.data;
return new ResultEvent(`A: ${a}, B: ${b}`);
});
```
This step means that it requires two events: `AEvent` and `BEvent`. It will return a `ResultEvent` with the data `A: ${a}, B: ${b}`.
## A or B input
If we want to have a step that can accept either `AEvent` or `BEvent`, we can define the step like this:
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
const aEvent = await context.requireEvent(AEvent);
const bEvent = await context.requireEvent(BEvent);
const a = aEvent.data;
const b = bEvent.data;
return new StopEvent(`Hello, ${input}! A: ${a}, B: ${b}`);
});
// ---cut---
workflow.addStep({
inputs: [WorkflowEvent.or(AEvent, BEvent)],
outputs: [ResultEvent]
}, async (
context,
aOrBEvent
) => {
if (aOrBEvent instanceof AEvent) {
// ^?
const a = aOrBEvent.data;
// ^?
return new ResultEvent(`A: ${a}`);
} else {
const b = aOrBEvent.data;
// ^?
return new ResultEvent(`B: ${b}`);
}
});
```
This step means that it requires either `AEvent` or `BEvent`. It will return a `ResultEvent` with the data `A: ${a}` or `B: ${b}`.
You can still combine the logic with `context.requireEvent` to get the data from the event.
<Accordions>
<Accordion title="Under the hood">
We use JavaScript Inheritance and the prototype chain to implement the `or` logic.
The `or` method creates a new class that extends the two classes that you pass to it.
<a
target="_blank"
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain"
>
MDN - Inheritance and the prototype chain
</a>
</Accordion>
</Accordions>
## Multiple outputs
You can define multiple outputs for a step.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
class AEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
class BEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ResultEvent extends WorkflowEvent<string> {
constructor(data: string) {
super(data);
}
}
const workflow = new Workflow<never, string, string>();
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [AEvent, BEvent]
}, async (
context,
startEvent
) => {
const input = startEvent.data;
if (Math.random() > 0.5) {
return new AEvent(`Hello, ${input}!`);
} else {
return new BEvent(42);
}
});
```
This step will return either an `AEvent` or a `BEvent` based on a random number.
@@ -1,196 +0,0 @@
---
title: Basic Usage
description: Learn how to use the LlamaIndex workflow.
---
A `Workflow` in LlamaIndex.TS is an event-driven abstraction used to chain together several events.
Workflows are made up of steps, with each step responsible for handling certain event types and emitting new events.
Workflows are designed for any cases that benefit from event-driven programming, not only for LLM and AI tasks.
```package-install
npm i @llamaindex/workflow
```
## Start from scratch
Let's start from a Hello World workflow.
```ts twoslash
import { Workflow } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
// ---cut---
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ^?
```
First, we define a workflow with 3 generic types: `ContextData`, `Input`, and `Output`.
In general, `ContextData` is used to store the shared data between steps, `Input` is the type of the input event, and `Output` is the type of the output event.
In you code logic, you should **share state between steps via `ContextData`**.
```ts twoslash
import { Workflow, StartEvent, StopEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.data.counter++;
return new StopEvent(`Hello, ${input}!`);
});
```
In the workflow, we add a step that listens to `StartEvent<string>` and emits `StopEvent<string>`.
The step is an async function that takes two arguments: `context` and `event`.
### `context` type
<AutoTypeTable path="./src/deps/type.ts" name="HandlerContext" />
There are two more properties in `HandlerContext`:
- `sendEvent`: invoke another event in the workflow, other than `StartEvent`, `StopEvent`, or the current event. (Or there will have circular reference)
- `requireEvent`: wait for a specific event to be emitted.
You can use `sendEvent` and `requireEvent` to build complex workflows.
```ts twoslash
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
// ---cut---
class AnalysisStartEvent extends WorkflowEvent<string> {}
class AnalysisStopEvent extends WorkflowEvent<boolean> {}
workflow.addStep({
inputs: [AnalysisStartEvent],
outputs: [AnalysisStopEvent]
}, async (...args) => {
// do some analysis
return new AnalysisStopEvent(true);
})
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.sendEvent(new AnalysisStartEvent('start'));
context.data.counter++;
const { data } = await context.requireEvent(AnalysisStopEvent);
return new StopEvent(`Hello, ${input}! Analysis result: ${data ? 'success' : 'fail'}`);
});
```
For example, you can compile `requireEvent` with `waitUntil` in [Vercel Functions](https://vercel.com/docs/functions/functions-api-reference#waituntil) or [Cloudflare Worker](https://developers.cloudflare.com/workers/runtime-apis/context/#waituntil)
```ts twoslash
import { waitUntil } from '@vercel/functions';
import { Workflow, StartEvent, StopEvent, WorkflowEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
class AnalysisStartEvent extends WorkflowEvent<string> {}
class AnalysisStopEvent extends WorkflowEvent<boolean> {}
// ---cut---
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.sendEvent(new AnalysisStartEvent('start'));
context.data.counter++;
waitUntil(context.requireEvent(AnalysisStopEvent));
// note that `waitUntil` is not a promise, it will extend the lifetime of the workflow
// you can wait for some background tasks to finish
return new StopEvent(`Hello, ${input}!`);
});
```
## Multiple runs
You can run the same workflow multiple times with different inputs.
```ts twoslash
import { Workflow, StartEvent, StopEvent } from '@llamaindex/workflow';
type ContextData = {
counter: number;
}
const contextData: ContextData = { counter: 0 };
const workflow = new Workflow<ContextData, string, string>();
workflow.addStep({
inputs: [StartEvent<string>],
outputs: [StopEvent<string>]
}, async (context, startEvent) => {
const input = startEvent.data;
context.data.counter++;
return new StopEvent(`Hello, ${input}!`);
});
// ---cut---
{
const ret = await workflow.run('Alex', contextData);
console.log(ret.data); // Hello, Alex!
}
{
const ret = await workflow.run('World', contextData);
console.log(ret.data); // Hello, World!
}
```
Context is shared between runs, so the counter will be increased.
Ideally, it should be serializable to make sure it can be recovered from HTTP requests or other storage.
### Full example
<iframe
className="w-full h-[440px]"
aria-label="Workflow example"
src="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=node/workflow/basic.ts"
/>
## `Workflow` type
<AutoTypeTable path="./src/deps/type.ts" name="Workflow" />
## `WorkflowContext` type
<AutoTypeTable path="./src/deps/type.ts" name="WorkflowContext" />
@@ -1,6 +0,0 @@
{
"title": "Workflow",
"description": "See how to use @llamaindex/workflow",
"defaultOpen": false,
"pages": ["index", "different-inputs-outputs", "streaming"]
}
@@ -1,198 +0,0 @@
---
title: Streaming
description: Learn how to use the LlamaIndex workflow with streaming.
---
`Workflow` API by default is designed for streaming data. In this guide, we will show you how to use the `Workflow` API with streaming data.
Each `workflow.run` call returns `WorkflowContext`, which implements `AsyncIterable` interface. You can use it to stream data.
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
workflow.addStep({
inputs: [StartEvent<number>],
outputs: [StopEvent<number>]
}, async (context, startEvent) => {
const total = startEvent.data;
for (let i = 0; i < total; i++) {
context.sendEvent(new ComputeEvent(i));
}
const computeResults = await Promise.all(Array.from({ length: total }).map(() => context.requireEvent(ComputeResultEvent)));
// Workflow API allows you to start events in parallel and wait for all of them to finish
context.data.sum = computeResults.reduce((acc, curr) => acc + curr.data, 0);
return new StopEvent(context.data.sum);
});
```
We define a parallel computation workflow that computes the sum of numbers from 0 to `total`.
The workflow sends `ComputeEvent` events for each number and waits for `ComputeResultEvent` events. After receiving all `ComputeResultEvent` events, the workflow returns the sum as a `StopEvent`.
What if we want cutoff if the sum exceeds a certain value?
## Streaming
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
import { StopCircle } from 'lucide-react';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
// ---cut---
const context = workflow.run(1000, {
sum: 0
});
for await (const event of context) {
if (event instanceof ComputeEvent) {
if (context.data.sum > 100) {
throw new Error('Sum exceeds 100');
}
}
if (event instanceof StopEvent) {
console.log('result', event.data);
}
}
```
You can define more custom logic using `AsyncIterable` interface.
For example. I just want to stop the workflow if I get a `ComputeResultEvent`
```ts twoslash
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
import { StopCircle } from 'lucide-react';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
// ---cut---
async function compute() {
const context = workflow.run(1000, {
sum: 0
});
for await (const event of context) {
if (event instanceof ComputeResultEvent) {
return event.data;
}
}
throw new Error('UNREACHABLE');
}
const result = await compute();
```
### Streaming with UI
You can use the `Workflow` API with UI libraries like React.
```tsx twoslash
// @filename: utils.ts
export async function runWithoutBlocking(fn: () => Promise<void>) {
fn();
}
// @filename: action.ts
// ---cut---
'use server';
// "use server" is required to enable server side feature in React
import { createStreamableUI } from 'ai/rsc';
import { runWithoutBlocking } from './utils';
// ---cut-start---
import { Workflow, WorkflowEvent, StartEvent, StopEvent } from '@llamaindex/workflow';
class ComputeEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
class ComputeResultEvent extends WorkflowEvent<number> {
constructor(data: number) {
super(data);
}
}
type ContextData = {
sum: number;
}
const workflow = new Workflow<ContextData, number, number>();
const min = 100;
const max = 1000;
workflow.addStep(
{
inputs: [ComputeEvent],
outputs: [ComputeResultEvent]
},
async (context, event) => {
await new Promise((resolve) =>
setTimeout(resolve, Math.floor(Math.random() * (max - min + 1) + min))
);
return new ComputeResultEvent(event.data);
}
);
// ---cut-end---
export async function compute() {
'use server';
const ui = createStreamableUI();
const context = workflow.run(100, {
sum: 0
});
runWithoutBlocking(async () => {
for await (const event of context) {
if (event instanceof ComputeResultEvent) {
// Update UI
} else if (event instanceof StopEvent) {
// Update UI
}
// ...
}
});
return ui.value;
}
```
<WorkflowStreamingDemo />
+1 -1
View File
@@ -1,3 +1,3 @@
{
"pages": ["llamaindex", "llamaflow", "cloud", "api"]
"pages": ["llamaindex", "api"]
}
+9 -2
View File
@@ -3,12 +3,19 @@
"extends": ["//"],
"tasks": {
"build": {
"inputs": [
"node_modules/@llama-flow/docs/**",
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.mdx",
"src/**/*.md"
],
"outputs": [
".next",
".source",
"next-env.d.ts",
"src/content/docs/cloud/api/**",
"src/content/docs/api/**"
"src/content/docs/api/**",
"tsconfig.json"
],
"env": [
"LLAMA_CLOUD_API_KEY",
+2 -4
View File
@@ -2,12 +2,10 @@
"plugin": ["typedoc-plugin-markdown", "typedoc-plugin-merge-modules"],
"entryPoints": [
"../../packages/{,**/}index.ts",
"../../packages/readers/src/*.ts",
"../../packages/cloud/src/{reader,utils}.ts"
"../../packages/readers/src/*.ts"
],
"exclude": [
"../../packages/autotool/**/src/index.ts",
"../../packages/cloud/src/client/index.ts",
"**/node_modules/**",
"**/dist/**",
"**/test/**",
@@ -22,7 +20,7 @@
"categoryOrder": ["Classes", "Enums", "Functions", "Interfaces", "Types"],
"sort": ["source-order"],
"entryFileName": "index.md",
"fileExtension": ".mdx",
"fileExtension": ".md",
"hidePageTitle": true,
"hidePageHeader": true,
"hideGroupHeadings": true,
@@ -1,5 +1,11 @@
# @llamaindex/cloudflare-worker-agent-test
## 0.0.156
### Patch Changes
- llamaindex@0.10.2
## 0.0.155
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/cloudflare-worker-agent-test",
"version": "0.0.155",
"version": "0.0.156",
"type": "module",
"private": true,
"scripts": {
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/next-agent-test
## 0.1.156
### Patch Changes
- llamaindex@0.10.2
## 0.1.155
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-agent-test",
"version": "0.1.155",
"version": "0.1.156",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,11 @@
# test-edge-runtime
## 0.1.155
### Patch Changes
- llamaindex@0.10.2
## 0.1.154
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/nextjs-edge-runtime-test",
"version": "0.1.154",
"version": "0.1.155",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,12 @@
# @llamaindex/next-node-runtime
## 0.1.22
### Patch Changes
- llamaindex@0.10.2
- @llamaindex/huggingface@0.1.6
## 0.1.21
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/next-node-runtime-test",
"version": "0.1.21",
"version": "0.1.22",
"private": true,
"scripts": {
"dev": "next dev",
@@ -1,5 +1,11 @@
# vite-import-llamaindex
## 0.0.22
### Patch Changes
- llamaindex@0.10.2
## 0.0.21
### Patch Changes
@@ -1,7 +1,7 @@
{
"name": "vite-import-llamaindex",
"private": true,
"version": "0.0.21",
"version": "0.0.22",
"type": "module",
"scripts": {
"build": "vite build",
@@ -1,5 +1,11 @@
# @llamaindex/waku-query-engine-test
## 0.0.156
### Patch Changes
- llamaindex@0.10.2
## 0.0.155
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/waku-query-engine-test",
"version": "0.0.155",
"version": "0.0.156",
"type": "module",
"private": true,
"scripts": {
+20
View File
@@ -1,5 +1,25 @@
# examples
## 0.3.9
### Patch Changes
- Updated dependencies [96dac4d]
- Updated dependencies [e5c3f95]
- @llamaindex/google@0.2.4
- @llamaindex/openai@0.3.4
- llamaindex@0.10.2
- @llamaindex/clip@0.0.52
- @llamaindex/deepinfra@0.0.52
- @llamaindex/deepseek@0.0.12
- @llamaindex/fireworks@0.0.12
- @llamaindex/groq@0.0.67
- @llamaindex/huggingface@0.1.6
- @llamaindex/jinaai@0.0.12
- @llamaindex/perplexity@0.0.9
- @llamaindex/together@0.0.12
- @llamaindex/vllm@0.0.38
## 0.3.8
### Patch Changes
+14 -14
View File
@@ -1,6 +1,6 @@
{
"name": "@llamaindex/examples",
"version": "0.3.8",
"version": "0.3.9",
"private": true,
"scripts": {
"lint": "eslint .",
@@ -15,16 +15,16 @@
"@llamaindex/astra": "^0.0.16",
"@llamaindex/azure": "^0.1.11",
"@llamaindex/chroma": "^0.0.16",
"@llamaindex/clip": "^0.0.51",
"@llamaindex/clip": "^0.0.52",
"@llamaindex/cloud": "^4.0.3",
"@llamaindex/cohere": "^0.0.16",
"@llamaindex/core": "^0.6.2",
"@llamaindex/deepinfra": "^0.0.51",
"@llamaindex/deepinfra": "^0.0.52",
"@llamaindex/env": "^0.1.29",
"@llamaindex/firestore": "^1.0.9",
"@llamaindex/google": "^0.2.3",
"@llamaindex/groq": "^0.0.66",
"@llamaindex/huggingface": "^0.1.5",
"@llamaindex/google": "^0.2.4",
"@llamaindex/groq": "^0.0.67",
"@llamaindex/huggingface": "^0.1.6",
"@llamaindex/milvus": "^0.1.11",
"@llamaindex/mistral": "^0.1.2",
"@llamaindex/mixedbread": "^0.0.16",
@@ -32,7 +32,7 @@
"@llamaindex/elastic-search": "^0.1.2",
"@llamaindex/node-parser": "^2.0.2",
"@llamaindex/ollama": "^0.1.2",
"@llamaindex/openai": "^0.3.3",
"@llamaindex/openai": "^0.3.4",
"@llamaindex/pinecone": "^0.1.2",
"@llamaindex/portkey-ai": "^0.0.44",
"@llamaindex/postgres": "^0.0.45",
@@ -41,15 +41,15 @@
"@llamaindex/replicate": "^0.0.44",
"@llamaindex/upstash": "^0.0.16",
"@llamaindex/vercel": "^0.1.2",
"@llamaindex/vllm": "^0.0.37",
"@llamaindex/vllm": "^0.0.38",
"@llamaindex/voyage-ai": "^1.0.8",
"@llamaindex/weaviate": "^0.0.16",
"@llamaindex/workflow": "^1.0.3",
"@llamaindex/deepseek": "^0.0.11",
"@llamaindex/fireworks": "^0.0.11",
"@llamaindex/together": "^0.0.11",
"@llamaindex/jinaai": "^0.0.11",
"@llamaindex/perplexity": "^0.0.8",
"@llamaindex/deepseek": "^0.0.12",
"@llamaindex/fireworks": "^0.0.12",
"@llamaindex/together": "^0.0.12",
"@llamaindex/jinaai": "^0.0.12",
"@llamaindex/perplexity": "^0.0.9",
"@llamaindex/supabase": "^0.1.1",
"@llamaindex/tools": "^0.0.5",
"@notionhq/client": "^2.2.15",
@@ -60,7 +60,7 @@
"commander": "^12.1.0",
"dotenv": "^16.4.5",
"js-tiktoken": "^1.0.14",
"llamaindex": "^0.10.1",
"llamaindex": "^0.10.2",
"mongodb": "6.7.0",
"postgres": "^3.4.4",
"wikipedia": "^2.1.2",
+3 -4
View File
@@ -21,12 +21,14 @@
},
"devDependencies": {
"@changesets/cli": "^2.27.5",
"@eslint/js": "^9.25.0",
"bunchee": "6.4.0",
"eslint": "9.22.0",
"eslint-config-next": "^15.1.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^2.3.3",
"eslint-plugin-react": "7.37.2",
"eslint-plugin-turbo": "^2.5.0",
"globals": "^15.12.0",
"husky": "^9.1.7",
"lint-staged": "^15.2.11",
@@ -39,7 +41,7 @@
"typescript-eslint": "^8.18.0",
"vitest": "^3.1.1"
},
"packageManager": "pnpm@9.12.3",
"packageManager": "pnpm@10.8.1",
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
@@ -48,8 +50,5 @@
"*.{json,md,yml}": [
"prettier --write"
]
},
"dependencies": {
"p-retry": "^6.2.1"
}
}
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/autotool
## 7.0.2
### Patch Changes
- llamaindex@0.10.2
## 7.0.1
### Patch Changes
@@ -1,5 +1,12 @@
# @llamaindex/autotool-01-node-example
## 0.0.103
### Patch Changes
- llamaindex@0.10.2
- @llamaindex/autotool@7.0.2
## 0.0.102
### Patch Changes
@@ -13,5 +13,5 @@
"scripts": {
"start": "node --import tsx --import @llamaindex/autotool/node ./src/index.ts"
},
"version": "0.0.102"
"version": "0.0.103"
}
+1 -1
View File
@@ -6,7 +6,7 @@
"url": "git+https://github.com/run-llama/LlamaIndexTS.git",
"directory": "packages/autotool"
},
"version": "7.0.1",
"version": "7.0.2",
"description": "auto transpile your JS function to LLM Agent compatible",
"files": [
"dist",
+3
View File
@@ -63,5 +63,8 @@
"peerDependencies": {
"@llamaindex/core": "workspace:*",
"@llamaindex/env": "workspace:*"
},
"dependencies": {
"p-retry": "^6.2.1"
}
}
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/experimental
## 0.0.172
### Patch Changes
- llamaindex@0.10.2
## 0.0.171
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/experimental",
"description": "Experimental package for LlamaIndexTS",
"version": "0.0.171",
"version": "0.0.172",
"type": "module",
"types": "dist/type/index.d.ts",
"main": "dist/cjs/index.js",
+7
View File
@@ -1,5 +1,12 @@
# llamaindex
## 0.10.2
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.10.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "llamaindex",
"version": "0.10.1",
"version": "0.10.2",
"license": "MIT",
"type": "module",
"keywords": [
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/clip
## 0.0.52
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.51
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/clip",
"description": "Clip Embedding Adapter for LlamaIndex",
"version": "0.0.51",
"version": "0.0.52",
"type": "module",
"types": "dist/index.d.ts",
"main": "dist/index.cjs",
@@ -1,5 +1,12 @@
# @llamaindex/deepinfra
## 0.0.52
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.51
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/deepinfra",
"description": "Deepinfra Adapter for LlamaIndex",
"version": "0.0.51",
"version": "0.0.52",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/deepseek
## 0.0.12
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.11
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/deepseek",
"description": "DeepSeek Adapter for LlamaIndex",
"version": "0.0.11",
"version": "0.0.12",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -1,5 +1,12 @@
# @llamaindex/fireworks
## 0.0.12
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.11
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/fireworks",
"description": "Fireworks Adapter for LlamaIndex",
"version": "0.0.11",
"version": "0.0.12",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/google
## 0.2.4
### Patch Changes
- 96dac4d: Add Gemini 2.5 Flash Preview
## 0.2.3
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/google",
"description": "Google Adapter for LlamaIndex",
"version": "0.2.3",
"version": "0.2.4",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+2
View File
@@ -62,6 +62,7 @@ export const GEMINI_MODEL_INFO_MAP: Record<GEMINI_MODEL, GeminiModelInfo> = {
[GEMINI_MODEL.GEMINI_2_0_FLASH_THINKING_EXP]: { contextWindow: 32768 },
[GEMINI_MODEL.GEMINI_2_0_PRO_EXPERIMENTAL]: { contextWindow: 2 * 10 ** 6 },
[GEMINI_MODEL.GEMINI_2_5_PRO_PREVIEW]: { contextWindow: 10 ** 6 },
[GEMINI_MODEL.GEMINI_2_5_FLASH_PREVIEW]: { contextWindow: 10 ** 6 },
};
export const SUPPORT_TOOL_CALL_MODELS: GEMINI_MODEL[] = [
@@ -79,6 +80,7 @@ export const SUPPORT_TOOL_CALL_MODELS: GEMINI_MODEL[] = [
GEMINI_MODEL.GEMINI_2_0_FLASH,
GEMINI_MODEL.GEMINI_2_0_PRO_EXPERIMENTAL,
GEMINI_MODEL.GEMINI_2_5_PRO_PREVIEW,
GEMINI_MODEL.GEMINI_2_5_FLASH_PREVIEW,
];
export const DEFAULT_GEMINI_PARAMS = {
+1
View File
@@ -74,6 +74,7 @@ export enum GEMINI_MODEL {
GEMINI_2_0_FLASH_THINKING_EXP = "gemini-2.0-flash-thinking-exp-01-21",
GEMINI_2_0_PRO_EXPERIMENTAL = "gemini-2.0-pro-exp-02-05",
GEMINI_2_5_PRO_PREVIEW = "gemini-2.5-pro-preview-03-25",
GEMINI_2_5_FLASH_PREVIEW = "gemini-2.5-flash-preview-04-17",
}
export interface GeminiModelInfo {
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/groq
## 0.0.67
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.66
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/groq",
"description": "Groq Adapter for LlamaIndex",
"version": "0.0.66",
"version": "0.0.67",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -1,5 +1,12 @@
# @llamaindex/huggingface
## 0.1.6
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.1.5
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/huggingface",
"description": "Huggingface Adapter for LlamaIndex",
"version": "0.1.5",
"version": "0.1.6",
"type": "module",
"types": "dist/index.d.ts",
"main": "dist/index.cjs",
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/jinaai
## 0.0.12
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.11
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/jinaai",
"description": "JinaAI Adapter for LlamaIndex",
"version": "0.0.11",
"version": "0.0.12",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+6
View File
@@ -1,5 +1,11 @@
# @llamaindex/openai
## 0.3.4
### Patch Changes
- e5c3f95: Update o4-mini to accept reasoning parameters and exclude temperature
## 0.3.3
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/openai",
"description": "OpenAI Adapter for LlamaIndex",
"version": "0.3.3",
"version": "0.3.4",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+3 -2
View File
@@ -149,11 +149,12 @@ export function isFunctionCallingModel(llm: LLM): llm is OpenAI {
export function isReasoningModel(model: ChatModel | string): boolean {
const isO1 = model.startsWith("o1");
const isO3 = model.startsWith("o3");
return isO1 || isO3;
const isO4 = model.startsWith("o4");
return isO1 || isO3 || isO4;
}
export function isTemperatureSupported(model: ChatModel | string): boolean {
return !model.startsWith("o3");
return !model.startsWith("o3") && !model.startsWith("o4");
}
export type OpenAIAdditionalMetadata = object;
@@ -1,5 +1,12 @@
# @llamaindex/perplexity
## 0.0.9
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.8
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/perplexity",
"description": "Perplexity Adapter for LlamaIndex",
"version": "0.0.8",
"version": "0.0.9",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/together
## 0.0.12
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.11
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/together",
"description": "Together Adapter for LlamaIndex",
"version": "0.0.11",
"version": "0.0.12",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+7
View File
@@ -1,5 +1,12 @@
# @llamaindex/vllm
## 0.0.38
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
## 0.0.37
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/vllm",
"description": "vLLM Adapter for LlamaIndex",
"version": "0.0.37",
"version": "0.0.38",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/server
## 0.1.5
### Patch Changes
- 7ca9ddf: Add generate ui workflow to @llamaindex/server
- 3310eaa: chore: bump chat-ui
- llamaindex@0.10.2
## 0.1.4
### Patch Changes
@@ -4,9 +4,10 @@ import { ChatSection as ChatSectionUI } from "@llamaindex/chat-ui";
import "@llamaindex/chat-ui/styles/markdown.css";
import "@llamaindex/chat-ui/styles/pdf.css";
import { useChat } from "ai/react";
import { Sparkles, Star } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import Header from "./header";
import { RenderingErrors } from "./rendering-errors";
import { Button } from "./ui/button";
import CustomChatInput from "./ui/chat/chat-input";
import CustomChatMessages from "./ui/chat/chat-messages";
import { fetchComponentDefinitions } from "./ui/chat/custom/events/loader";
@@ -51,20 +52,66 @@ export default function ChatSection() {
experimental_throttle: 100,
});
return (
<div className="flex h-[85vh] w-full flex-col gap-2">
<Header />
<RenderingErrors
uniqueErrors={uniqueErrors}
clearErrors={() => setErrors([])}
/>
<ChatSectionUI handler={handler} className="min-h-0 w-full flex-1">
<CustomChatMessages
componentDefs={componentDefs}
appendError={appendError}
/>
<CustomChatInput />
</ChatSectionUI>
<>
<div className="grid h-screen w-screen grid-cols-4 gap-4 overflow-hidden">
<div className="col-span-1">
<div className="flex flex-col gap-8 p-2 pl-4">
<div className="flex items-center gap-2">
<Sparkles className="size-4" />
<h1 className="font-semibold">{getConfig("APP_TITLE")}</h1>
</div>
<RenderingErrors
uniqueErrors={uniqueErrors}
clearErrors={() => setErrors([])}
/>
</div>
</div>
<div className="col-span-2 h-full min-h-0">
<ChatSectionUI handler={handler} className="p-0">
<CustomChatMessages
componentDefs={componentDefs}
appendError={appendError}
/>
<CustomChatInput />
</ChatSectionUI>
</div>
<div className="col-span-1">
<LlamaIndexLinks />
</div>
</div>
<TailwindCDNInjection />
</>
);
}
function LlamaIndexLinks() {
return (
<div className="flex items-center justify-end gap-4 p-2 pr-4">
<div className="flex items-center gap-2">
<a
href="https://www.llamaindex.ai/"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200"
>
Built by LlamaIndex
</a>
<img
className="h-[24px] w-[24px] rounded-sm"
src="/llama.png"
alt="Llama Logo"
/>
</div>
<a
href="https://github.com/run-llama/LlamaIndexTS"
target="_blank"
rel="noopener noreferrer"
>
<Button variant="outline" size="sm">
<Star className="mr-2 size-4" />
Star on GitHub
</Button>
</a>
</div>
);
}
@@ -1,28 +0,0 @@
"use client";
import { getConfig } from "./ui/lib/utils";
export default function Header() {
return (
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm">
<div className="flex w-full flex-col items-center pb-2 text-center">
<h1 className="mb-2 text-4xl font-bold">{getConfig("APP_TITLE")}</h1>
<div className="flex items-center justify-center gap-2">
<a
href="https://www.llamaindex.ai/"
target="_blank"
rel="noopener noreferrer"
className="text-sm text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200"
>
Built by LlamaIndex
</a>
<img
className="h-[24px] w-[24px] rounded-sm"
src="/llama.png"
alt="Llama Logo"
/>
</div>
</div>
</div>
);
}
@@ -1,25 +1,15 @@
"use client";
import { useChatMessage } from "@llamaindex/chat-ui";
import { User2 } from "lucide-react";
import { ChatMessage } from "@llamaindex/chat-ui";
export function ChatMessageAvatar() {
const { message } = useChatMessage();
if (message.role === "user") {
return (
<div className="bg-background flex h-8 w-8 shrink-0 select-none items-center justify-center rounded-md border shadow-sm">
<User2 className="h-4 w-4" />
</div>
);
}
return (
<div className="flex h-8 w-8 shrink-0 select-none items-center justify-center rounded-md border bg-black text-white shadow-sm">
<ChatMessage.Avatar>
<img
className="h-[40px] w-[40px] rounded-xl object-contain"
className="border-1 rounded-full border-[#e711dd]"
src="/llama.png"
alt="Llama Logo"
/>
</div>
</ChatMessage.Avatar>
);
}
@@ -45,30 +45,24 @@ export default function CustomChatInput() {
const annotations = getAnnotations();
return (
<ChatInput
className="rounded-xl shadow-xl"
resetUploadedFiles={reset}
annotations={annotations}
>
<div>
{/* Image preview section */}
{imageUrl && (
<ImagePreview url={imageUrl} onRemove={() => setImageUrl(null)} />
)}
{/* Document previews section */}
{files.length > 0 && (
<div className="flex w-full gap-4 overflow-auto py-2">
{files.map((file) => (
<DocumentInfo
key={file.id}
document={{ url: file.url, sources: [] }}
className="mb-2 mt-2"
onRemove={() => removeDoc(file)}
/>
))}
</div>
)}
</div>
<ChatInput resetUploadedFiles={reset} annotations={annotations}>
{/* Image preview section */}
{imageUrl && (
<ImagePreview url={imageUrl} onRemove={() => setImageUrl(null)} />
)}
{/* Document previews section */}
{files.length > 0 && (
<div className="flex w-full gap-4 overflow-auto py-2">
{files.map((file) => (
<DocumentInfo
key={file.id}
document={{ url: file.url, sources: [] }}
className="mb-2 mt-2"
onRemove={() => removeDoc(file)}
/>
))}
</div>
)}
<ChatInput.Form>
<ChatInput.Field />
{uploadAPI && <ChatInput.Upload onUpload={handleUploadFile} />}
@@ -16,7 +16,7 @@ export default function CustomChatMessages({
const { messages } = useChatUI();
return (
<ChatMessages className="rounded-xl shadow-xl">
<ChatMessages>
<ChatMessages.List>
{messages.map((message, index) => (
<ChatMessage
@@ -32,9 +32,9 @@ export default function CustomChatMessages({
<ChatMessage.Actions />
</ChatMessage>
))}
<ChatMessages.Empty />
<ChatMessages.Loading />
</ChatMessages.List>
<ChatMessages.Actions />
<ChatStarter />
</ChatMessages>
);
@@ -4,7 +4,7 @@ import { useChatUI } from "@llamaindex/chat-ui";
import { StarterQuestions } from "@llamaindex/chat-ui/widgets";
import { getConfig } from "../lib/utils";
export function ChatStarter() {
export function ChatStarter({ className }: { className?: string }) {
const { append, messages, requestData } = useChatUI();
const starterQuestions = getConfig("STARTER_QUESTIONS") ?? [];
@@ -13,6 +13,7 @@ export function ChatStarter() {
<StarterQuestions
append={(message) => append(message, { data: requestData })}
questions={starterQuestions}
className={className}
/>
);
}
+1 -7
View File
@@ -13,11 +13,5 @@ const ChatSection = dynamic(() => import("./components/chat-section"), {
});
export default function Home() {
return (
<main className="background-gradient flex h-screen w-screen items-center justify-center overflow-hidden">
<div className="w-[90%] space-y-2 lg:w-[60rem] lg:space-y-10">
<ChatSection />
</div>
</main>
);
return <ChatSection />;
}
+20 -6
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/server",
"description": "LlamaIndex Server",
"version": "0.1.4",
"version": "0.1.5",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -45,21 +45,24 @@
"@types/node": "^22.9.0",
"@types/react": "^19",
"@types/react-dom": "^19",
"llamaindex": "workspace:*",
"eslint": "^9",
"eslint-config-next": "15.2.3",
"postcss": "^8.5.3",
"postcss-cli": "^11.0.1",
"tailwindcss": "^4",
"tw-animate-css": "1.2.5",
"tsx": "^4.19.3",
"tw-animate-css": "1.2.5",
"vitest": "^2.1.5"
},
"dependencies": {
"@babel/parser": "^7.27.0",
"@babel/standalone": "^7.27.0",
"@babel/traverse": "^7.27.0",
"@babel/types": "^7.27.0",
"@hookform/resolvers": "^5.0.1",
"@llamaindex/chat-ui": "0.3.2",
"@llama-flow/core": "^0.3.4",
"@llamaindex/chat-ui": "0.4.0",
"@llamaindex/env": "workspace:*",
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-alert-dialog": "^1.1.7",
@@ -94,7 +97,6 @@
"date-fns": "^4.1.0",
"embla-carousel-react": "^8.6.0",
"input-otp": "^1.4.2",
"llamaindex": "workspace:*",
"lucide-react": "^0.460.0",
"next": "^15.3.0",
"next-themes": "^0.4.3",
@@ -106,7 +108,19 @@
"recharts": "^2.15.2",
"sonner": "^2.0.3",
"tailwind-merge": "^2.6.0",
"vaul": "^1.1.2",
"zod": "^3.24.2"
"vaul": "^1.1.2"
},
"peerDependencies": {
"llamaindex": "workspace:*",
"zod": "^3.24.2",
"zod-to-json-schema": "^3.23.3"
},
"peerDependenciesMeta": {
"zod": {
"optional": true
},
"zod-to-json-schema": {
"optional": true
}
}
}
+1
View File
@@ -1,4 +1,5 @@
export * from "./events";
export * from "./server";
export * from "./types";
export { generateEventComponent } from "./utils/gen-ui";
export { toStreamGenerator } from "./utils/workflow";
+561
View File
@@ -0,0 +1,561 @@
import { parse } from "@babel/parser";
import type { NodePath } from "@babel/traverse";
import traverse from "@babel/traverse";
import type {
ExportDefaultDeclaration,
ImportDeclaration,
ImportDefaultSpecifier,
ImportNamespaceSpecifier,
ImportSpecifier,
} from "@babel/types";
import { createWorkflow, getContext, workflowEvent } from "@llama-flow/core";
import { collect } from "@llama-flow/core/stream/consumer";
import { until } from "@llama-flow/core/stream/until";
import type { LLM } from "llamaindex";
import type { ZodType } from "zod";
const writeAggregationEvent = workflowEvent<{
eventSchema: object;
uiDescription: string;
}>();
const writeUiComponentEvent = workflowEvent<{
eventSchema: object;
uiDescription: string;
aggregationFunction: string | undefined;
}>();
const refineGeneratedCodeEvent = workflowEvent<{
uiCode: string;
aggregationFunction: string;
uiDescription: string;
}>();
const startEvent = workflowEvent<{
eventSchema: object;
}>();
const stopEvent = workflowEvent<string | null>();
const CODE_STRUCTURE = `
// export the component
// The component accepts an 'events' array prop. Each item in the array conforms to the schema provided during generation.
export default function Component({ events }) {
// logic for aggregating events (if needed)
const aggregatedEvents = // ... aggregation logic based on aggregationFunction description ...
// Determine which events to render (original or aggregated)
const eventsToRender = aggregatedEvents || events;
return (
<div>
{/* Render eventsToRender using shadcn/ui, lucide-react, tailwind CSS */}
{/* Map over eventsToRender and display each one */}
{/* Example: */}
{/* {eventsToRender.map((event, index) => (
<Card key={index}>
<CardHeader>
<CardTitle>Event Data</CardTitle> // Adjust title as needed
</CardHeader>
<CardContent>
<pre>{JSON.stringify(event, null, 2)}</pre>
</CardContent>
</Card>
))} */}
</div>
);
}
`;
const SOURCE_MAP: Record<string, boolean> = {
react: true,
"react-dom": true,
"@/components/ui/accordion": true,
"@/components/ui/alert": true,
"@/components/ui/alert-dialog": true,
"@/components/ui/aspect-ratio": true,
"@/components/ui/avatar": true,
"@/components/ui/badge": true,
"@/components/ui/breadcrumb": true,
"@/components/ui/button": true,
"@/components/ui/calendar": true,
"@/components/ui/card": true,
"@/components/ui/carousel": true,
"@/components/ui/chart": true,
"@/components/ui/checkbox": true,
"@/components/ui/collapsible": true,
"@/components/ui/command": true,
"@/components/ui/context-menu": true,
"@/components/ui/dialog": true,
"@/components/ui/drawer": true,
"@/components/ui/dropdown-menu": true,
"@/components/ui/form": true,
"@/components/ui/hover-card": true,
"@/components/ui/input": true,
"@/components/ui/input-otp": true,
"@/components/ui/label": true,
"@/components/ui/menubar": true,
"@/components/ui/navigation-menu": true,
"@/components/ui/pagination": true,
"@/components/ui/popover": true,
"@/components/ui/progress": true,
"@/components/ui/radio-group": true,
"@/components/ui/resizable": true,
"@/components/ui/scroll-area": true,
"@/components/ui/select": true,
"@/components/ui/separator": true,
"@/components/ui/sheet": true,
"@/components/ui/sidebar": true,
"@/components/ui/skeleton": true,
"@/components/ui/slider": true,
"@/components/ui/sonner": true,
"@/components/ui/switch": true,
"@/components/ui/table": true,
"@/components/ui/tabs": true,
"@/components/ui/textarea": true,
"@/components/ui/toggle": true,
"@/components/ui/toggle-group": true,
"@/components/ui/tooltip": true,
"@/components/lib/utils": true,
"@/lib/utils": true,
"lucide-react": true,
"@llamaindex/chat-ui/widgets": true,
};
function generateSupportedDeps(): string {
// Extract all shadcn component names from SOURCE_MAP
const shadcnComponents = Object.keys(SOURCE_MAP)
.filter((key) => key.startsWith("@/components/ui/"))
.map((key) => key.replace("@/components/ui/", ""))
.sort()
.join(", ");
return `
- React: import { useState } from "react";
- shadcn/ui: import { ComponentName } from "@/components/ui/<component_path>";
Supported shadcn components:
${shadcnComponents}
- lucide-react: import { IconName } from "lucide-react";
- tailwind css: import { cn } from "@/lib/utils"; // Note: clsx is not supported
- LlamaIndex's markdown-ui: import { Markdown } from "@llamaindex/chat-ui/widgets";
`;
}
const SUPPORTED_DEPS = generateSupportedDeps();
function validateComponentCode(code: string): {
isValid: boolean;
error?: string;
componentName?: string;
} {
try {
const imports: Array<{ name: string; source: string }> = [];
let componentName: string | null = null;
// Parse the code into an AST
const ast = parse(code, {
sourceType: "module",
plugins: ["jsx", "typescript"],
});
// Traverse the AST to find import declarations
traverse(ast, {
// Find import declarations
ImportDeclaration(path: NodePath<ImportDeclaration>) {
path.node.specifiers.forEach(
(
specifier:
| ImportSpecifier
| ImportDefaultSpecifier
| ImportNamespaceSpecifier,
) => {
if (
specifier.type === "ImportSpecifier" ||
specifier.type === "ImportDefaultSpecifier"
) {
imports.push({
name: specifier.local.name, // e.g., "Button"
source: path.node.source.value, // e.g., "@/components/ui/button"
});
}
},
);
},
// Find export default declaration
ExportDefaultDeclaration(path: NodePath<ExportDefaultDeclaration>) {
const declaration = path.node.declaration;
if (declaration.type === "FunctionDeclaration" && declaration.id) {
componentName = declaration.id.name; // e.g., "EventTimeline"
} else if (
declaration.type === "Identifier" &&
path.scope.hasBinding(declaration.name)
) {
componentName = declaration.name; // e.g., named function assigned to export
}
},
});
// Validate imports
for (const { name, source } of imports) {
if (!(source in SOURCE_MAP)) {
console.error(`Invalid import: ${name} from ${source}`);
return {
isValid: false,
error: `Failed to import ${name} from ${source}. Reason: Module not found.
\nHere is the list of supported imports: ${SUPPORTED_DEPS}`,
};
}
}
// Validate component export
if (!componentName) {
console.warn("Could not identify component name in the generated code.");
}
return {
isValid: true,
...(componentName ? { componentName } : {}),
};
} catch (error) {
console.error("Error during code validation:", error);
return {
isValid: false,
error:
error instanceof Error ? error.message : "Unknown validation error",
};
}
}
/**
* Creates the UI generation workflow with the provided LLM instance.
*
* @param llm - The LLM instance to use for the workflow.
* @returns The configured workflow instance.
*/
export function createGenUiWorkflow(llm: LLM) {
const genUiWorkflow = createWorkflow();
genUiWorkflow.handle([startEvent], async ({ data: { eventSchema } }) => {
const context = getContext();
const planningPrompt = `
# Your role
You are an AI assistant helping to plan a React UI component. This component will display *one or more events* in a chat application, all conforming to a single JSON schema.
# Context
Here is the JSON schema for the events the component needs to display:
${JSON.stringify(eventSchema, null, 2)}
# Task
1. Analyze the event schema.
2. Decide if multiple events of this type should be aggregated before rendering in the UI (e.g., group similar events, summarize sequences). Assume the component will receive an array of these events.
3. If aggregation is needed, provide a *brief* description of the JavaScript function logic (no code implementation yet, just the logic description) that would take an array of events and return an aggregated representation.
4. Provide a concise description of the desired UI look and feel for displaying these events (e.g., "Display each event in a card with an icon representing the event type.").
e.g: Assume that the backend produce list of events with animal name, action, and status.
\`\`\`
A card-based layout displaying animal actions:
- Each card shows an animal's image at the top
- Below the image: animal name as the card title
- Action details in the card body with an icon (eating 🍖, sleeping 😴, playing 🎾)
- Status badge in the corner showing if action is ongoing/completed
- Expandable section for additional details
- Soft color scheme based on action type
\`\`\`
Don't be verbose, just return the description for the UI based on the event schema and data.
`;
try {
const response = await llm.complete({
prompt: planningPrompt,
stream: false,
});
const responseText = response.text.trim();
console.log("\nUI Description:", responseText);
context.sendEvent(
writeAggregationEvent.with({
eventSchema,
uiDescription: responseText,
}),
);
} catch (error) {
console.error("Error during UI planning:", error);
context.sendEvent(stopEvent.with(null));
}
});
genUiWorkflow.handle([writeAggregationEvent], async ({ data: planData }) => {
const context = getContext();
const schemaContext = JSON.stringify(planData.eventSchema, null, 2);
const uiDescriptionContext = planData.uiDescription;
const writingPrompt = `
# Your role
You are a frontend developer who is developing a React component for given events that are emitted from a backend workflow.
Here are the events that you need to work on: ${schemaContext}
Here is the description of the UI: ${uiDescriptionContext}
# Task
Based on the description of the UI and the list of events, write the aggregation function that will be used to aggregate the events.
Take into account that the list of events grows with time. At the beginning, there is only one event in the list, and events are incrementally added.
To render the events in a visually pleasing way, try to aggregate them by their attributes and render the aggregates instead of just rendering a list of all events.
Don't add computation to the aggregation function, just group the events by their attributes.
Make sure that the aggregation should reflect the description of the UI and the grouped events are not duplicated, make it as simple as possible to avoid unnecessary issues.
# Answer with the following format:
\`\`\`jsx
const aggregateEvents = () => {
// code for aggregating events here if needed otherwise let the jsx code block empty
}
\`\`\`
`;
try {
const response = await llm.complete({
prompt: writingPrompt,
stream: false,
});
const generatedCode = response.text.trim();
context.sendEvent(
writeUiComponentEvent.with({
eventSchema: planData.eventSchema,
uiDescription: planData.uiDescription,
aggregationFunction: generatedCode,
}),
);
} catch (error) {
console.error("Error during aggregation function writing:", error);
context.sendEvent(stopEvent.with(null));
}
});
genUiWorkflow.handle([writeUiComponentEvent], async ({ data: planData }) => {
const context = getContext();
const aggregationFunctionContext = planData.aggregationFunction
? `
# Here is the aggregation function that aggregates the events:
${planData.aggregationFunction}`
: "";
const schemaContext = JSON.stringify(planData.eventSchema, null, 2);
const uiDescriptionContext = planData.uiDescription;
const writingPrompt = `
# Your role
You are a frontend developer who is developing a React component using shadcn/ui, lucide-react, LlamaIndex's chat-ui, and tailwind css (cn) for the UI.
You are given a list of events and other context.
Your task is to write a beautiful UI for the events that will be included in a chat UI.
# Context:
Here are the events that you need to work on: ${schemaContext}
${aggregationFunctionContext}
Here is the description of the UI:
\`\`\`
${uiDescriptionContext}
\`\`\`
# Only use the following dependencies: ${SUPPORTED_DEPS}
# Requirements:
- Write beautiful UI components for the events using the supported dependencies
- The component text/label should be specified for each event type.
# Instructions:
## Event and schema notice
- Based on the provided list of events, determine their types and attributes.
- It's normal that the schema is applied to all events, but the events might be completely different where some schema attributes aren't used.
- You should make the component visually distinct for each event type.
e.g: A simple cat schema
\`\`\`{"type": "cat", "action": ["jump", "run", "meow"], "jump": {"height": 10, "distance": 20}, "run": {"distance": 100}}\`\`\`
You should display the jump, run and meow actions in different ways. Don't try to render "height" for the "run" and "meow" action.
## UI notice
- Use the supported dependencies for the UI.
- Be careful on state handling, make sure the update should be updated in the state and there is no duplicate state.
- For a long content, consider to use markdown along with dropdown to show the full content.
e.g:
\`\`\`jsx
import { Markdown } from "@llamaindex/chat-ui/widgets";
<Markdown content={content} />
\`\`\`
- Try to make the component placement not monotonous, consider use row/column/flex/grid layout.
`;
try {
const response = await llm.complete({
prompt: writingPrompt,
stream: false,
});
const generatedCode = response.text.trim();
context.sendEvent(
refineGeneratedCodeEvent.with({
uiCode: generatedCode,
aggregationFunction: planData.aggregationFunction || "",
uiDescription: planData.uiDescription,
}),
);
} catch (error) {
console.error("Error during UI component writing:", error);
context.sendEvent(stopEvent.with(null));
}
});
genUiWorkflow.handle(
[refineGeneratedCodeEvent],
async ({ data: writeData }) => {
const context = getContext();
const MAX_VALIDATION_ATTEMPTS = 3;
let currentCode = writeData.uiCode;
let attemptCount = 0;
let validationError = null;
while (attemptCount < MAX_VALIDATION_ATTEMPTS) {
attemptCount++;
if (attemptCount > 1) {
console.log(
`Refinement attempt ${attemptCount}/${MAX_VALIDATION_ATTEMPTS}`,
);
}
try {
// Build refinement prompt - include error info for subsequent attempts
const errorSection =
attemptCount > 1 && validationError
? `\n# Error to fix:\n${validationError}\n\n# Additional requirements:\n1. Only import from supported modules\n2. Ensure the component has an export default statement\n3. Component must accept an 'events' array prop`
: "";
const refiningPrompt = `
# Your role
You are a senior frontend developer reviewing React code written by a junior developer.
# Context:
- The goal is to create a React component that displays an array of events.
- Required Code Structure (Component accepts an \`events\` array prop):
${CODE_STRUCTURE}
- Aggregation Context (if any): ${writeData.aggregationFunction || "None"}
- ${attemptCount > 1 ? "Previous" : "Generated"} Code:
${currentCode}${errorSection}
# Task:
Review and refine the provided code. Ensure it strictly follows the "Required Code Structure" (including accepting the \`events\` array prop), implements any described aggregation logic correctly, imports are correct (individual shadcn/ui imports), and there are no obvious bugs or undefined variables.
# Output Format:
Return ONLY the final, refined code, enclosed in a single JSX code block (\`\`\`jsx ... \`\`\`). Do not add any explanations before or after the code block.
`;
const response = await llm.complete({
prompt: refiningPrompt,
stream: false,
});
const refinedCode = response.text.trim();
// Extract code from markdown block if present
const codeMatch = refinedCode.match(/```jsx\n?([^]*?)\n?```/);
if (codeMatch && codeMatch[1]) {
currentCode = codeMatch[1].trim();
} else {
// Fallback if no block found - attempt cleanup
currentCode = refinedCode.replace(/^```jsx|```$/g, "").trim();
console.warn(
"Could not find standard JSX code block in refinement response, using raw content.",
);
}
// Validate the refined code
const validation = validateComponentCode(currentCode);
if (validation.isValid) {
console.log(`\n✅ Code validated successfully`);
context.sendEvent(stopEvent.with(currentCode));
return;
} else {
validationError = validation.error;
console.warn(
`Validation failed (attempt ${attemptCount}/${MAX_VALIDATION_ATTEMPTS}): ${validation.error}`,
);
// If this was the last attempt, give up
if (attemptCount >= MAX_VALIDATION_ATTEMPTS) {
console.error(
`Failed to generate valid code after ${MAX_VALIDATION_ATTEMPTS} attempts`,
);
context.sendEvent(stopEvent.with(null));
return;
}
// Otherwise continue to the next iteration of the loop
}
} catch (error) {
console.error(
`Error during refinement attempt ${attemptCount}:`,
error,
);
context.sendEvent(stopEvent.with(null));
return;
}
}
},
);
return genUiWorkflow;
}
/**
* Generates a React UI component for displaying event data of a given type.
*
* @param eventType - A Zod schema representing the event type.
* @param llm - The LLM instance to use for the workflow.
* We recommend using gpt-4.1, sonnet-3.7, or gemini-2.5-pro
* for better results
* @returns The generated React component code as a string.
*/
export async function generateEventComponent(
eventType: ZodType | object,
llm: LLM,
): Promise<string> {
let eventSchema: object = eventType;
if ("parse" in eventType && "safeParse" in eventType) {
// Zod schema given, convert to JSON schema including descriptions
const zodToJsonSchema = (await import("zod-to-json-schema")).default;
const zodEventSchema = zodToJsonSchema(eventType, {
target: "openApi3",
});
if (!zodEventSchema) {
throw new Error("Could not get JSON schema for the event type");
}
eventSchema = zodEventSchema;
}
console.log(`🎨 Starting UI generation...
`);
try {
const genUiWorkflow = createGenUiWorkflow(llm);
const { stream, sendEvent } = genUiWorkflow.createContext();
sendEvent(startEvent.with({ eventSchema }));
// Collect all events until the stop event and get the last one
const allEvents = await collect(until(stream, stopEvent));
const result = allEvents[allEvents.length - 1];
if (result?.data === null) {
throw new Error("Workflow failed.");
} else if (result) {
console.log("\nWorkflow finished successfully.");
return result.data;
} else {
throw new Error("Workflow result is undefined.");
}
} catch (error) {
console.error("Workflow execution failed:", error);
throw new Error(`UI generation workflow failed: ${error}`);
}
}
+96 -63
View File
@@ -7,14 +7,13 @@ settings:
importers:
.:
dependencies:
p-retry:
specifier: ^6.2.1
version: 6.2.1
devDependencies:
'@changesets/cli':
specifier: ^2.27.5
version: 2.29.1
'@eslint/js':
specifier: ^9.25.0
version: 9.25.0
bunchee:
specifier: 6.4.0
version: 6.4.0(typescript@5.7.3)
@@ -33,6 +32,9 @@ importers:
eslint-plugin-react:
specifier: 7.37.2
version: 7.37.2(eslint@9.22.0(jiti@2.4.2))
eslint-plugin-turbo:
specifier: ^2.5.0
version: 2.5.0(eslint@9.22.0(jiti@2.4.2))(turbo@2.5.0)
globals:
specifier: ^15.12.0
version: 15.15.0
@@ -76,8 +78,8 @@ importers:
specifier: ^10.1.0
version: 10.2.0(react@19.1.0)
'@llama-flow/docs':
specifier: 0.0.3
version: 0.0.3
specifier: 0.0.5
version: 0.0.5
'@llamaindex/chat-ui':
specifier: 0.2.0
version: 0.2.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -296,14 +298,14 @@ importers:
specifier: ^4.19.3
version: 4.19.3
typedoc:
specifier: 0.28.2
version: 0.28.2(typescript@5.7.3)
specifier: 0.28.3
version: 0.28.3(typescript@5.7.3)
typedoc-plugin-markdown:
specifier: ^4.6.2
version: 4.6.2(typedoc@0.28.2(typescript@5.7.3))
version: 4.6.2(typedoc@0.28.3(typescript@5.7.3))
typedoc-plugin-merge-modules:
specifier: ^7.0.0
version: 7.0.0(typedoc@0.28.2(typescript@5.7.3))
specifier: ' ^7.0.0'
version: 7.0.0(typedoc@0.28.3(typescript@5.7.3))
typescript:
specifier: ^5.7.3
version: 5.7.3
@@ -619,7 +621,7 @@ importers:
specifier: ^0.0.16
version: link:../packages/providers/storage/chroma
'@llamaindex/clip':
specifier: ^0.0.51
specifier: ^0.0.52
version: link:../packages/providers/clip
'@llamaindex/cloud':
specifier: ^4.0.3
@@ -631,10 +633,10 @@ importers:
specifier: ^0.6.2
version: link:../packages/core
'@llamaindex/deepinfra':
specifier: ^0.0.51
specifier: ^0.0.52
version: link:../packages/providers/deepinfra
'@llamaindex/deepseek':
specifier: ^0.0.11
specifier: ^0.0.12
version: link:../packages/providers/deepseek
'@llamaindex/elastic-search':
specifier: ^0.1.2
@@ -646,19 +648,19 @@ importers:
specifier: ^1.0.9
version: link:../packages/providers/storage/firestore
'@llamaindex/fireworks':
specifier: ^0.0.11
specifier: ^0.0.12
version: link:../packages/providers/fireworks
'@llamaindex/google':
specifier: ^0.2.3
specifier: ^0.2.4
version: link:../packages/providers/google
'@llamaindex/groq':
specifier: ^0.0.66
specifier: ^0.0.67
version: link:../packages/providers/groq
'@llamaindex/huggingface':
specifier: ^0.1.5
specifier: ^0.1.6
version: link:../packages/providers/huggingface
'@llamaindex/jinaai':
specifier: ^0.0.11
specifier: ^0.0.12
version: link:../packages/providers/jinaai
'@llamaindex/milvus':
specifier: ^0.1.11
@@ -679,10 +681,10 @@ importers:
specifier: ^0.1.2
version: link:../packages/providers/ollama
'@llamaindex/openai':
specifier: ^0.3.3
specifier: ^0.3.4
version: link:../packages/providers/openai
'@llamaindex/perplexity':
specifier: ^0.0.8
specifier: ^0.0.9
version: link:../packages/providers/perplexity
'@llamaindex/pinecone':
specifier: ^0.1.2
@@ -706,7 +708,7 @@ importers:
specifier: ^0.1.1
version: link:../packages/providers/storage/supabase
'@llamaindex/together':
specifier: ^0.0.11
specifier: ^0.0.12
version: link:../packages/providers/together
'@llamaindex/tools':
specifier: ^0.0.5
@@ -718,7 +720,7 @@ importers:
specifier: ^0.1.2
version: link:../packages/providers/vercel
'@llamaindex/vllm':
specifier: ^0.0.37
specifier: ^0.0.38
version: link:../packages/providers/vllm
'@llamaindex/voyage-ai':
specifier: ^1.0.8
@@ -754,7 +756,7 @@ importers:
specifier: ^1.0.14
version: 1.0.19
llamaindex:
specifier: ^0.10.1
specifier: ^0.10.2
version: link:../packages/llamaindex
mongodb:
specifier: 6.7.0
@@ -875,6 +877,10 @@ importers:
version: 4.19.3
packages/cloud:
dependencies:
p-retry:
specifier: ^6.2.1
version: 6.2.1
devDependencies:
'@hey-api/client-fetch':
specifier: ^0.6.0
@@ -1655,12 +1661,18 @@ importers:
'@babel/traverse':
specifier: ^7.27.0
version: 7.27.0
'@babel/types':
specifier: ^7.27.0
version: 7.27.0
'@hookform/resolvers':
specifier: ^5.0.1
version: 5.0.1(react-hook-form@7.55.0(react@19.1.0))
'@llama-flow/core':
specifier: ^0.3.4
version: 0.3.4(@modelcontextprotocol/sdk@1.9.0)(hono@4.7.7)(next@15.3.0(@opentelemetry/api@1.9.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(p-retry@6.2.1)(zod@3.24.2)
'@llamaindex/chat-ui':
specifier: 0.3.2
version: 0.3.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
specifier: 0.4.0
version: 0.4.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@llamaindex/env':
specifier: workspace:*
version: link:../env
@@ -1763,9 +1775,6 @@ importers:
input-otp:
specifier: ^1.4.2
version: 1.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
llamaindex:
specifier: workspace:*
version: link:../llamaindex
lucide-react:
specifier: ^0.460.0
version: 0.460.0(react@19.1.0)
@@ -1805,6 +1814,9 @@ importers:
zod:
specifier: ^3.24.2
version: 3.24.2
zod-to-json-schema:
specifier: ^3.23.3
version: 3.24.5(zod@3.24.2)
devDependencies:
'@eslint/eslintrc':
specifier: ^3
@@ -1833,6 +1845,9 @@ importers:
eslint-config-next:
specifier: 15.2.3
version: 15.2.3(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
llamaindex:
specifier: workspace:*
version: link:../llamaindex
postcss:
specifier: ^8.5.3
version: 8.5.3
@@ -3287,6 +3302,10 @@ packages:
resolution: {integrity: sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/js@9.25.0':
resolution: {integrity: sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.6':
resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3789,16 +3808,36 @@ packages:
'@lezer/yaml@1.0.3':
resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==}
'@llama-flow/docs@0.0.3':
resolution: {integrity: sha512-5BFSbaWY7Ps5djzXilgyy9t7OYElyoojvEmLy/FC1azUnn6poIxvr04Ctsoi0PR44sYyqWb7hkuU5iJap6uLyA==}
'@llama-flow/core@0.3.4':
resolution: {integrity: sha512-BOe23pfm7j9hKMH7u0jFS8bPKLsShKgz8KdN/rXeicgnopCwhDMO4ppOg7Cy7tWap8kYZIY8ZliN7Q9SmNfjkg==}
peerDependencies:
'@modelcontextprotocol/sdk': ^1.7.0
hono: ^4.7.4
next: ^15.2.2
p-retry: ^6.2.1
zod: ^3.24.2
peerDependenciesMeta:
'@modelcontextprotocol/sdk':
optional: true
hono:
optional: true
next:
optional: true
p-retry:
optional: true
zod:
optional: true
'@llama-flow/docs@0.0.5':
resolution: {integrity: sha512-iAEqqWgPnJNxm4syNSxudDE1aHYNi1eTrxHg+FjcPeZhxyksLYRzpmzUikcZv0uhxgLwRinF7UPTnH9ioKlaEw==}
'@llamaindex/chat-ui@0.2.0':
resolution: {integrity: sha512-9U5+9l2UVBaOG8fSuMjnere5R2QSNxCEcixMwBgt4L4b0evo8jU4ZzlSxLPunWfpn1PWFVMUwKLlSSwa1qTTyA==}
peerDependencies:
react: ^18.2.0 || ^19.0.0 || ^19.0.0-rc
'@llamaindex/chat-ui@0.3.2':
resolution: {integrity: sha512-YcQOghcxutqHK9KO2CRSws0inDR5bbMZkmpUFJtC2aWcHjWi8wYbzVZjRVl1vrb3VCk+VInKOhFUTW9hEkzydA==}
'@llamaindex/chat-ui@0.4.0':
resolution: {integrity: sha512-u9jOUuyKPDFnJsorfH8oIE0UVO+zlabbD8lgTFbN37XUdYFFG4rteEYwUWc/n4/h/GjnFcTfxpiyWmiwTKzicw==}
peerDependencies:
react: ^18.2.0 || ^19.0.0 || ^19.0.0-rc
@@ -12627,8 +12666,8 @@ packages:
peerDependencies:
typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x
typedoc@0.28.2:
resolution: {integrity: sha512-9Giuv+eppFKnJ0oi+vxqLM817b/IrIsEMYgy3jj6zdvppAfDqV3d6DXL2vXUg2TnlL62V48th25Zf/tcQKAJdg==}
typedoc@0.28.3:
resolution: {integrity: sha512-5svOCTfXvVSh6zbZKSQluZhR8yN2tKpTeHZxlmWpE6N5vc3R8k/jhg9nnD6n5tN9/ObuQTojkONrOxFdUFUG9w==}
engines: {node: '>= 18', pnpm: '>= 10'}
hasBin: true
peerDependencies:
@@ -15361,6 +15400,8 @@ snapshots:
'@eslint/js@9.22.0': {}
'@eslint/js@9.25.0': {}
'@eslint/object-schema@2.1.6': {}
'@eslint/plugin-kit@0.2.7':
@@ -15877,7 +15918,15 @@ snapshots:
'@lezer/highlight': 1.2.1
'@lezer/lr': 1.4.2
'@llama-flow/docs@0.0.3': {}
'@llama-flow/core@0.3.4(@modelcontextprotocol/sdk@1.9.0)(hono@4.7.7)(next@15.3.0(@opentelemetry/api@1.9.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(p-retry@6.2.1)(zod@3.24.2)':
optionalDependencies:
'@modelcontextprotocol/sdk': 1.9.0
hono: 4.7.7
next: 15.3.0(@opentelemetry/api@1.9.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
p-retry: 6.2.1
zod: 3.24.2
'@llama-flow/docs@0.0.5': {}
'@llamaindex/chat-ui@0.2.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
@@ -15909,7 +15958,7 @@ snapshots:
- react-dom
- supports-color
'@llamaindex/chat-ui@0.3.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
'@llamaindex/chat-ui@0.4.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@llamaindex/pdf-viewer': 1.3.0(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-collapsible': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -20724,7 +20773,7 @@ snapshots:
'@typescript-eslint/parser': 8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
eslint: 9.22.0(jiti@2.4.2)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))
eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.22.0(jiti@2.4.2))
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.22.0(jiti@2.4.2))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.22.0(jiti@2.4.2))
eslint-plugin-react: 7.37.2(eslint@9.22.0(jiti@2.4.2))
@@ -20754,22 +20803,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.0
enhanced-resolve: 5.18.1
eslint: 9.22.0(jiti@2.4.2)
fast-glob: 3.3.3
get-tsconfig: 4.10.0
is-bun-module: 1.3.0
is-glob: 4.0.3
stable-hash: 0.0.4
optionalDependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.22.0(jiti@2.4.2))
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.16.0(jiti@2.4.2)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
@@ -20798,7 +20831,7 @@ snapshots:
is-glob: 4.0.3
stable-hash: 0.0.4
optionalDependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.22.0(jiti@2.4.2))
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.22.0(jiti@2.4.2))
transitivePeerDependencies:
- supports-color
@@ -20824,14 +20857,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2)):
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.22.0(jiti@2.4.2)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
eslint: 9.22.0(jiti@2.4.2)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))
eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.22.0(jiti@2.4.2))
transitivePeerDependencies:
- supports-color
@@ -20904,7 +20937,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.22.0(jiti@2.4.2)
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.22.0(jiti@2.4.2))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -27135,13 +27168,13 @@ snapshots:
optionalDependencies:
rxjs: 7.8.1
typedoc-plugin-markdown@4.6.2(typedoc@0.28.2(typescript@5.7.3)):
typedoc-plugin-markdown@4.6.2(typedoc@0.28.3(typescript@5.7.3)):
dependencies:
typedoc: 0.28.2(typescript@5.7.3)
typedoc: 0.28.3(typescript@5.7.3)
typedoc-plugin-merge-modules@7.0.0(typedoc@0.28.2(typescript@5.7.3)):
typedoc-plugin-merge-modules@7.0.0(typedoc@0.28.3(typescript@5.7.3)):
dependencies:
typedoc: 0.28.2(typescript@5.7.3)
typedoc: 0.28.3(typescript@5.7.3)
typedoc@0.26.11(typescript@5.7.3):
dependencies:
@@ -27152,7 +27185,7 @@ snapshots:
typescript: 5.7.3
yaml: 2.7.1
typedoc@0.28.2(typescript@5.7.3):
typedoc@0.28.3(typescript@5.7.3):
dependencies:
'@gerrit0/mini-shiki': 3.2.3
lunr: 2.3.9
+8
View File
@@ -1,5 +1,13 @@
# @llamaindex/unit-test
## 0.1.22
### Patch Changes
- Updated dependencies [e5c3f95]
- @llamaindex/openai@0.3.4
- llamaindex@0.10.2
## 0.1.21
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@llamaindex/unit-test",
"private": true,
"version": "0.1.21",
"version": "0.1.22",
"type": "module",
"scripts": {
"test": "vitest run"