Repository: run-llama/LlamaIndexTS
Pull request #1704: chore: add unit test for agent workflow
Author: login: leehuwuj
Created: 2025-03-05T04:09:54Z | Merged: 2025-03-10T09:44:49Z



Diff:
diff --git a/unit/workflow/agent-workflow.test.ts b/unit/workflow/agent-workflow.test.ts
new file mode 100644
index 0000000000..09ede8da7c
--- /dev/null
+++ b/unit/workflow/agent-workflow.test.ts
@@ -0,0 +1,268 @@
+import { FunctionTool } from "@llamaindex/core/tools";
+import { AgentWorkflow, FunctionAgent } from "@llamaindex/workflow/agent";
+import {
+  MockLLM,
+  Settings,
+  ToolCallLLM,
+  type JSONObject,
+  type LLMChatParamsNonStreaming,
+  type LLMChatParamsStreaming,
+} from "llamaindex";
+import { describe, expect, test, vi } from "vitest";
+import { z } from "zod";
+
+describe("AgentWorkflow", () => {
+  test("agent workflow and function agent creation correctly", () => {
+    // Create a minimal mock for ToolCallLLM
+    const mockLLM = MockLLM as unknown as ToolCallLLM;
+
+    // Create minimal tools
+    const addTool = FunctionTool.from(
+      (params: { x: number; y: number }) => params.x + params.y,
+      {
+        name: "add",
+        description: "Adds two numbers",
+        parameters: z.object({
+          x: z.number(),
+          y: z.number(),
+        }),
+      },
+    );
+    const multiplyTool = FunctionTool.from(
+      (params: { x: number; y: number }) => params.x * params.y,
+      {
+        name: "multiply",
+        description: "Multiplies two numbers",
+        parameters: z.object({
+          x: z.number(),
+          y: z.number(),
+        }),
+      },
+    );
+
+    // Create function agents
+    const calculatorAgent = new FunctionAgent({
+      name: "CalculatorAgent",
+      description: "Simple calculator",
+      tools: [addTool],
+      llm: mockLLM,
+    });
+
+    const mathAgent = new FunctionAgent({
+      name: "MathAgent",
+      description: "Performs math operations",
+      tools: [addTool, multiplyTool],
+      llm: mockLLM,
+      canHandoffTo: [calculatorAgent],
+    });
+
+    // Verify create single agent workflow
+    const singleAgentWorkflow = AgentWorkflow.fromTools({
+      tools: [addTool],
+      llm: mockLLM,
+    });
+    expect(singleAgentWorkflow).toBeDefined();
+
+    // Verify workflow initializes correctly with multiple agents
+    const workflow = new AgentWorkflow({
+      agents: [mathAgent, calculatorAgent],
+      rootAgent: mathAgent,
+      verbose: false,
+    });
+
+    // Verify workflow is defined
+    expect(workflow).toBeDefined();
+
+    // Verify adding duplicate agents throws an error
+    expect(() => {
+      new AgentWorkflow({
+        agents: [mathAgent, mathAgent],
+        rootAgent: mathAgent,
+      });
+    }).toThrow();
+
+    // Verify using a non-existent root agent throws an error
+    expect(() => {
+      new AgentWorkflow({
+        agents: [mathAgent],
+        rootAgent: calculatorAgent,
+      });
+    }).toThrow();
+
+    // Expect mathAgent has handOff tools after setup
+    expect(
+      mathAgent.tools.some((tool) => tool.metadata.name === "handOff"),
+    ).toBe(true);
+  });
+
+  test("single agent workflow runs correctly", async () => {
+    // This test don't need to handoff
+    const mockLLM = setupToolCallingMockLLM("add", { x: 1, y: 2 });
+
+    Settings.llm = mockLLM;
+
+    const addTool = FunctionTool.from(
+      (params: { x: number; y: number }) => {
+        console.log("addTool called with", params);
+        return params.x + params.y;
+      },
+      {
+        name: "add",
+        description: "Adds two numbers",
+      },
+    );
+
+    // Spy on the tool's call method
+    vi.spyOn(addTool, "call");
+
+    const workflow = AgentWorkflow.fromTools({
+      tools: [addTool],
+      llm: mockLLM as unknown as ToolCallLLM,
+      verbose: false,
+    });
+
+    const result = workflow.run("What is 2 + 2?");
+
+    const events = [];
+    for await (const event of result) {
+      events.push(event);
+    }
+
+    // Validate the specific sequence of events emitted by the workflow
+    const expectedEventSequence = [
+      "StartEvent",
+      "AgentInput",
+      "AgentSetup",
+      "AgentStepEvent",
+      "AgentStream",
+      "AgentOutput",
+      "ToolCallsEvent",
+      "ToolResultsEvent",
+      "AgentToolCall",
+      "AgentToolCallResult",
+      "AgentInput",
+      "AgentSetup",
+      "AgentStepEvent",
+      "AgentStream",
+      "AgentOutput",
+      "StopEvent",
+    ];
+
+    // Check the event sequence - exact types in exact order
+    expect(events.map((e) => e.constructor.name)).toEqual(
+      expectedEventSequence,
+    );
+
+    // Check if addTool is called
+    expect(addTool.call).toHaveBeenCalled();
+
+    // Check that we have events
+    expect(events.length).toEqual(expectedEventSequence.length);
+
+    //
+  });
+});
+
+/**
+ * Configure a mock LLM to respond with tool calling responses.
+ * This version will first return a tool call, then return a response without tool calls by checking the message history.
+ */
+function setupToolCallingMockLLM(toolName: string, toolKwargs: unknown) {
+  // Reset mocks
+  vi.resetAllMocks();
+
+  const mockLLM = new MockLLM({
+    responseMessage: "I'll help with that.",
+    metadata: {
+      model: "mock-model",
+      temperature: 0,
+      topP: 1,
+      contextWindow: 4096,
+      tokenizer: undefined,
+    },
+  });
+
+  let hasCalledTool = false;
+
+  // Override the chat method with our custom implementation
+  mockLLM.chat = vi
+    .fn()
+    .mockImplementation(
+      (params: LLMChatParamsStreaming | LLMChatParamsNonStreaming) => {
+        // Track if we've already returned a tool call response
+        // If we have tool results in the message history, we're in the second round
+        const hasToolResult = params.messages.some(
+          (msg) =>
+            msg.options &&
+            typeof msg.options === "object" &&
+            "toolResult" in msg.options,
+        );
+
+        if (hasToolResult || hasCalledTool) {
+          // Second response - just return a normal message without tool calls
+          hasCalledTool = false; // Reset for next run
+
+          if (params.stream === true) {
+            return Promise.resolve({
+              async *[Symbol.asyncIterator]() {
+                yield {
+                  delta: "Final response",
+                  raw: {},
+                };
+              },
+            });
+          } else {
+            return Promise.resolve({
+              message: {
+                role: "assistant",
+                content: "Final response",
+              },
+              raw: {},
+            });
+          }
+        } else {
+          // First response - return a tool call
+          hasCalledTool = true;
+
+          if (params.stream === true) {
+            return Promise.resolve({
+              async *[Symbol.asyncIterator]() {
+                yield {
+                  delta: "I'll help with that.",
+                  raw: {},
+                  options: {
+                    toolCall: [
+                      {
+                        id: "call_123",
+                        name: toolName,
+                        input: toolKwargs as JSONObject,
+                      },
+                    ],
+                  },
+                };
+              },
+            });
+          } else {
+            return Promise.resolve({
+              message: {
+                role: "assistant",
+                content: "I'll help with that.",
+                options: {
+                  toolCall: [
+                    {
+                      id: "call_123",
+                      name: toolName,
+                      input: toolKwargs as JSONObject,
+                    },
+                  ],
+                },
+              },
+              raw: {},
+            });
+          }
+        }
+      },
+    );
+
+  return mockLLM;
+}
diff --git a/unit/workflow/function-agent.test.ts b/unit/workflow/function-agent.test.ts
new file mode 100644
index 0000000000..1dc658b437
--- /dev/null
+++ b/unit/workflow/function-agent.test.ts
@@ -0,0 +1,72 @@
+import {
+  AgentToolCallResult,
+  FunctionAgent,
+  FunctionTool,
+  MockLLM,
+  ToolCallLLM,
+  type ChatMessage,
+} from "llamaindex";
+import { describe, expect, test } from "vitest";
+import { z } from "zod";
+
+const mockLLM = new MockLLM() as unknown as ToolCallLLM;
+
+describe("FunctionAgent", () => {
+  test("function agent can parse tool call results", async () => {
+    // Create minimal tools
+    const addTool = FunctionTool.from(
+      (params: { x: number; y: number }) => params.x + params.y,
+      {
+        name: "add",
+        description: "Adds two numbers",
+        parameters: z.object({
+          x: z.number(),
+          y: z.number(),
+        }),
+      },
+    );
+
+    const calculatorAgent = new FunctionAgent({
+      name: "CalculatorAgent",
+      description: "Simple calculator",
+      tools: [addTool],
+      llm: mockLLM,
+    });
+
+    const dummyResult = {
+      data: {
+        toolName: "add",
+        toolKwargs: { x: 2, y: 2 },
+        toolId: "123",
+        toolOutput: { result: "4", isError: false, id: "123" },
+        returnDirect: false,
+      },
+      displayName: "test",
+    } as AgentToolCallResult;
+
+    const dummyContext = {
+      data: {
+        scratchpad: [],
+      },
+    };
+
+    await calculatorAgent.handleToolCallResults(
+      // eslint-disable-next-line @typescript-eslint/no-explicit-any
+      dummyContext as any,
+      [dummyResult],
+    );
+
+    // Check if agent's scratchpad has been updated with the correct message
+    expect(dummyContext.data.scratchpad.length).toEqual(1);
+    const message = dummyContext.data.scratchpad[0] as unknown as ChatMessage;
+    expect(message.content).toEqual("4");
+    expect(message.role).toEqual("user");
+    expect(message.options).toEqual({
+      toolResult: {
+        id: "123",
+        isError: false,
+        result: "4",
+      },
+    });
+  });
+});


Reviews:
user: login: marcusschiesser
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T10:43:23Z
user: login: marcusschiesser
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T10:47:35Z
user: login: marcusschiesser
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T04:11:44Z

Review comments:
path: unit/workflow/llm.ts
user: login: marcusschiesser
body: we already have a MockLLM in core packages, can't reuse it?
created_at: 2025-03-05T10:43:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,150 @@
+import {
+  AgentToolCall,
+  AgentToolCallResult,
+  FunctionAgent,
+  FunctionTool,
+  type ChatMessage,
+} from "llamaindex";
+import { describe, expect, test } from "vitest";
+import { z } from "zod";
+import { setupMockLLM } from "./llm.js";
+
+describe("FunctionAgent", () => {
path: unit/workflow/function-agent.test.ts
user: login: marcusschiesser
body: is it testing public methods handleToolCallResults, takeStep and finalize?
why is it testing private methods getToolCallFromResponseChunk?
created_at: 2025-03-05T10:47:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,268 @@
+import { FunctionTool } from "@llamaindex/core/tools";
+import { AgentWorkflow, FunctionAgent } from "@llamaindex/workflow/agent";
+import {
+  MockLLM,
+  Settings,
+  ToolCallLLM,
+  type JSONObject,
+  type LLMChatParamsNonStreaming,
+  type LLMChatParamsStreaming,
+} from "llamaindex";
+import { describe, expect, test, vi } from "vitest";
+import { z } from "zod";
+
+describe("AgentWorkflow", () => {
+  test("agent workflow and function agent creation correctly", () => {
+    // Create a minimal mock for ToolCallLLM
+    const mockLLM = MockLLM as unknown as ToolCallLLM;
+
+    // Create minimal tools
+    const addTool = FunctionTool.from(
+      (params: { x: number; y: number }) => params.x + params.y,
+      {
+        name: "add",
+        description: "Adds two numbers",
+        parameters: z.object({
+          x: z.number(),
+          y: z.number(),
+        }),
+      },
+    );
+    const multiplyTool = FunctionTool.from(
+      (params: { x: number; y: number }) => params.x * params.y,
+      {
+        name: "multiply",
+        description: "Multiplies two numbers",
+        parameters: z.object({
+          x: z.number(),
+          y: z.number(),
+        }),
+      },
+    );
+
+    // Create function agents
+    const calculatorAgent = new FunctionAgent({
+      name: "CalculatorAgent",
+      description: "Simple calculator",
+      tools: [addTool],
+      llm: mockLLM,
+    });
+
+    const mathAgent = new FunctionAgent({
+      name: "MathAgent",
+      description: "Performs math operations",
+      tools: [addTool, multiplyTool],
+      llm: mockLLM,
+      canHandoffTo: [calculatorAgent],
+    });
+
+    // Verify create single agent workflow
+    const singleAgentWorkflow = AgentWorkflow.fromTools({
+      tools: [addTool],
+      llm: mockLLM,
+    });
+    expect(singleAgentWorkflow).toBeDefined();
+
+    // Verify workflow initializes correctly with multiple agents
+    const workflow = new AgentWorkflow({
+      agents: [mathAgent, calculatorAgent],
+      rootAgent: mathAgent,
+      verbose: false,
+    });
+
+    // Verify workflow is defined
+    expect(workflow).toBeDefined();
+
+    // Verify adding duplicate agents throws an error
+    expect(() => {
+      new AgentWorkflow({
+        agents: [mathAgent, mathAgent],
+        rootAgent: mathAgent,
+      });
+    }).toThrow();
+
+    // Verify using a non-existent root agent throws an error
+    expect(() => {
+      new AgentWorkflow({
+        agents: [mathAgent],
+        rootAgent: calculatorAgent,
+      });
+    }).toThrow();
+
+    // Expect mathAgent has handOff tools after setup
+    expect(
+      mathAgent.tools.some((tool) => tool.metadata.name === "handOff"),
+    ).toBe(true);
+  });
+
+  test("single agent workflow runs correctly", async () => {
+    // This test don't need to handoff
+    const mockLLM = setupToolCallingMockLLM("add", { x: 1, y: 2 });
+
+    Settings.llm = mockLLM;
+
+    const addTool = FunctionTool.from(
+      (params: { x: number; y: number }) => {
+        console.log("addTool called with", params);
+        return params.x + params.y;
+      },
+      {
+        name: "add",
+        description: "Adds two numbers",
+      },
+    );
+
+    // Spy on the tool's call method
+    vi.spyOn(addTool, "call");
+
+    const workflow = AgentWorkflow.fromTools({
+      tools: [addTool],
+      llm: mockLLM as unknown as ToolCallLLM,
+      verbose: false,
+    });
+
+    const result = workflow.run("What is 2 + 2?");
+
+    const events = [];
+    for await (const event of result) {
+      events.push(event);
+    }
+
+    // Validate the specific sequence of events emitted by the workflow
+    const expectedEventSequence = [
+      "StartEvent",
+      "AgentInput",
+      "AgentSetup",
+      "AgentStepEvent",
+      "AgentStream",
+      "AgentOutput",
+      "ToolCallsEvent",
+      "ToolResultsEvent",
+      "AgentToolCall",
+      "AgentToolCallResult",
+      "AgentInput",
+      "AgentSetup",
+      "AgentStepEvent",
+      "AgentStream",
+      "AgentOutput",
+      "StopEvent",
+    ];
+
+    // Check the event sequence - exact types in exact order
+    expect(events.map((e) => e.constructor.name)).toEqual(
+      expectedEventSequence,
+    );
+
+    // Check if addTool is called
+    expect(addTool.call).toHaveBeenCalled();
+
+    // Check that we have events
+    expect(events.length).toEqual(expectedEventSequence.length);
+
+    //
+  });
+});
+
+/**
+ * Configure a mock LLM to respond with tool calling responses.
+ * This version will first return a tool call, then return a response without tool calls by checking the message history.
+ */
+function setupToolCallingMockLLM(toolName: string, toolKwargs: unknown) {
path: unit/workflow/agent-workflow.test.ts
user: login: marcusschiesser
body: move to mockllm?
created_at: 2025-03-06T04:10:45Z
author_association: CONTRIBUTOR
path: unit/workflow/function-agent.test.ts
user: login: marcusschiesser
body: test for takeStep?
created_at: 2025-03-06T04:11:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-03-05T04:09:58Z
body: ###  ⚠️  No Changeset found

Latest commit: 2249945907e0631ee0f93b14f961373e5136a006

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/run-llama/LlamaIndexTS/new/lee/add-test-agent-workflow?filename=.changeset/nasty-papayas-begin.md&value=---%0A%22%40llamaindex%2Funit-test%22%3A%20patch%0A---%0A%0Achore%3A%20add%20unit%20test%20for%20agent%20workflow%0A)


author_association: NONE
user: login: vercel[bot]
created_at: 2025-03-05T04:09:59Z
body: [vc]: #HXl7Q+omt5+TZ5yYOODJQ9IeyfeEe7kvtHWNq885FLA=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJsbGFtYWluZGV4LXRzLWRvYyIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9sbGFtYS1pbmRleC9sbGFtYWluZGV4LXRzLWRvYy9BVGVOYkRjdW9UUTh5Y3Z1azJXVURDUThTdEJnIiwicHJldmlld1VybCI6ImxsYW1haW5kZXgtdHMtZG9jLWdpdC1sZWUtYWRkLXRlc3QtYWdlbnQtd29ya2Zsb3cucHIuc3RhZ2luZy5sbGFtYWluZGV4LmFpIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImxsYW1haW5kZXgtdHMtZG9jLWdpdC1sZWUtYWRkLXRlc3QtYWdlbnQtd29ya2Zsb3cucHIuc3RhZ2luZy5sbGFtYWluZGV4LmFpIn0sInJvb3REaXJlY3RvcnkiOiJhcHBzL25leHQifV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **llamaindex-ts-doc** | ✅ Ready ([Inspect](https://vercel.com/llama-index/llamaindex-ts-doc/ATeNbDcuoTQ8ycvuk2WUDCQ8StBg)) | [Visit Preview](https://llamaindex-ts-doc-git-lee-add-test-agent-workflow.pr.staging.llamaindex.ai) | 💬 [**Add feedback**](https://vercel.live/open-feedback/llamaindex-ts-doc-git-lee-add-test-agent-workflow.pr.staging.llamaindex.ai?via=pr-comment-feedback-link) | Mar 6, 2025 4:22am |


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-05T04:11:30Z
body: ## size-limit report 📦 
| Path                         | Size           | Loading time (3g) | Running time (snapdragon) | Total time |
| ---------------------------- | -------------- | ----------------- | ------------------------- | ---------- |
| dist/LlamaIndexImportTest.js | 503.34 KB (0%) | 10.1 s (0%)       | 888 ms (+30.64% 🔺)       | 11 s       |
author_association: CONTRIBUTOR
user: login: pkg-pr-new[bot]
created_at: 2025-03-05T04:14:11Z
body: 
[Open in Stackblitz](https://pkg.pr.new/template/9150ec78-6459-4456-a4dd-dd861a084056)


<details><summary><b>@llamaindex/autotool</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/autotool@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/cloud</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/cloud@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/community</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/community@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/core</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/core@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/env</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/env@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/experimental</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/experimental@1704
```

</p></details>
      
    

<details><summary><b>llamaindex</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/llamaindex@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/node-parser</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/node-parser@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/readers</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/readers@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/wasm-tools</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/wasm-tools@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/workflow</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/workflow@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/anthropic</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/anthropic@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/clip</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/clip@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/cohere</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/cohere@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/deepinfra</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/deepinfra@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/google</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/google@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/groq</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/groq@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/huggingface</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/huggingface@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/mistral</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/mistral@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/mixedbread</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/mixedbread@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/ollama</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/ollama@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/openai</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/openai@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/portkey-ai</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/portkey-ai@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/replicate</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/replicate@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/vercel</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/vercel@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/vllm</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/vllm@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/voyage-ai</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/voyage-ai@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/astra</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/astra@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/azure</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/azure@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/chroma</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/chroma@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/firestore</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/firestore@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/milvus</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/milvus@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/mongodb</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/mongodb@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/pinecone</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/pinecone@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/postgres</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/postgres@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/qdrant</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/qdrant@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/upstash</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/upstash@1704
```

</p></details>
      
    

<details><summary><b>@llamaindex/weaviate</b></summary><p>

```
npm i https://pkg.pr.new/run-llama/LlamaIndexTS/@llamaindex/weaviate@1704
```

</p></details>
      
    

_commit: <a href="https://github.com/run-llama/LlamaIndexTS/runs/38284543122"><code>2249945</code></a>_

author_association: NONE