mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-15 06:52:45 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1e85f3e31 |
@@ -1,7 +0,0 @@
|
||||
---
|
||||
"@llamaindex/readers": patch
|
||||
"@llamaindex/core": patch
|
||||
"@llamaindex/doc": patch
|
||||
---
|
||||
|
||||
Expose more content to fix the issue with unavailable documentation links, and adjust the documentation based on the latest code.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@llamaindex/google": patch
|
||||
---
|
||||
|
||||
Added saftey setting parameter for gemini
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@llamaindex/pinecone": minor
|
||||
---
|
||||
|
||||
Fix deleting of document by id in PineconeVectorStore
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
"@llamaindex/huggingface": minor
|
||||
"@llamaindex/anthropic": minor
|
||||
"@llamaindex/mistral": minor
|
||||
"@llamaindex/google": minor
|
||||
"@llamaindex/ollama": minor
|
||||
"@llamaindex/openai": minor
|
||||
"@llamaindex/core": minor
|
||||
"@llamaindex/examples": minor
|
||||
---
|
||||
|
||||
Added support for structured output in the chat api of openai and ollama
|
||||
Added structured output parameter in the provider
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@llamaindex/tools": patch
|
||||
---
|
||||
|
||||
feat: @llamaindex/tools
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
"@llamaindex/mistral": minor
|
||||
"@llamaindex/examples": minor
|
||||
---
|
||||
|
||||
Added support for function calling in mistral provider
|
||||
Update model list for mistral provider
|
||||
Added example for the tool call in mistral
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
"@llamaindex/cloud": patch
|
||||
"@llamaindex/community": patch
|
||||
"@llamaindex/core": patch
|
||||
"@llamaindex/readers": patch
|
||||
---
|
||||
|
||||
fix: add retry handling logic to parser reader and fix lint issues
|
||||
@@ -162,12 +162,7 @@ async function validateLinks(): Promise<LinkValidationResult[]> {
|
||||
const invalidLinks = links.filter(({ link }) => {
|
||||
// Check if the link exists in valid routes
|
||||
// First normalize the link (remove any query string or hash)
|
||||
const baseLink = link.split("?")[0].split("#")[0];
|
||||
// Remove the trailing slash if present.
|
||||
// This works with links like "api/interfaces/MetadataFilter#operator" and "api/interfaces/MetadataFilter/#operator".
|
||||
const normalizedLink = baseLink.endsWith("/")
|
||||
? baseLink.slice(0, -1)
|
||||
: baseLink;
|
||||
const normalizedLink = link.split("#")[0].split("?")[0];
|
||||
|
||||
// Remove llamaindex/ prefix if it exists as it's the root of the docs
|
||||
let routePath = normalizedLink;
|
||||
|
||||
@@ -11,6 +11,8 @@ import {
|
||||
} from "fumadocs-ui/page";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
const { AutoTypeTable } = createTypeTable();
|
||||
|
||||
export const revalidate = false;
|
||||
|
||||
export default async function Page(props: {
|
||||
@@ -20,7 +22,6 @@ export default async function Page(props: {
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
const { AutoTypeTable } = createTypeTable();
|
||||
const MDX = page.data.body;
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,7 +35,7 @@ Currently, the following readers are mapped to specific file types:
|
||||
|
||||
- [TextFileReader](/docs/api/classes/TextFileReader): `.txt`
|
||||
- [PDFReader](/docs/api/classes/PDFReader): `.pdf`
|
||||
- [CSVReader](/docs/api/classes/CSVReader): `.csv`
|
||||
- [PapaCSVReader](/docs/api/classes/PapaCSVReader): `.csv`
|
||||
- [MarkdownReader](/docs/api/classes/MarkdownReader): `.md`
|
||||
- [DocxReader](/docs/api/classes/DocxReader): `.docx`
|
||||
- [HTMLReader](/docs/api/classes/HTMLReader): `.htm`, `.html`
|
||||
|
||||
@@ -12,5 +12,5 @@ Check the [LlamaIndexTS Github](https://github.com/run-llama/LlamaIndexTS) for t
|
||||
|
||||
## API Reference
|
||||
|
||||
- [BaseChatStore](/docs/api/classes/BaseChatStore)
|
||||
- [BaseChatStore](/docs/api/interfaces/BaseChatStore)
|
||||
|
||||
|
||||
@@ -74,4 +74,4 @@ the response is not correct with a score of 2.5
|
||||
|
||||
## API Reference
|
||||
|
||||
- [CorrectnessEvaluator](/docs/api/classes/CorrectnessEvaluator)
|
||||
- [CorrectnessEvaluator](/docs/api/classes/CorrectnessEvaluator)
|
||||
|
||||
@@ -28,21 +28,14 @@ Answer:`;
|
||||
|
||||
### 1. Customizing the default prompt on initialization
|
||||
|
||||
The first method is to create a new instance of a Response Synthesizer (or the module you would like to update the prompt) by using the getResponseSynthesizer function. Instead of passing the custom prompt to the deprecated responseBuilder parameter, call getResponseSynthesizer with the mode as the first argument and supply the new prompt via the options parameter.
|
||||
The first method is to create a new instance of `ResponseSynthesizer` (or the module you would like to update the prompt) and pass the custom prompt to the `responseBuilder` parameter. Then, pass the instance to the `asQueryEngine` method of the index.
|
||||
|
||||
```ts
|
||||
// Create an instance of Response Synthesizer
|
||||
|
||||
// Deprecated usage:
|
||||
// Create an instance of response synthesizer
|
||||
const responseSynthesizer = new ResponseSynthesizer({
|
||||
responseBuilder: new CompactAndRefine(undefined, newTextQaPrompt),
|
||||
});
|
||||
|
||||
// Current usage:
|
||||
const responseSynthesizer = getResponseSynthesizer('compact', {
|
||||
textQATemplate: newTextQaPrompt
|
||||
})
|
||||
|
||||
// Create index
|
||||
const index = await VectorStoreIndex.fromDocuments([document]);
|
||||
|
||||
@@ -82,5 +75,5 @@ const response = await queryEngine.query({
|
||||
|
||||
## API Reference
|
||||
|
||||
- [Response Synthesizer](/docs/llamaindex/modules/response_synthesizer)
|
||||
- [ResponseSynthesizer](/docs/api/classes/ResponseSynthesizer)
|
||||
- [CompactAndRefine](/docs/api/classes/CompactAndRefine)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Response Synthesizer
|
||||
title: ResponseSynthesizer
|
||||
---
|
||||
|
||||
The ResponseSynthesizer is responsible for sending the query, nodes, and prompt templates to the LLM to generate a response. There are a few key modes for generating a response:
|
||||
@@ -12,17 +12,15 @@ The ResponseSynthesizer is responsible for sending the query, nodes, and prompt
|
||||
multiple compact prompts. The same as `refine`, but should result in less LLM calls.
|
||||
- `TreeSummarize`: Given a set of text chunks and the query, recursively construct a tree
|
||||
and return the root node as the response. Good for summarization purposes.
|
||||
- `MultiModal`: Combines textual inputs with additional modality-specific metadata to generate an integrated response.
|
||||
It leverages a text QA template to build a prompt that incorporates various input types and produces either streaming or complete responses.
|
||||
This approach is ideal for use cases where enriching the answer with multi-modal context (such as images, audio, or other data)
|
||||
can enhance the output quality.
|
||||
- `SimpleResponseBuilder`: Given a set of text chunks and the query, apply the query to each text
|
||||
chunk while accumulating the responses into an array. Returns a concatenated string of all
|
||||
responses. Good for when you need to run the same query separately against each text
|
||||
chunk.
|
||||
|
||||
```typescript
|
||||
import { NodeWithScore, TextNode, getResponseSynthesizer, responseModeSchema } from "llamaindex";
|
||||
import { NodeWithScore, TextNode, ResponseSynthesizer } from "llamaindex";
|
||||
|
||||
// you can also use responseModeSchema.Enum.refine, responseModeSchema.Enum.tree_summarize, responseModeSchema.Enum.multi_modal
|
||||
// or you can use the CompactAndRefine, Refine, TreeSummarize, or MultiModal classes directly
|
||||
const responseSynthesizer = getResponseSynthesizer(responseModeSchema.Enum.compact);
|
||||
const responseSynthesizer = new ResponseSynthesizer();
|
||||
|
||||
const nodesWithScore: NodeWithScore[] = [
|
||||
{
|
||||
@@ -57,9 +55,8 @@ for await (const chunk of stream) {
|
||||
|
||||
## API Reference
|
||||
|
||||
- [getResponseSynthesizer](/docs/api/functions/getResponseSynthesizer)
|
||||
- [responseModeSchema](/docs/api/variables/responseModeSchema)
|
||||
- [ResponseSynthesizer](/docs/api/classes/ResponseSynthesizer)
|
||||
- [Refine](/docs/api/classes/Refine)
|
||||
- [CompactAndRefine](/docs/api/classes/CompactAndRefine)
|
||||
- [TreeSummarize](/docs/api/classes/TreeSummarize)
|
||||
- [MultiModal](/docs/api/classes/MultiModal)
|
||||
- [SimpleResponseBuilder](/docs/api/classes/SimpleResponseBuilder)
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
{
|
||||
"plugin": ["typedoc-plugin-markdown", "typedoc-plugin-merge-modules"],
|
||||
"entryPoints": [
|
||||
"../../packages/{,**/}index.ts",
|
||||
"../../packages/readers/src/*.ts",
|
||||
"../../packages/cloud/src/{reader,utils}.ts"
|
||||
],
|
||||
"entryPoints": ["../../packages/**/src/index.ts"],
|
||||
"exclude": [
|
||||
"../../packages/autotool/**/src/index.ts",
|
||||
"../../packages/cloud/src/client/index.ts",
|
||||
"**/node_modules/**",
|
||||
"**/dist/**",
|
||||
"**/test/**",
|
||||
|
||||
@@ -42,7 +42,6 @@ export class OpenAI implements LLM {
|
||||
contextWindow: 2048,
|
||||
tokenizer: undefined,
|
||||
isFunctionCallingModel: true,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +50,6 @@ export default tseslint.config(
|
||||
"**/lib/*",
|
||||
"**/deps/**",
|
||||
"**/.next/**",
|
||||
"**/.source/**", // Ignore .source directories
|
||||
"!.git", // Don't ignore .git directory
|
||||
"**/.*", // Ignore all dot files and directories
|
||||
"**/node_modules/**",
|
||||
"**/build/**",
|
||||
"**/.docusaurus/**",
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { OpenAI } from "@llamaindex/openai";
|
||||
import { wiki } from "@llamaindex/tools";
|
||||
import { AgentStream, agent } from "llamaindex";
|
||||
import { WikipediaTool } from "../wiki";
|
||||
|
||||
async function main() {
|
||||
const llm = new OpenAI({ model: "gpt-4-turbo" });
|
||||
const wikiTool = new WikipediaTool();
|
||||
|
||||
const workflow = agent({
|
||||
tools: [wiki()],
|
||||
tools: [wikiTool],
|
||||
llm,
|
||||
verbose: false,
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import os from "os";
|
||||
import { z } from "zod";
|
||||
|
||||
import { wiki } from "@llamaindex/tools";
|
||||
import { WikipediaTool } from "../wiki";
|
||||
const llm = openai({
|
||||
model: "gpt-4o-mini",
|
||||
});
|
||||
@@ -46,7 +46,7 @@ async function main() {
|
||||
description:
|
||||
"Responsible for gathering relevant information from the internet",
|
||||
systemPrompt: `You are a research agent. Your role is to gather information from the internet using the provided tools and then transfer this information to the report agent for content creation.`,
|
||||
tools: [wiki()],
|
||||
tools: [new WikipediaTool()],
|
||||
canHandoffTo: [reportAgent],
|
||||
llm,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { anthropic } from "@llamaindex/anthropic";
|
||||
import { wiki } from "@llamaindex/tools";
|
||||
import { agent, tool } from "llamaindex";
|
||||
import { z } from "zod";
|
||||
import { WikipediaTool } from "../wiki";
|
||||
|
||||
const workflow = agent({
|
||||
tools: [
|
||||
@@ -13,7 +13,7 @@ const workflow = agent({
|
||||
}),
|
||||
execute: ({ location }) => `The weather in ${location} is sunny`,
|
||||
}),
|
||||
wiki(),
|
||||
new WikipediaTool(),
|
||||
],
|
||||
llm: anthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY,
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { gemini, GEMINI_MODEL } from "@llamaindex/google";
|
||||
|
||||
(async () => {
|
||||
if (!process.env.GOOGLE_API_KEY) {
|
||||
throw new Error("Please set the GOOGLE_API_KEY environment variable.");
|
||||
}
|
||||
const llm = gemini({
|
||||
model: GEMINI_MODEL.GEMINI_PRO_LATEST,
|
||||
});
|
||||
const stream = await llm.chat({
|
||||
messages: [
|
||||
{ content: "You want to talk in rhymes.", role: "system" },
|
||||
{
|
||||
content:
|
||||
"How much wood would a woodchuck chuck if a woodchuck could chuck wood?",
|
||||
role: "user",
|
||||
},
|
||||
],
|
||||
stream: true,
|
||||
});
|
||||
for await (const chunk of stream) {
|
||||
process.stdout.write(chunk.delta);
|
||||
}
|
||||
console.log("\n\ndone");
|
||||
})();
|
||||
+12
-39
@@ -1,5 +1,4 @@
|
||||
import { OpenAI } from "@llamaindex/openai";
|
||||
import { z } from "zod";
|
||||
|
||||
// Example using OpenAI's chat API to extract JSON from a sales call transcript
|
||||
// using json_mode see https://platform.openai.com/docs/guides/text-generation/json-mode for more details
|
||||
@@ -7,47 +6,22 @@ import { z } from "zod";
|
||||
const transcript =
|
||||
"[Phone rings]\n\nJohn: Hello, this is John.\n\nSarah: Hi John, this is Sarah from XYZ Company. I'm calling to discuss our new product, the XYZ Widget, and see if it might be a good fit for your business.\n\nJohn: Hi Sarah, thanks for reaching out. I'm definitely interested in learning more about the XYZ Widget. Can you give me a quick overview of what it does?\n\nSarah: Of course! The XYZ Widget is a cutting-edge tool that helps businesses streamline their workflow and improve productivity. It's designed to automate repetitive tasks and provide real-time data analytics to help you make informed decisions.\n\nJohn: That sounds really interesting. I can see how that could benefit our team. Do you have any case studies or success stories from other companies who have used the XYZ Widget?\n\nSarah: Absolutely, we have several case studies that I can share with you. I'll send those over along with some additional information about the product. I'd also love to schedule a demo for you and your team to see the XYZ Widget in action.\n\nJohn: That would be great. I'll make sure to review the case studies and then we can set up a time for the demo. In the meantime, are there any specific action items or next steps we should take?\n\nSarah: Yes, I'll send over the information and then follow up with you to schedule the demo. In the meantime, feel free to reach out if you have any questions or need further information.\n\nJohn: Sounds good, I appreciate your help Sarah. I'm looking forward to learning more about the XYZ Widget and seeing how it can benefit our business.\n\nSarah: Thank you, John. I'll be in touch soon. Have a great day!\n\nJohn: You too, bye.";
|
||||
|
||||
const exampleSchema = z.object({
|
||||
summary: z.string(),
|
||||
products: z.array(z.string()),
|
||||
rep_name: z.string(),
|
||||
prospect_name: z.string(),
|
||||
action_items: z.array(z.string()),
|
||||
});
|
||||
|
||||
const example = {
|
||||
summary:
|
||||
"High-level summary of the call transcript. Should not exceed 3 sentences.",
|
||||
products: ["product 1", "product 2"],
|
||||
rep_name: "Name of the sales rep",
|
||||
prospect_name: "Name of the prospect",
|
||||
action_items: ["action item 1", "action item 2"],
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const llm = new OpenAI({
|
||||
model: "gpt-4o",
|
||||
model: "gpt-4-1106-preview",
|
||||
additionalChatOptions: { response_format: { type: "json_object" } },
|
||||
});
|
||||
|
||||
//response format as zod schema
|
||||
const example = {
|
||||
summary:
|
||||
"High-level summary of the call transcript. Should not exceed 3 sentences.",
|
||||
products: ["product 1", "product 2"],
|
||||
rep_name: "Name of the sales rep",
|
||||
prospect_name: "Name of the prospect",
|
||||
action_items: ["action item 1", "action item 2"],
|
||||
};
|
||||
|
||||
const response = await llm.chat({
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: `You are an expert assistant for summarizing and extracting insights from sales call transcripts.`,
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: `Here is the transcript: \n------\n${transcript}\n------`,
|
||||
},
|
||||
],
|
||||
responseFormat: exampleSchema,
|
||||
});
|
||||
|
||||
console.log(response.message.content);
|
||||
|
||||
//response format as json_object
|
||||
const response2 = await llm.chat({
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
@@ -60,10 +34,9 @@ async function main() {
|
||||
content: `Here is the transcript: \n------\n${transcript}\n------`,
|
||||
},
|
||||
],
|
||||
responseFormat: { type: "json_object" },
|
||||
});
|
||||
|
||||
console.log(response2.message.content);
|
||||
console.log(response.message.content);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { mistral } from "@llamaindex/mistral";
|
||||
import { wiki } from "@llamaindex/tools";
|
||||
import { agent, tool } from "llamaindex";
|
||||
import { z } from "zod";
|
||||
|
||||
const workflow = agent({
|
||||
tools: [
|
||||
tool({
|
||||
name: "weather",
|
||||
description: "Get the weather",
|
||||
parameters: z.object({
|
||||
location: z.string().describe("The location to get the weather for"),
|
||||
}),
|
||||
execute: ({ location }) => `The weather in ${location} is sunny`,
|
||||
}),
|
||||
wiki(),
|
||||
],
|
||||
llm: mistral({
|
||||
apiKey: process.env.MISTRAL_API_KEY,
|
||||
model: "mistral-small-latest",
|
||||
}),
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const result = await workflow.run(
|
||||
"What is the weather in New York? What's the history of New York from Wikipedia in 3 sentences?",
|
||||
);
|
||||
console.log(result.data);
|
||||
}
|
||||
|
||||
void main();
|
||||
@@ -49,7 +49,6 @@
|
||||
"@llamaindex/together": "^0.0.5",
|
||||
"@llamaindex/jinaai": "^0.0.5",
|
||||
"@llamaindex/perplexity": "^0.0.2",
|
||||
"@llamaindex/tools": "^0.0.1",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@pinecone-database/pinecone": "^4.0.0",
|
||||
"@vercel/postgres": "^0.10.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { openai } from "@ai-sdk/openai";
|
||||
import { wiki } from "@llamaindex/tools";
|
||||
import { VercelLLM } from "@llamaindex/vercel";
|
||||
import { LLMAgent } from "llamaindex";
|
||||
import { WikipediaTool } from "../wiki";
|
||||
|
||||
async function main() {
|
||||
// Create an instance of VercelLLM with the OpenAI model
|
||||
@@ -33,7 +33,7 @@ async function main() {
|
||||
console.log("\n=== Test 3: Using LLMAgent with WikipediaTool ===");
|
||||
const agent = new LLMAgent({
|
||||
llm: vercelLLM,
|
||||
tools: [wiki()],
|
||||
tools: [new WikipediaTool()],
|
||||
});
|
||||
|
||||
const { message } = await agent.chat({
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/** Example of a tool that uses Wikipedia */
|
||||
|
||||
import type { JSONSchemaType } from "ajv";
|
||||
import type { BaseTool, ToolMetadata } from "llamaindex";
|
||||
import { default as wiki } from "wikipedia";
|
||||
|
||||
type WikipediaParameter = {
|
||||
query: string;
|
||||
lang?: string;
|
||||
};
|
||||
|
||||
type WikipediaToolParams = {
|
||||
metadata?: ToolMetadata<JSONSchemaType<WikipediaParameter>>;
|
||||
};
|
||||
|
||||
const DEFAULT_META_DATA: ToolMetadata<JSONSchemaType<WikipediaParameter>> = {
|
||||
name: "wikipedia_search",
|
||||
description: "A tool that uses a query engine to search Wikipedia.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: {
|
||||
type: "string",
|
||||
description: "The query to search for",
|
||||
},
|
||||
lang: {
|
||||
type: "string",
|
||||
description: "The language to search in",
|
||||
nullable: true,
|
||||
},
|
||||
},
|
||||
required: ["query"],
|
||||
},
|
||||
};
|
||||
|
||||
export class WikipediaTool implements BaseTool<WikipediaParameter> {
|
||||
private readonly DEFAULT_LANG = "en";
|
||||
metadata: ToolMetadata<JSONSchemaType<WikipediaParameter>>;
|
||||
|
||||
constructor(params?: WikipediaToolParams) {
|
||||
this.metadata = params?.metadata || DEFAULT_META_DATA;
|
||||
}
|
||||
|
||||
async loadData(
|
||||
page: string,
|
||||
lang: string = this.DEFAULT_LANG,
|
||||
): Promise<string> {
|
||||
wiki.setLang(lang);
|
||||
const pageResult = await wiki.page(page, { autoSuggest: false });
|
||||
const content = await pageResult.content();
|
||||
return content;
|
||||
}
|
||||
|
||||
async call({
|
||||
query,
|
||||
lang = this.DEFAULT_LANG,
|
||||
}: WikipediaParameter): Promise<string> {
|
||||
const searchResult = await wiki.search(query);
|
||||
if (searchResult.results.length === 0) return "No search results.";
|
||||
return await this.loadData(searchResult.results[0].title, lang);
|
||||
}
|
||||
}
|
||||
@@ -46,8 +46,5 @@
|
||||
"*.{json,md,yml}": [
|
||||
"prettier --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"p-retry": "^6.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
+118
-203
@@ -1,8 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { type Client, createClient, createConfig } from "@hey-api/client-fetch";
|
||||
import { Document, FileReader } from "@llamaindex/core/schema";
|
||||
import { fs, getEnv, path } from "@llamaindex/env";
|
||||
import pRetry from "p-retry";
|
||||
import {
|
||||
type Body_upload_file_api_v1_parsing_upload_post,
|
||||
type ParserLanguages,
|
||||
@@ -17,18 +15,16 @@ import {
|
||||
import { sleep } from "./utils";
|
||||
|
||||
export type Language = ParserLanguages;
|
||||
|
||||
export type ResultType = "text" | "markdown" | "json";
|
||||
|
||||
// Export the backoff pattern type.
|
||||
export type BackoffPattern = "constant" | "linear" | "exponential";
|
||||
|
||||
// TODO: should move into @llamaindex/env
|
||||
//todo: should move into @llamaindex/env
|
||||
type WriteStream = {
|
||||
write: (text: string) => void;
|
||||
};
|
||||
|
||||
// Do not modify this variable or cause type errors
|
||||
// eslint-disable-next-line no-var
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-var
|
||||
var process: any;
|
||||
|
||||
/**
|
||||
@@ -45,57 +41,48 @@ export class LlamaParseReader extends FileReader {
|
||||
// The result type for the parser.
|
||||
resultType: ResultType = "text";
|
||||
// The interval in seconds to check if the parsing is done.
|
||||
checkInterval: number = 1;
|
||||
checkInterval = 1;
|
||||
// The maximum timeout in seconds to wait for the parsing to finish.
|
||||
maxTimeout = 2000;
|
||||
// Whether to print the progress of the parsing.
|
||||
verbose = true;
|
||||
// The language to parse the file in.
|
||||
// The language of the text to parse.
|
||||
language: ParserLanguages[] = ["en"];
|
||||
|
||||
// New polling options:
|
||||
// Controls the backoff mode: "constant", "linear", or "exponential".
|
||||
backoffPattern: BackoffPattern = "linear";
|
||||
// Maximum interval in seconds between polls.
|
||||
maxCheckInterval: number = 5;
|
||||
// Maximum number of retryable errors before giving up.
|
||||
maxErrorCount: number = 4;
|
||||
|
||||
// The parsing instruction for the parser. Backend default is an empty string.
|
||||
parsingInstruction?: string | undefined;
|
||||
// Whether to ignore diagonal text (when the text rotation in degrees is not 0, 90, 180, or 270). Backend default is false.
|
||||
// Wether to ignore diagonal text (when the text rotation in degrees is not 0, 90, 180 or 270, so not a horizontal or vertical text). Backend default is false.
|
||||
skipDiagonalText?: boolean | undefined;
|
||||
// Whether to ignore the cache and re-process the document. Documents are cached for 48 hours after job completion. Backend default is false.
|
||||
// Wheter to ignore the cache and re-process the document. All documents are kept in cache for 48hours after the job was completed to avoid processing the same document twice. Backend default is false.
|
||||
invalidateCache?: boolean | undefined;
|
||||
// Whether the document should not be cached. Backend default is false.
|
||||
// Wether the document should not be cached in the first place. Backend default is false.
|
||||
doNotCache?: boolean | undefined;
|
||||
// Whether to use a faster mode to extract text (skipping OCR and table/heading reconstruction). Not compatible with gpt4oMode. Backend default is false.
|
||||
// Wether to use a faster mode to extract text from documents. This mode will skip OCR of images, and table/heading reconstruction. Note: Non-compatible with gpt4oMode. Backend default is false.
|
||||
fastMode?: boolean | undefined;
|
||||
// Whether to keep columns in the text according to document layout. May reduce reconstruction accuracy and LLM/embedings performance.
|
||||
// Wether to keep column in the text according to document layout. Reduce reconstruction accuracy, and LLM's/embedings performances in most cases.
|
||||
doNotUnrollColumns?: boolean | undefined;
|
||||
// A templated page separator for splitting text. If not set, default is "\n---\n".
|
||||
// A templated page separator to use to split the text. If the results contain `{page_number}` (e.g. JSON mode), it will be replaced by the next page number. If not set the default separator '\\n---\\n' will be used.
|
||||
pageSeparator?: string | undefined;
|
||||
// A templated prefix to add at the beginning of each page.
|
||||
//A templated prefix to add to the beginning of each page. If the results contain `{page_number}`, it will be replaced by the page number.>
|
||||
pagePrefix?: string | undefined;
|
||||
// A templated suffix to add at the end of each page.
|
||||
// A templated suffix to add to the end of each page. If the results contain `{page_number}`, it will be replaced by the page number.
|
||||
pageSuffix?: string | undefined;
|
||||
// Deprecated. Use vendorMultimodal params. Whether to use gpt-4o to extract text.
|
||||
// Deprecated. Use vendorMultimodal params. Whether to use gpt-4o to extract text from documents.
|
||||
gpt4oMode: boolean = false;
|
||||
// Deprecated. Use vendorMultimodal params. The API key for GPT-4o. Can be set via LLAMA_CLOUD_GPT4O_API_KEY.
|
||||
// Deprecated. Use vendorMultimodal params. The API key for the GPT-4o API. Optional, lowers the cost of parsing. Can be set as an env variable: LLAMA_CLOUD_GPT4O_API_KEY.
|
||||
gpt4oApiKey?: string | undefined;
|
||||
// The bounding box margins as a string.
|
||||
// The bounding box to use to extract text from documents. Describe as a string containing the bounding box margins.
|
||||
boundingBox?: string | undefined;
|
||||
// The target pages (comma separated list, starting at 0).
|
||||
// The target pages to extract text from documents. Describe as a comma separated list of page numbers. The first page of the document is page 0
|
||||
targetPages?: string | undefined;
|
||||
// Whether to ignore errors during parsing.
|
||||
// Whether or not to ignore and skip errors raised during parsing.
|
||||
ignoreErrors: boolean = true;
|
||||
// Whether to split by page using the pageSeparator (or "\n---\n" as default).
|
||||
// Whether to split by page using the pageSeparator or '\n---\n' as default.
|
||||
splitByPage: boolean = true;
|
||||
// Whether to use the vendor multimodal API.
|
||||
useVendorMultimodalModel: boolean = false;
|
||||
// The model name for the vendor multimodal API.
|
||||
// The model name for the vendor multimodal API
|
||||
vendorMultimodalModelName?: string | undefined;
|
||||
// The API key for the multimodal API. Can be set via LLAMA_CLOUD_VENDOR_MULTIMODAL_API_KEY.
|
||||
// The API key for the multimodal API. Can also be set as an env variable: LLAMA_CLOUD_VENDOR_MULTIMODAL_API_KEY
|
||||
vendorMultimodalApiKey?: string | undefined;
|
||||
|
||||
webhookUrl?: string | undefined;
|
||||
@@ -186,7 +173,7 @@ export class LlamaParseReader extends FileReader {
|
||||
}
|
||||
this.apiKey = apiKey;
|
||||
if (this.baseUrl.endsWith("/")) {
|
||||
this.baseUrl = this.baseUrl.slice(0, -1);
|
||||
this.baseUrl = this.baseUrl.slice(0, -"/".length);
|
||||
}
|
||||
if (this.baseUrl.endsWith("/api/parsing")) {
|
||||
this.baseUrl = this.baseUrl.slice(0, -"/api/parsing".length);
|
||||
@@ -216,19 +203,13 @@ export class LlamaParseReader extends FileReader {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a job for the LlamaParse API.
|
||||
*
|
||||
* @param data - The file data as a Uint8Array.
|
||||
* @param filename - Optional filename for the file.
|
||||
* @returns A Promise resolving to the job ID as a string.
|
||||
*/
|
||||
// Create a job for the LlamaParse API
|
||||
async #createJob(data: Uint8Array, filename?: string): Promise<string> {
|
||||
if (this.verbose) {
|
||||
console.log("Started uploading the file");
|
||||
}
|
||||
|
||||
// TODO: remove Blob usage when we drop Node.js 18 support
|
||||
// todo: remove Blob usage when we drop Node.js 18 support
|
||||
const file: File | Blob =
|
||||
globalThis.File && filename
|
||||
? new File([data], filename)
|
||||
@@ -339,124 +320,87 @@ export class LlamaParseReader extends FileReader {
|
||||
return response.data.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the result of a parsing job.
|
||||
*
|
||||
* Uses a polling loop with retry logic. Each API call is retried
|
||||
* up to maxErrorCount times if it fails with a 5XX or socket error.
|
||||
* The delay between polls increases according to the specified backoffPattern ("constant", "linear", or "exponential"),
|
||||
* capped by maxCheckInterval.
|
||||
*
|
||||
* @param jobId - The job ID.
|
||||
* @param resultType - The type of result to fetch ("text", "json", or "markdown").
|
||||
* @returns A Promise resolving to the job result.
|
||||
*/
|
||||
// Get the result of the job
|
||||
private async getJobResult(
|
||||
jobId: string,
|
||||
resultType: "text" | "json" | "markdown",
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
): Promise<any> {
|
||||
const signal = AbortSignal.timeout(this.maxTimeout * 1000);
|
||||
let tries = 0;
|
||||
let currentInterval = this.checkInterval;
|
||||
|
||||
while (true) {
|
||||
await sleep(currentInterval * 1000);
|
||||
await sleep(this.checkInterval * 1000);
|
||||
|
||||
// Wraps the API call in a retry
|
||||
let result;
|
||||
try {
|
||||
result = await pRetry(
|
||||
() =>
|
||||
getJobApiV1ParsingJobJobIdGet({
|
||||
// Check the job status. If unsuccessful response, checks if maximum timeout has been reached. If reached, throws an error
|
||||
const result = await getJobApiV1ParsingJobJobIdGet({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
query: {
|
||||
project_id: this.project_id ?? null,
|
||||
organization_id: this.organization_id ?? null,
|
||||
},
|
||||
signal,
|
||||
});
|
||||
const { data } = result;
|
||||
|
||||
const status = (data as Record<string, unknown>)["status"];
|
||||
// If job has completed, return the result
|
||||
if (status === "SUCCESS") {
|
||||
let result;
|
||||
switch (resultType) {
|
||||
case "json": {
|
||||
result = await getJobJsonResultApiV1ParsingJobJobIdResultJsonGet({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: { job_id: jobId },
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
query: {
|
||||
project_id: this.project_id ?? null,
|
||||
organization_id: this.organization_id ?? null,
|
||||
},
|
||||
signal: AbortSignal.timeout(this.maxTimeout * 1000),
|
||||
}),
|
||||
{
|
||||
retries: this.maxErrorCount,
|
||||
onFailedAttempt: (error) => {
|
||||
// Retry only on 5XX or socket errors.
|
||||
const status = (error.cause as any)?.response?.status;
|
||||
if (
|
||||
!(
|
||||
(status && status >= 500 && status < 600) ||
|
||||
((error.cause as any)?.code &&
|
||||
((error.cause as any).code === "ECONNRESET" ||
|
||||
(error.cause as any).code === "ETIMEDOUT" ||
|
||||
(error.cause as any).code === "ECONNREFUSED"))
|
||||
)
|
||||
) {
|
||||
throw error;
|
||||
}
|
||||
if (this.verbose) {
|
||||
console.warn(
|
||||
`Attempting to get job ${jobId} result (attempt ${error.attemptNumber}) failed. Retrying...`,
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
} catch (e: any) {
|
||||
throw new Error(
|
||||
`Max error count reached for job ${jobId}: ${e.message}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { data } = result;
|
||||
const status = (data as Record<string, unknown>)["status"];
|
||||
|
||||
if (status === "SUCCESS") {
|
||||
let resultData;
|
||||
switch (resultType) {
|
||||
case "json": {
|
||||
resultData =
|
||||
await getJobJsonResultApiV1ParsingJobJobIdResultJsonGet({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: { job_id: jobId },
|
||||
query: {
|
||||
project_id: this.project_id ?? null,
|
||||
organization_id: this.organization_id ?? null,
|
||||
},
|
||||
signal: AbortSignal.timeout(this.maxTimeout * 1000),
|
||||
});
|
||||
signal,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "markdown": {
|
||||
resultData =
|
||||
await getJobResultApiV1ParsingJobJobIdResultMarkdownGet({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: { job_id: jobId },
|
||||
query: {
|
||||
project_id: this.project_id ?? null,
|
||||
organization_id: this.organization_id ?? null,
|
||||
},
|
||||
signal: AbortSignal.timeout(this.maxTimeout * 1000),
|
||||
});
|
||||
result = await getJobResultApiV1ParsingJobJobIdResultMarkdownGet({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
query: {
|
||||
project_id: this.project_id ?? null,
|
||||
organization_id: this.organization_id ?? null,
|
||||
},
|
||||
signal,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "text": {
|
||||
resultData =
|
||||
await getJobTextResultApiV1ParsingJobJobIdResultTextGet({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: { job_id: jobId },
|
||||
query: {
|
||||
project_id: this.project_id ?? null,
|
||||
organization_id: this.organization_id ?? null,
|
||||
},
|
||||
signal: AbortSignal.timeout(this.maxTimeout * 1000),
|
||||
});
|
||||
result = await getJobTextResultApiV1ParsingJobJobIdResultTextGet({
|
||||
client: this.#client,
|
||||
throwOnError: true,
|
||||
path: {
|
||||
job_id: jobId,
|
||||
},
|
||||
query: {
|
||||
project_id: this.project_id ?? null,
|
||||
organization_id: this.organization_id ?? null,
|
||||
},
|
||||
signal,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resultData.data;
|
||||
return result.data;
|
||||
// If job is still pending, check if maximum timeout has been reached. If reached, throws an error
|
||||
} else if (status === "PENDING") {
|
||||
signal.throwIfAborted();
|
||||
if (this.verbose && tries % 10 === 0) {
|
||||
this.stdout?.write(".");
|
||||
}
|
||||
@@ -464,35 +408,23 @@ export class LlamaParseReader extends FileReader {
|
||||
} else {
|
||||
if (this.verbose) {
|
||||
console.error(
|
||||
`Received error response ${status} for job ${jobId}. Got Error Code: ${data.error_code} and Error Message: ${data.error_message}`,
|
||||
`Recieved Error response ${status} for job ${jobId}. Got Error Code: ${data.error_code} and Error Message: ${data.error_message}`,
|
||||
);
|
||||
}
|
||||
throw new Error(
|
||||
`Failed to parse the file: ${jobId}, status: ${status}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Adjust the polling interval based on the backoff pattern.
|
||||
if (this.backoffPattern === "exponential") {
|
||||
currentInterval = Math.min(currentInterval * 2, this.maxCheckInterval);
|
||||
} else if (this.backoffPattern === "linear") {
|
||||
currentInterval = Math.min(
|
||||
currentInterval + this.checkInterval,
|
||||
this.maxCheckInterval,
|
||||
);
|
||||
} else if (this.backoffPattern === "constant") {
|
||||
currentInterval = this.checkInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from a file and returns an array of Document objects.
|
||||
* To be used with resultType "text" or "markdown".
|
||||
* To be used with resultType = "text" and "markdown"
|
||||
*
|
||||
* @param fileContent - The content of the file as a Uint8Array.
|
||||
* @param filename - Optional filename for the file.
|
||||
* @returns A Promise that resolves to an array of Document objects.
|
||||
* @param {Uint8Array} fileContent - The content of the file to be loaded.
|
||||
* @param {string} filename - The name of the file to be loaded.
|
||||
* @return {Promise<Document[]>} A Promise object that resolves to an array of Document objects.
|
||||
*/
|
||||
async loadDataAsContent(
|
||||
fileContent: Uint8Array,
|
||||
@@ -504,38 +436,42 @@ export class LlamaParseReader extends FileReader {
|
||||
console.log(`Started parsing the file under job id ${jobId}`);
|
||||
}
|
||||
|
||||
// Return results as Document objects.
|
||||
// Return results as Document objects
|
||||
const jobResults = await this.getJobResult(jobId, this.resultType);
|
||||
const resultText = jobResults[this.resultType];
|
||||
|
||||
// Split the text by separator if splitByPage is true.
|
||||
// Split the text by separator if splitByPage is true
|
||||
if (this.splitByPage) {
|
||||
return this.splitTextBySeparator(resultText);
|
||||
}
|
||||
|
||||
return [new Document({ text: resultText })];
|
||||
return [
|
||||
new Document({
|
||||
text: resultText,
|
||||
}),
|
||||
];
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn(
|
||||
`Error while parsing the file with: ${error.message ?? error.detail}`,
|
||||
);
|
||||
if (this.ignoreErrors) {
|
||||
console.warn(
|
||||
`Error while parsing the file: ${error.message ?? error.detail}`,
|
||||
);
|
||||
return [];
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from a file and returns an array of JSON objects.
|
||||
* To be used with resultType "json".
|
||||
* To be used with resultType = "json"
|
||||
*
|
||||
* @param filePathOrContent - The file path or the file content as a Uint8Array.
|
||||
* @returns A Promise that resolves to an array of JSON objects.
|
||||
* @param {string} filePathOrContent - The file path to the file or the content of the file as a Buffer
|
||||
* @return {Promise<Record<string, any>[]>} A Promise that resolves to an array of JSON objects.
|
||||
*/
|
||||
async loadJson(
|
||||
filePathOrContent: string | Uint8Array,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
): Promise<Record<string, any>[]> {
|
||||
let jobId;
|
||||
const isFilePath = typeof filePathOrContent === "string";
|
||||
@@ -543,7 +479,7 @@ export class LlamaParseReader extends FileReader {
|
||||
const data = isFilePath
|
||||
? await fs.readFile(filePathOrContent)
|
||||
: filePathOrContent;
|
||||
// Create a job for the file.
|
||||
// Creates a job for the file
|
||||
jobId = await this.#createJob(
|
||||
data,
|
||||
isFilePath ? path.basename(filePathOrContent) : undefined,
|
||||
@@ -552,14 +488,14 @@ export class LlamaParseReader extends FileReader {
|
||||
console.log(`Started parsing the file under job id ${jobId}`);
|
||||
}
|
||||
|
||||
// Return results as an array of JSON objects.
|
||||
// Return results as an array of JSON objects (same format as Python version of the reader)
|
||||
const resultJson = await this.getJobResult(jobId, "json");
|
||||
resultJson.job_id = jobId;
|
||||
resultJson.file_path = isFilePath ? filePathOrContent : undefined;
|
||||
return [resultJson];
|
||||
} catch (e) {
|
||||
console.error(`Error while parsing the file under job id ${jobId}`, e);
|
||||
if (this.ignoreErrors) {
|
||||
console.error(`Error while parsing the file under job id ${jobId}`, e);
|
||||
return [];
|
||||
} else {
|
||||
throw e;
|
||||
@@ -569,24 +505,27 @@ export class LlamaParseReader extends FileReader {
|
||||
|
||||
/**
|
||||
* Downloads and saves images from a given JSON result to a specified download path.
|
||||
* Currently only supports resultType "json".
|
||||
* Currently only supports resultType = "json"
|
||||
*
|
||||
* @param jsonResult - The JSON result containing image information.
|
||||
* @param downloadPath - The path where the downloaded images will be saved.
|
||||
* @returns A Promise that resolves to an array of image objects.
|
||||
* @param {Record<string, any>[]} jsonResult - The JSON result containing image information.
|
||||
* @param {string} downloadPath - The path to save the downloaded images.
|
||||
* @return {Promise<Record<string, any>[]>} A Promise that resolves to an array of image objects.
|
||||
*/
|
||||
async getImages(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
jsonResult: Record<string, any>[],
|
||||
downloadPath: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
): Promise<Record<string, any>[]> {
|
||||
try {
|
||||
// Create download directory if it doesn't exist (checks for write access).
|
||||
// Create download directory if it doesn't exist (Actually check for write access, not existence, since fsPromises does not have a `existsSync` method)
|
||||
try {
|
||||
await fs.access(downloadPath);
|
||||
} catch {
|
||||
await fs.mkdir(downloadPath, { recursive: true });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const images: Record<string, any>[] = [];
|
||||
for (const result of jsonResult) {
|
||||
const jobId = result.job_id;
|
||||
@@ -602,7 +541,7 @@ export class LlamaParseReader extends FileReader {
|
||||
imageName,
|
||||
);
|
||||
await this.fetchAndSaveImage(imageName, imagePath, jobId);
|
||||
// Assign metadata to the image.
|
||||
// Assign metadata to the image
|
||||
image.path = imagePath;
|
||||
image.job_id = jobId;
|
||||
image.original_pdf_path = result.file_path;
|
||||
@@ -622,14 +561,6 @@ export class LlamaParseReader extends FileReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the file path for an image.
|
||||
*
|
||||
* @param downloadPath - The base download directory.
|
||||
* @param jobId - The job ID.
|
||||
* @param imageName - The image name.
|
||||
* @returns A Promise that resolves to the full image path.
|
||||
*/
|
||||
private async getImagePath(
|
||||
downloadPath: string,
|
||||
jobId: string,
|
||||
@@ -638,13 +569,6 @@ export class LlamaParseReader extends FileReader {
|
||||
return path.join(downloadPath, `${jobId}-${imageName}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an image from the API and saves it to the specified path.
|
||||
*
|
||||
* @param imageName - The name of the image.
|
||||
* @param imagePath - The local path to save the image.
|
||||
* @param jobId - The associated job ID.
|
||||
*/
|
||||
private async fetchAndSaveImage(
|
||||
imageName: string,
|
||||
imagePath: string,
|
||||
@@ -666,21 +590,18 @@ export class LlamaParseReader extends FileReader {
|
||||
throw new Error(`Failed to download image: ${response.error.detail}`);
|
||||
}
|
||||
const blob = (await response.data) as Blob;
|
||||
// Write the image buffer to the specified imagePath.
|
||||
// Write the image buffer to the specified imagePath
|
||||
await fs.writeFile(imagePath, new Uint8Array(await blob.arrayBuffer()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out invalid values (null, undefined, empty string) for specific parameters.
|
||||
*
|
||||
* @param params - The parameters object.
|
||||
* @param keysToCheck - The keys to check for valid values.
|
||||
* @returns A new object with filtered parameters.
|
||||
*/
|
||||
// Filters out invalid values (null, undefined, empty string) of specific params.
|
||||
private filterSpecificParams(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
params: Record<string, any>,
|
||||
keysToCheck: string[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
): Record<string, any> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const filteredParams: Record<string, any> = {};
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
if (keysToCheck.includes(key)) {
|
||||
@@ -694,12 +615,6 @@ export class LlamaParseReader extends FileReader {
|
||||
return filteredParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits text into Document objects using the page separator.
|
||||
*
|
||||
* @param text - The text to be split.
|
||||
* @returns An array of Document objects.
|
||||
*/
|
||||
private splitTextBySeparator(text: string): Document[] {
|
||||
const separator = this.pageSeparator ?? "\n---\n";
|
||||
const textChunks = text.split(separator);
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
} from "./utils";
|
||||
|
||||
export class AmazonProvider extends Provider<ConverseStreamOutput> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getResultFromResponse(response: Record<string, any>): ConverseResponse {
|
||||
return JSON.parse(toUtf8(response.body));
|
||||
}
|
||||
@@ -53,7 +52,7 @@ export class AmazonProvider extends Provider<ConverseStreamOutput> {
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: ResponseStream): string {
|
||||
const event: ConverseStreamOutput | undefined =
|
||||
let event: ConverseStreamOutput | undefined =
|
||||
this.getStreamingEventResponse(response);
|
||||
if (!event || !event.contentBlockDelta) return "";
|
||||
const delta: ContentBlockDelta | undefined = event.contentBlockDelta.delta;
|
||||
|
||||
@@ -56,7 +56,7 @@ export const mapImageContent = (imageUrl: string): ImageBlock => {
|
||||
mimeType as keyof typeof ACCEPTED_IMAGE_MIME_TYPE_FORMAT_MAP
|
||||
],
|
||||
|
||||
// @ts-expect-error: there's a mistake in the "@aws-sdk/client-bedrock-runtime" compared to the actual api
|
||||
// @ts-ignore: there's a mistake in the "@aws-sdk/client-bedrock-runtime" compared to the actual api
|
||||
source: { bytes: data },
|
||||
};
|
||||
};
|
||||
|
||||
@@ -381,7 +381,6 @@ export class Bedrock extends ToolCallLLM<BedrockAdditionalChatOptions> {
|
||||
maxTokens: this.maxTokens,
|
||||
contextWindow: BEDROCK_FOUNDATION_LLMS[this.model] ?? 128000,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -20,5 +20,4 @@ export const DEFAULT_NAMESPACE = "docstore";
|
||||
//#region llama cloud
|
||||
export const DEFAULT_PROJECT_NAME = "Default";
|
||||
export const DEFAULT_BASE_URL = "https://api.cloud.llamaindex.ai";
|
||||
export const DEFAULT_EU_BASE_URL = "https://api.cloud.eu.llamaindex.ai";
|
||||
//#endregion
|
||||
|
||||
@@ -28,12 +28,11 @@ export abstract class BaseLLM<
|
||||
async complete(
|
||||
params: LLMCompletionParamsStreaming | LLMCompletionParamsNonStreaming,
|
||||
): Promise<CompletionResponse | AsyncIterable<CompletionResponse>> {
|
||||
const { prompt, stream, responseFormat } = params;
|
||||
const { prompt, stream } = params;
|
||||
if (stream) {
|
||||
const stream = await this.chat({
|
||||
messages: [{ content: prompt, role: "user" }],
|
||||
stream: true,
|
||||
...(responseFormat ? { responseFormat } : {}),
|
||||
});
|
||||
return streamConverter(stream, (chunk) => {
|
||||
return {
|
||||
@@ -42,12 +41,9 @@ export abstract class BaseLLM<
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const chatResponse = await this.chat({
|
||||
messages: [{ content: prompt, role: "user" }],
|
||||
...(responseFormat ? { responseFormat } : {}),
|
||||
});
|
||||
|
||||
return {
|
||||
text: extractText(chatResponse.message.content),
|
||||
raw: chatResponse.raw,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { Tokenizers } from "@llamaindex/env/tokenizers";
|
||||
import type { JSONSchemaType } from "ajv";
|
||||
import { z } from "zod";
|
||||
import type { JSONObject, JSONValue } from "../global";
|
||||
|
||||
/**
|
||||
@@ -107,7 +106,6 @@ export type LLMMetadata = {
|
||||
maxTokens?: number | undefined;
|
||||
contextWindow: number;
|
||||
tokenizer: Tokenizers | undefined;
|
||||
structuredOutput: boolean;
|
||||
};
|
||||
|
||||
export interface LLMChatParamsBase<
|
||||
@@ -117,7 +115,6 @@ export interface LLMChatParamsBase<
|
||||
messages: ChatMessage<AdditionalMessageOptions>[];
|
||||
additionalChatOptions?: AdditionalChatOptions;
|
||||
tools?: BaseTool[];
|
||||
responseFormat?: z.ZodType | object;
|
||||
}
|
||||
|
||||
export interface LLMChatParamsStreaming<
|
||||
@@ -136,7 +133,6 @@ export interface LLMChatParamsNonStreaming<
|
||||
|
||||
export interface LLMCompletionParamsBase {
|
||||
prompt: MessageContent;
|
||||
responseFormat?: z.ZodType | object;
|
||||
}
|
||||
|
||||
export interface LLMCompletionParamsStreaming extends LLMCompletionParamsBase {
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
} from "./base-synthesizer";
|
||||
import { createMessageContent } from "./utils";
|
||||
|
||||
export const responseModeSchema = z.enum([
|
||||
const responseModeSchema = z.enum([
|
||||
"refine",
|
||||
"compact",
|
||||
"tree_summarize",
|
||||
@@ -35,7 +35,7 @@ export type ResponseMode = z.infer<typeof responseModeSchema>;
|
||||
/**
|
||||
* A response builder that uses the query to ask the LLM generate a better response using multiple text chunks.
|
||||
*/
|
||||
export class Refine extends BaseSynthesizer {
|
||||
class Refine extends BaseSynthesizer {
|
||||
textQATemplate: TextQAPrompt;
|
||||
refineTemplate: RefinePrompt;
|
||||
|
||||
@@ -213,7 +213,7 @@ export class Refine extends BaseSynthesizer {
|
||||
/**
|
||||
* CompactAndRefine is a slight variation of Refine that first compacts the text chunks into the smallest possible number of chunks.
|
||||
*/
|
||||
export class CompactAndRefine extends Refine {
|
||||
class CompactAndRefine extends Refine {
|
||||
async getResponse(
|
||||
query: MessageContent,
|
||||
nodes: NodeWithScore[],
|
||||
@@ -267,7 +267,7 @@ export class CompactAndRefine extends Refine {
|
||||
/**
|
||||
* TreeSummarize repacks the text chunks into the smallest possible number of chunks and then summarizes them, then recursively does so until there's one chunk left.
|
||||
*/
|
||||
export class TreeSummarize extends BaseSynthesizer {
|
||||
class TreeSummarize extends BaseSynthesizer {
|
||||
summaryTemplate: TreeSummarizePrompt;
|
||||
|
||||
constructor(
|
||||
@@ -370,7 +370,7 @@ export class TreeSummarize extends BaseSynthesizer {
|
||||
}
|
||||
}
|
||||
|
||||
export class MultiModal extends BaseSynthesizer {
|
||||
class MultiModal extends BaseSynthesizer {
|
||||
metadataMode: MetadataMode;
|
||||
textQATemplate: TextQAPrompt;
|
||||
|
||||
|
||||
@@ -2,15 +2,7 @@ export {
|
||||
BaseSynthesizer,
|
||||
type BaseSynthesizerOptions,
|
||||
} from "./base-synthesizer";
|
||||
export {
|
||||
CompactAndRefine,
|
||||
MultiModal,
|
||||
Refine,
|
||||
TreeSummarize,
|
||||
getResponseSynthesizer,
|
||||
responseModeSchema,
|
||||
type ResponseMode,
|
||||
} from "./factory";
|
||||
export { getResponseSynthesizer, type ResponseMode } from "./factory";
|
||||
export type {
|
||||
SynthesizeEndEvent,
|
||||
SynthesizeQuery,
|
||||
|
||||
@@ -35,7 +35,6 @@ export class MockLLM extends ToolCallLLM {
|
||||
topP: 0.5,
|
||||
contextWindow: 1024,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,6 @@ describe("sentence splitter", () => {
|
||||
id_: docId,
|
||||
text: "This is a test sentence. This is another test sentence.",
|
||||
});
|
||||
|
||||
const nodes = sentenceSplitter.getNodesFromDocuments([doc]);
|
||||
nodes.forEach((node) => {
|
||||
// test node id should match uuid regex
|
||||
|
||||
@@ -191,7 +191,6 @@ export class Anthropic extends ToolCallLLM<
|
||||
].contextWindow
|
||||
: 200000,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
type ModelParams as GoogleModelParams,
|
||||
type RequestOptions as GoogleRequestOptions,
|
||||
type GenerateContentStreamResult as GoogleStreamGenerateContentResult,
|
||||
type SafetySetting,
|
||||
} from "@google/generative-ai";
|
||||
|
||||
import { wrapLLMEvent } from "@llamaindex/core/decorator";
|
||||
@@ -89,7 +88,6 @@ const DEFAULT_GEMINI_PARAMS = {
|
||||
export type GeminiConfig = Partial<typeof DEFAULT_GEMINI_PARAMS> & {
|
||||
session?: IGeminiSession;
|
||||
requestOptions?: GoogleRequestOptions;
|
||||
safetySettings?: SafetySetting[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -114,7 +112,7 @@ export class GeminiSession implements IGeminiSession {
|
||||
): GoogleGenerativeModel {
|
||||
return this.gemini.getGenerativeModel(
|
||||
{
|
||||
safetySettings: metadata.safetySettings ?? DEFAULT_SAFETY_SETTINGS,
|
||||
safetySettings: DEFAULT_SAFETY_SETTINGS,
|
||||
...metadata,
|
||||
},
|
||||
requestOpts,
|
||||
@@ -220,7 +218,6 @@ export class Gemini extends ToolCallLLM<GeminiAdditionalChatOptions> {
|
||||
maxTokens?: number | undefined;
|
||||
#requestOptions?: GoogleRequestOptions | undefined;
|
||||
session: IGeminiSession;
|
||||
safetySettings: SafetySetting[];
|
||||
|
||||
constructor(init?: GeminiConfig) {
|
||||
super();
|
||||
@@ -230,14 +227,13 @@ export class Gemini extends ToolCallLLM<GeminiAdditionalChatOptions> {
|
||||
this.maxTokens = init?.maxTokens ?? undefined;
|
||||
this.session = init?.session ?? GeminiSessionStore.get();
|
||||
this.#requestOptions = init?.requestOptions ?? undefined;
|
||||
this.safetySettings = init?.safetySettings ?? DEFAULT_SAFETY_SETTINGS;
|
||||
}
|
||||
|
||||
get supportToolCall(): boolean {
|
||||
return SUPPORT_TOOL_CALL_MODELS.includes(this.model);
|
||||
}
|
||||
|
||||
get metadata(): LLMMetadata & { safetySettings: SafetySetting[] } {
|
||||
get metadata(): LLMMetadata {
|
||||
return {
|
||||
model: this.model,
|
||||
temperature: this.temperature,
|
||||
@@ -245,8 +241,6 @@ export class Gemini extends ToolCallLLM<GeminiAdditionalChatOptions> {
|
||||
maxTokens: this.maxTokens,
|
||||
contextWindow: GEMINI_MODEL_INFO_MAP[this.model].contextWindow,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
safetySettings: this.safetySettings,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -256,7 +250,7 @@ export class Gemini extends ToolCallLLM<GeminiAdditionalChatOptions> {
|
||||
const context = getChatContext(params);
|
||||
const common = {
|
||||
history: context.history,
|
||||
safetySettings: this.safetySettings,
|
||||
safetySettings: DEFAULT_SAFETY_SETTINGS,
|
||||
};
|
||||
|
||||
return params.tools?.length
|
||||
@@ -270,7 +264,7 @@ export class Gemini extends ToolCallLLM<GeminiAdditionalChatOptions> {
|
||||
),
|
||||
},
|
||||
],
|
||||
safetySettings: this.safetySettings,
|
||||
safetySettings: DEFAULT_SAFETY_SETTINGS,
|
||||
}
|
||||
: common;
|
||||
}
|
||||
|
||||
@@ -59,15 +59,14 @@ export class GeminiVertexSession implements IGeminiSession {
|
||||
getGenerativeModel(
|
||||
metadata: VertexModelParams,
|
||||
): VertexGenerativeModelPreview | VertexGenerativeModel {
|
||||
const safetySettings = metadata.safetySettings ?? DEFAULT_SAFETY_SETTINGS;
|
||||
if (this.preview) {
|
||||
return this.vertex.preview.getGenerativeModel({
|
||||
safetySettings,
|
||||
safetySettings: DEFAULT_SAFETY_SETTINGS,
|
||||
...metadata,
|
||||
});
|
||||
}
|
||||
return this.vertex.getGenerativeModel({
|
||||
safetySettings,
|
||||
safetySettings: DEFAULT_SAFETY_SETTINGS,
|
||||
...metadata,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ export class HuggingFaceLLM extends BaseLLM {
|
||||
maxTokens: this.maxTokens,
|
||||
contextWindow: this.contextWindow,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,6 @@ export class HuggingFaceInferenceAPI extends BaseLLM {
|
||||
maxTokens: this.maxTokens,
|
||||
contextWindow: this.contextWindow,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,10 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "bunchee",
|
||||
"dev": "bunchee --watch",
|
||||
"test": "vitest run"
|
||||
"dev": "bunchee --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bunchee": "6.4.0",
|
||||
"vitest": "^2.1.5"
|
||||
"bunchee": "6.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@llamaindex/core": "workspace:*",
|
||||
|
||||
@@ -1,51 +1,21 @@
|
||||
import { wrapEventCaller } from "@llamaindex/core/decorator";
|
||||
import {
|
||||
ToolCallLLM,
|
||||
type BaseTool,
|
||||
BaseLLM,
|
||||
type ChatMessage,
|
||||
type ChatResponse,
|
||||
type ChatResponseChunk,
|
||||
type LLMChatParamsNonStreaming,
|
||||
type LLMChatParamsStreaming,
|
||||
type PartialToolCall,
|
||||
type ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import { extractText } from "@llamaindex/core/utils";
|
||||
import { getEnv } from "@llamaindex/env";
|
||||
import { type Mistral } from "@mistralai/mistralai";
|
||||
import type {
|
||||
AssistantMessage,
|
||||
ChatCompletionRequest,
|
||||
ChatCompletionStreamRequest,
|
||||
ContentChunk,
|
||||
Tool,
|
||||
ToolMessage,
|
||||
} from "@mistralai/mistralai/models/components";
|
||||
import type { ContentChunk } from "@mistralai/mistralai/models/components";
|
||||
|
||||
export const ALL_AVAILABLE_MISTRAL_MODELS = {
|
||||
"mistral-tiny": { contextWindow: 32000 },
|
||||
"mistral-small": { contextWindow: 32000 },
|
||||
"mistral-medium": { contextWindow: 32000 },
|
||||
"mistral-small-latest": { contextWindow: 32000 },
|
||||
"mistral-large-latest": { contextWindow: 131000 },
|
||||
"codestral-latest": { contextWindow: 256000 },
|
||||
"pixtral-large-latest": { contextWindow: 131000 },
|
||||
"mistral-saba-latest": { contextWindow: 32000 },
|
||||
"ministral-3b-latest": { contextWindow: 131000 },
|
||||
"ministral-8b-latest": { contextWindow: 131000 },
|
||||
"mistral-embed": { contextWindow: 8000 },
|
||||
"mistral-moderation-latest": { contextWindow: 8000 },
|
||||
};
|
||||
|
||||
export const TOOL_CALL_MISTRAL_MODELS = [
|
||||
"mistral-small-latest",
|
||||
"mistral-large-latest",
|
||||
"codestral-latest",
|
||||
"pixtral-large-latest",
|
||||
"ministral-8b-latest",
|
||||
"ministral-3b-latest",
|
||||
];
|
||||
|
||||
export class MistralAISession {
|
||||
apiKey: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -76,7 +46,7 @@ export class MistralAISession {
|
||||
/**
|
||||
* MistralAI LLM implementation
|
||||
*/
|
||||
export class MistralAI extends ToolCallLLM<ToolCallLLMMessageOptions> {
|
||||
export class MistralAI extends BaseLLM {
|
||||
// Per completion MistralAI params
|
||||
model: keyof typeof ALL_AVAILABLE_MISTRAL_MODELS;
|
||||
temperature: number;
|
||||
@@ -90,7 +60,7 @@ export class MistralAI extends ToolCallLLM<ToolCallLLMMessageOptions> {
|
||||
|
||||
constructor(init?: Partial<MistralAI>) {
|
||||
super();
|
||||
this.model = init?.model ?? "mistral-small-latest";
|
||||
this.model = init?.model ?? "mistral-small";
|
||||
this.temperature = init?.temperature ?? 0.1;
|
||||
this.topP = init?.topP ?? 1;
|
||||
this.maxTokens = init?.maxTokens ?? undefined;
|
||||
@@ -107,55 +77,11 @@ export class MistralAI extends ToolCallLLM<ToolCallLLMMessageOptions> {
|
||||
maxTokens: this.maxTokens,
|
||||
contextWindow: ALL_AVAILABLE_MISTRAL_MODELS[this.model].contextWindow,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
get supportToolCall() {
|
||||
return TOOL_CALL_MISTRAL_MODELS.includes(this.metadata.model);
|
||||
}
|
||||
|
||||
formatMessages(messages: ChatMessage<ToolCallLLMMessageOptions>[]) {
|
||||
return messages.map((message) => {
|
||||
const options = message.options ?? {};
|
||||
//tool call message
|
||||
if ("toolCall" in options) {
|
||||
return {
|
||||
role: "assistant",
|
||||
content: extractText(message.content),
|
||||
toolCalls: options.toolCall.map((toolCall) => {
|
||||
return {
|
||||
id: toolCall.id,
|
||||
type: "function",
|
||||
function: {
|
||||
name: toolCall.name,
|
||||
arguments: toolCall.input,
|
||||
},
|
||||
};
|
||||
}),
|
||||
} satisfies AssistantMessage;
|
||||
}
|
||||
|
||||
//tool result message
|
||||
if ("toolResult" in options) {
|
||||
return {
|
||||
role: "tool",
|
||||
content: extractText(message.content),
|
||||
toolCallId: options.toolResult.id,
|
||||
} satisfies ToolMessage;
|
||||
}
|
||||
|
||||
return {
|
||||
role: message.role,
|
||||
content: extractText(message.content),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private buildParams(
|
||||
messages: ChatMessage<ToolCallLLMMessageOptions>[],
|
||||
tools?: BaseTool[],
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private buildParams(messages: ChatMessage[]): any {
|
||||
return {
|
||||
model: this.model,
|
||||
temperature: this.temperature,
|
||||
@@ -163,49 +89,25 @@ export class MistralAI extends ToolCallLLM<ToolCallLLMMessageOptions> {
|
||||
topP: this.topP,
|
||||
safeMode: this.safeMode,
|
||||
randomSeed: this.randomSeed,
|
||||
messages: this.formatMessages(messages),
|
||||
tools: tools?.map(MistralAI.toTool),
|
||||
};
|
||||
}
|
||||
|
||||
static toTool(tool: BaseTool): Tool {
|
||||
if (!tool.metadata.parameters) {
|
||||
throw new Error("Tool parameters are required");
|
||||
}
|
||||
|
||||
return {
|
||||
type: "function",
|
||||
function: {
|
||||
name: tool.metadata.name,
|
||||
description: tool.metadata.description,
|
||||
parameters: tool.metadata.parameters,
|
||||
},
|
||||
messages,
|
||||
};
|
||||
}
|
||||
|
||||
chat(
|
||||
params: LLMChatParamsStreaming,
|
||||
): Promise<AsyncIterable<ChatResponseChunk>>;
|
||||
chat(
|
||||
params: LLMChatParamsNonStreaming<ToolCallLLMMessageOptions>,
|
||||
): Promise<ChatResponse>;
|
||||
chat(params: LLMChatParamsNonStreaming): Promise<ChatResponse>;
|
||||
async chat(
|
||||
params: LLMChatParamsNonStreaming | LLMChatParamsStreaming,
|
||||
): Promise<
|
||||
| ChatResponse<ToolCallLLMMessageOptions>
|
||||
| AsyncIterable<ChatResponseChunk<ToolCallLLMMessageOptions>>
|
||||
> {
|
||||
const { messages, stream, tools } = params;
|
||||
): Promise<ChatResponse | AsyncIterable<ChatResponseChunk>> {
|
||||
const { messages, stream } = params;
|
||||
// Streaming
|
||||
if (stream) {
|
||||
return this.streamChat(messages, tools);
|
||||
return this.streamChat(params);
|
||||
}
|
||||
// Non-streaming
|
||||
const client = await this.session.getClient();
|
||||
const buildParams = this.buildParams(messages, tools);
|
||||
const response = await client.chat.complete(
|
||||
buildParams as ChatCompletionRequest,
|
||||
);
|
||||
const response = await client.chat.complete(this.buildParams(messages));
|
||||
|
||||
if (!response || !response.choices || !response.choices[0]) {
|
||||
throw new Error("Unexpected response format from Mistral API");
|
||||
@@ -219,100 +121,28 @@ export class MistralAI extends ToolCallLLM<ToolCallLLMMessageOptions> {
|
||||
message: {
|
||||
role: "assistant",
|
||||
content: this.extractContentAsString(content),
|
||||
options: response.choices[0]!.message?.toolCalls
|
||||
? {
|
||||
toolCall: response.choices[0]!.message.toolCalls.map(
|
||||
(toolCall) => ({
|
||||
id: toolCall.id,
|
||||
name: toolCall.function.name,
|
||||
input: this.extractArgumentsAsString(
|
||||
toolCall.function.arguments,
|
||||
),
|
||||
}),
|
||||
),
|
||||
}
|
||||
: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@wrapEventCaller
|
||||
protected async *streamChat(
|
||||
messages: ChatMessage[],
|
||||
tools?: BaseTool[],
|
||||
): AsyncIterable<ChatResponseChunk<ToolCallLLMMessageOptions>> {
|
||||
protected async *streamChat({
|
||||
messages,
|
||||
}: LLMChatParamsStreaming): AsyncIterable<ChatResponseChunk> {
|
||||
const client = await this.session.getClient();
|
||||
const buildParams = this.buildParams(
|
||||
messages,
|
||||
tools,
|
||||
) as ChatCompletionStreamRequest;
|
||||
const chunkStream = await client.chat.stream(buildParams);
|
||||
|
||||
let currentToolCall: PartialToolCall | null = null;
|
||||
const toolCallMap = new Map<string, PartialToolCall>();
|
||||
const chunkStream = await client.chat.stream(this.buildParams(messages));
|
||||
|
||||
for await (const chunk of chunkStream) {
|
||||
if (!chunk.data?.choices?.[0]?.delta) continue;
|
||||
if (!chunk.data || !chunk.data.choices || !chunk.data.choices.length)
|
||||
continue;
|
||||
|
||||
const choice = chunk.data.choices[0];
|
||||
if (!(choice.delta.content || choice.delta.toolCalls)) continue;
|
||||
|
||||
let shouldEmitToolCall: PartialToolCall | null = null;
|
||||
|
||||
if (choice.delta.toolCalls?.[0]) {
|
||||
const toolCall = choice.delta.toolCalls[0];
|
||||
|
||||
if (toolCall.id) {
|
||||
if (currentToolCall && toolCall.id !== currentToolCall.id) {
|
||||
shouldEmitToolCall = {
|
||||
...currentToolCall,
|
||||
input: JSON.parse(currentToolCall.input),
|
||||
};
|
||||
}
|
||||
|
||||
currentToolCall = {
|
||||
id: toolCall.id,
|
||||
name: toolCall.function!.name!,
|
||||
input: this.extractArgumentsAsString(toolCall.function!.arguments),
|
||||
};
|
||||
|
||||
toolCallMap.set(toolCall.id, currentToolCall!);
|
||||
} else if (currentToolCall && toolCall.function?.arguments) {
|
||||
currentToolCall.input += this.extractArgumentsAsString(
|
||||
toolCall.function.arguments,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const isDone: boolean = choice.finishReason !== null;
|
||||
|
||||
if (isDone && currentToolCall) {
|
||||
//emitting last tool call
|
||||
shouldEmitToolCall = {
|
||||
...currentToolCall,
|
||||
input: JSON.parse(currentToolCall.input),
|
||||
};
|
||||
}
|
||||
if (!choice) continue;
|
||||
|
||||
yield {
|
||||
raw: chunk.data,
|
||||
delta: this.extractContentAsString(choice.delta.content),
|
||||
options: shouldEmitToolCall
|
||||
? { toolCall: [shouldEmitToolCall] }
|
||||
: currentToolCall
|
||||
? { toolCall: [currentToolCall] }
|
||||
: {},
|
||||
};
|
||||
}
|
||||
|
||||
toolCallMap.clear();
|
||||
}
|
||||
|
||||
private extractArgumentsAsString(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
args: string | { [k: string]: any } | null | undefined,
|
||||
): string {
|
||||
return typeof args === "string" ? args : JSON.stringify(args) || "";
|
||||
}
|
||||
|
||||
private extractContentAsString(
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
import type { ChatMessage } from "@llamaindex/core/llms";
|
||||
import { setEnvs } from "@llamaindex/env";
|
||||
import { beforeAll, describe, expect, test } from "vitest";
|
||||
import { MistralAI } from "../src/index";
|
||||
|
||||
beforeAll(() => {
|
||||
setEnvs({
|
||||
MISTRAL_API_KEY: "valid",
|
||||
});
|
||||
});
|
||||
|
||||
describe("Message Formatting", () => {
|
||||
describe("Basic Message Formatting", () => {
|
||||
test("Mistral formats basic messages correctly", () => {
|
||||
const mistral = new MistralAI();
|
||||
const inputMessages: ChatMessage[] = [
|
||||
{
|
||||
content: "You are a helpful assistant.",
|
||||
role: "assistant",
|
||||
},
|
||||
{
|
||||
content: "Hello?",
|
||||
role: "user",
|
||||
},
|
||||
];
|
||||
const expectedOutput = [
|
||||
{
|
||||
content: "You are a helpful assistant.",
|
||||
role: "assistant",
|
||||
},
|
||||
{
|
||||
content: "Hello?",
|
||||
role: "user",
|
||||
},
|
||||
];
|
||||
|
||||
expect(mistral.formatMessages(inputMessages)).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
test("Mistral handles multi-turn conversation correctly", () => {
|
||||
const mistral = new MistralAI();
|
||||
const inputMessages: ChatMessage[] = [
|
||||
{ content: "Hi", role: "user" },
|
||||
{ content: "Hello! How can I help?", role: "assistant" },
|
||||
{ content: "What's the weather?", role: "user" },
|
||||
];
|
||||
const expectedOutput = [
|
||||
{ content: "Hi", role: "user" },
|
||||
{ content: "Hello! How can I help?", role: "assistant" },
|
||||
{ content: "What's the weather?", role: "user" },
|
||||
];
|
||||
expect(mistral.formatMessages(inputMessages)).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Tool Message Formatting", () => {
|
||||
const toolCallMessages: ChatMessage[] = [
|
||||
{
|
||||
role: "user",
|
||||
content: "What's the weather in London?",
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Let me check the weather.",
|
||||
options: {
|
||||
toolCall: [
|
||||
{
|
||||
id: "call_123",
|
||||
name: "weather",
|
||||
input: JSON.stringify({ location: "London" }),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: "The weather in London is sunny, +20°C",
|
||||
options: {
|
||||
toolResult: {
|
||||
id: "call_123",
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
test("Mistral formats tool calls correctly", () => {
|
||||
const mistral = new MistralAI();
|
||||
const expectedOutput = [
|
||||
{
|
||||
role: "user",
|
||||
content: "What's the weather in London?",
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: "Let me check the weather.",
|
||||
toolCalls: [
|
||||
{
|
||||
type: "function",
|
||||
id: "call_123",
|
||||
function: {
|
||||
name: "weather",
|
||||
arguments: '{"location":"London"}',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
role: "tool",
|
||||
content: "The weather in London is sunny, +20°C",
|
||||
toolCallId: "call_123",
|
||||
},
|
||||
];
|
||||
expect(mistral.formatMessages(toolCallMessages)).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -37,17 +37,5 @@
|
||||
"@llamaindex/env": "workspace:*",
|
||||
"ollama": "^0.5.10",
|
||||
"remeda": "^2.17.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^3.24.2",
|
||||
"zod-to-json-schema": "^3.23.3"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"zod": {
|
||||
"optional": true
|
||||
},
|
||||
"zod-to-json-schema": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,22 +57,6 @@ export type OllamaParams = {
|
||||
options?: Partial<Options>;
|
||||
};
|
||||
|
||||
async function getZod() {
|
||||
try {
|
||||
return await import("zod");
|
||||
} catch (e) {
|
||||
throw new Error("zod is required for structured output");
|
||||
}
|
||||
}
|
||||
|
||||
async function getZodToJsonSchema() {
|
||||
try {
|
||||
return await import("zod-to-json-schema");
|
||||
} catch (e) {
|
||||
throw new Error("zod-to-json-schema is required for structured output");
|
||||
}
|
||||
}
|
||||
|
||||
export class Ollama extends ToolCallLLM {
|
||||
supportToolCall: boolean = true;
|
||||
public readonly ollama: OllamaBase;
|
||||
@@ -108,7 +92,6 @@ export class Ollama extends ToolCallLLM {
|
||||
maxTokens: this.options.num_ctx,
|
||||
contextWindow: num_ctx,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -126,7 +109,7 @@ export class Ollama extends ToolCallLLM {
|
||||
): Promise<
|
||||
ChatResponse<ToolCallLLMMessageOptions> | AsyncIterable<ChatResponseChunk>
|
||||
> {
|
||||
const { messages, stream, tools, responseFormat } = params;
|
||||
const { messages, stream, tools } = params;
|
||||
const payload: ChatRequest = {
|
||||
model: this.model,
|
||||
messages: messages.map((message) => {
|
||||
@@ -147,20 +130,9 @@ export class Ollama extends ToolCallLLM {
|
||||
...this.options,
|
||||
},
|
||||
};
|
||||
|
||||
if (tools) {
|
||||
payload.tools = tools.map((tool) => Ollama.toTool(tool));
|
||||
}
|
||||
|
||||
if (responseFormat && this.metadata.structuredOutput) {
|
||||
const [{ zodToJsonSchema }, { z }] = await Promise.all([
|
||||
getZodToJsonSchema(),
|
||||
getZod(),
|
||||
]);
|
||||
if (responseFormat instanceof z.ZodType)
|
||||
payload.format = zodToJsonSchema(responseFormat);
|
||||
}
|
||||
|
||||
if (!stream) {
|
||||
const chatResponse = await this.ollama.chat({
|
||||
...payload,
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
"dependencies": {
|
||||
"@llamaindex/core": "workspace:*",
|
||||
"@llamaindex/env": "workspace:*",
|
||||
"openai": "^4.86.0",
|
||||
"zod": "^3.24.2"
|
||||
"openai": "^4.86.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import type {
|
||||
ClientOptions as OpenAIClientOptions,
|
||||
OpenAI as OpenAILLM,
|
||||
} from "openai";
|
||||
import { zodResponseFormat } from "openai/helpers/zod";
|
||||
import type { ChatModel } from "openai/resources/chat/chat";
|
||||
import type {
|
||||
ChatCompletionAssistantMessageParam,
|
||||
@@ -33,12 +32,7 @@ import type {
|
||||
ChatCompletionToolMessageParam,
|
||||
ChatCompletionUserMessageParam,
|
||||
} from "openai/resources/chat/completions";
|
||||
import type {
|
||||
ChatCompletionMessageParam,
|
||||
ResponseFormatJSONObject,
|
||||
ResponseFormatJSONSchema,
|
||||
} from "openai/resources/index.js";
|
||||
import { z } from "zod";
|
||||
import type { ChatCompletionMessageParam } from "openai/resources/index.js";
|
||||
import {
|
||||
AzureOpenAIWithUserAgent,
|
||||
getAzureConfigFromEnv,
|
||||
@@ -298,7 +292,6 @@ export class OpenAI extends ToolCallLLM<OpenAIAdditionalChatOptions> {
|
||||
maxTokens: this.maxTokens,
|
||||
contextWindow,
|
||||
tokenizer: Tokenizers.CL100K_BASE,
|
||||
structuredOutput: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -392,8 +385,7 @@ export class OpenAI extends ToolCallLLM<OpenAIAdditionalChatOptions> {
|
||||
| ChatResponse<ToolCallLLMMessageOptions>
|
||||
| AsyncIterable<ChatResponseChunk<ToolCallLLMMessageOptions>>
|
||||
> {
|
||||
const { messages, stream, tools, responseFormat, additionalChatOptions } =
|
||||
params;
|
||||
const { messages, stream, tools, additionalChatOptions } = params;
|
||||
const baseRequestParams = <OpenAILLM.Chat.ChatCompletionCreateParams>{
|
||||
model: this.model,
|
||||
temperature: this.temperature,
|
||||
@@ -416,20 +408,6 @@ export class OpenAI extends ToolCallLLM<OpenAIAdditionalChatOptions> {
|
||||
if (!isTemperatureSupported(baseRequestParams.model))
|
||||
delete baseRequestParams.temperature;
|
||||
|
||||
//add response format for the structured output
|
||||
if (responseFormat && this.metadata.structuredOutput) {
|
||||
if (responseFormat instanceof z.ZodType)
|
||||
baseRequestParams.response_format = zodResponseFormat(
|
||||
responseFormat,
|
||||
"response_format",
|
||||
);
|
||||
else {
|
||||
baseRequestParams.response_format = responseFormat as
|
||||
| ResponseFormatJSONObject
|
||||
| ResponseFormatJSONSchema;
|
||||
}
|
||||
}
|
||||
|
||||
// Streaming
|
||||
if (stream) {
|
||||
return this.streamChat(baseRequestParams);
|
||||
|
||||
@@ -64,7 +64,6 @@ export class Perplexity extends OpenAI {
|
||||
contextWindow:
|
||||
PERPLEXITY_MODELS[this.model as PerplexityModelName]?.contextWindow,
|
||||
tokenizer: Tokenizers.CL100K_BASE,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,6 @@ export class ReplicateLLM extends BaseLLM {
|
||||
maxTokens: this.maxTokens,
|
||||
contextWindow: ALL_AVAILABLE_REPLICATE_MODELS[this.model].contextWindow,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -117,15 +117,7 @@ export class PineconeVectorStore extends BaseVectorStore {
|
||||
}
|
||||
|
||||
const idx: Index = await this.index();
|
||||
const nodes = embeddingResults.map((node) => {
|
||||
const nodeRecord = this.nodeToRecord(node);
|
||||
|
||||
if (nodeRecord.metadata.ref_doc_id) {
|
||||
// adding refDoc id as prefix to the chunk to find them using refDoc id
|
||||
nodeRecord.id = `${nodeRecord.metadata.ref_doc_id}_chunk_${nodeRecord.id}`;
|
||||
}
|
||||
return nodeRecord;
|
||||
});
|
||||
const nodes = embeddingResults.map(this.nodeToRecord);
|
||||
|
||||
for (let i = 0; i < nodes.length; i += this.chunkSize) {
|
||||
const chunk = nodes.slice(i, i + this.chunkSize);
|
||||
@@ -156,43 +148,8 @@ export class PineconeVectorStore extends BaseVectorStore {
|
||||
* @returns Promise that resolves if the delete query did not throw an error.
|
||||
*/
|
||||
async delete(refDocId: string, deleteKwargs?: object): Promise<void> {
|
||||
const [idx, index] = await Promise.all([
|
||||
this.index(),
|
||||
//to get the information about the index
|
||||
this.db?.describeIndex(this.indexName),
|
||||
]);
|
||||
|
||||
if (index?.spec?.pod) {
|
||||
//if the index is a pod, delete the document by the metadata
|
||||
await idx.deleteMany({
|
||||
metadata: {
|
||||
ref_doc_id: refDocId,
|
||||
},
|
||||
});
|
||||
} else if (index?.spec?.serverless) {
|
||||
// filtering on metadata is not supported in serverless indexes
|
||||
// for serverless indexes, we can delete document by ID prefix
|
||||
// ref:https://docs.pinecone.io/guides/data/delete-data#delete-records-by-metadata
|
||||
// get the list of ids with the prefix (not supportered in non serverless indexes)
|
||||
let list = await idx.listPaginated({
|
||||
prefix: refDocId,
|
||||
});
|
||||
//do while loop to delete the document if there is no next paginationToken
|
||||
do {
|
||||
const ids = list?.vectors?.map((v) => v.id);
|
||||
|
||||
if (ids && ids.length > 0) {
|
||||
await idx.deleteMany(ids);
|
||||
}
|
||||
|
||||
if (list.pagination?.next) {
|
||||
list = await idx.listPaginated({
|
||||
prefix: refDocId,
|
||||
paginationToken: list.pagination?.next,
|
||||
});
|
||||
}
|
||||
} while (list.pagination?.next);
|
||||
}
|
||||
const idx = await this.index();
|
||||
return idx.deleteOne(refDocId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,6 @@ export class VercelLLM extends ToolCallLLM<VercelAdditionalChatOptions> {
|
||||
topP: 1,
|
||||
contextWindow: 128000,
|
||||
tokenizer: undefined,
|
||||
structuredOutput: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -230,6 +230,7 @@
|
||||
"mammoth": "^1.7.2",
|
||||
"mongodb": "^6.7.0",
|
||||
"notion-md-crawler": "^1.0.0",
|
||||
"papaparse": "^5.4.1",
|
||||
"unpdf": "^0.12.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export class SimpleCosmosDBReader implements BaseReader {
|
||||
const metadataFields = config.metadataFields;
|
||||
|
||||
try {
|
||||
const res = await container.items.query(query).fetchAll();
|
||||
let res = await container.items.query(query).fetchAll();
|
||||
const documents: Document[] = [];
|
||||
|
||||
for (const item of res.resources) {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
output/
|
||||
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"name": "@llamaindex/tools",
|
||||
"description": "LlamaIndex Tools",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"require": {
|
||||
"types": "./dist/index.d.cts",
|
||||
"default": "./dist/index.cjs"
|
||||
},
|
||||
"import": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/run-llama/LlamaIndexTS.git",
|
||||
"directory": "packages/tools"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "bunchee",
|
||||
"dev": "bunchee --watch",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bunchee": "6.4.0",
|
||||
"vitest": "^2.1.5",
|
||||
"@types/node": "^22.9.0",
|
||||
"@types/papaparse": "^5.3.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "^10.1.0",
|
||||
"@llamaindex/core": "workspace:*",
|
||||
"@llamaindex/env": "workspace:*",
|
||||
"@e2b/code-interpreter": "^1.0.4",
|
||||
"duck-duck-scrape": "^2.2.5",
|
||||
"papaparse": "^5.4.1",
|
||||
"marked": "^14.1.2",
|
||||
"got": "^14.4.1",
|
||||
"formdata-node": "^6.0.3",
|
||||
"ajv": "^8.12.0",
|
||||
"wikipedia": "^2.1.2",
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
export async function saveDocument(filePath: string, content: string | Buffer) {
|
||||
if (path.isAbsolute(filePath)) {
|
||||
throw new Error("Absolute file paths are not allowed.");
|
||||
}
|
||||
|
||||
const dirPath = path.dirname(filePath);
|
||||
await fs.promises.mkdir(dirPath, { recursive: true });
|
||||
|
||||
if (typeof content === "string") {
|
||||
await fs.promises.writeFile(filePath, content, "utf-8");
|
||||
} else {
|
||||
await fs.promises.writeFile(filePath, content);
|
||||
}
|
||||
}
|
||||
|
||||
export function getFileUrl(
|
||||
filePath: string,
|
||||
options?: {
|
||||
fileServerURLPrefix?: string | undefined;
|
||||
},
|
||||
): string {
|
||||
const fileServerURLPrefix =
|
||||
options?.fileServerURLPrefix || process.env.FILESERVER_URL_PREFIX;
|
||||
|
||||
if (!fileServerURLPrefix) {
|
||||
throw new Error(
|
||||
"To get a file URL, please provide a fileServerURLPrefix or set FILESERVER_URL_PREFIX environment variable.",
|
||||
);
|
||||
}
|
||||
|
||||
return `${fileServerURLPrefix}/${filePath}`;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export * from "./tools/code-generator";
|
||||
export * from "./tools/document-generator";
|
||||
export * from "./tools/duckduckgo";
|
||||
export * from "./tools/form-filling";
|
||||
export * from "./tools/img-gen";
|
||||
export * from "./tools/interpreter";
|
||||
export * from "./tools/openapi-action";
|
||||
export * from "./tools/weather";
|
||||
export * from "./tools/wiki";
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Settings, type JSONValue } from "@llamaindex/core/global";
|
||||
import type { ChatMessage } from "@llamaindex/core/llms";
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import { z } from "zod";
|
||||
|
||||
// prompt based on https://github.com/e2b-dev/ai-artifacts
|
||||
const CODE_GENERATION_PROMPT = `You are a skilled software engineer. You do not make mistakes. Generate an artifact. You can install additional dependencies. You can use one of the following templates:\n
|
||||
|
||||
1. code-interpreter-multilang: "Runs code as a Jupyter notebook cell. Strong data analysis angle. Can use complex visualisation to explain results.". File: script.py. Dependencies installed: python, jupyter, numpy, pandas, matplotlib, seaborn, plotly. Port: none.
|
||||
|
||||
2. nextjs-developer: "A Next.js 13+ app that reloads automatically. Using the pages router.". File: pages/index.tsx. Dependencies installed: nextjs@14.2.5, typescript, @types/node, @types/react, @types/react-dom, postcss, tailwindcss, shadcn. Port: 3000.
|
||||
|
||||
3. vue-developer: "A Vue.js 3+ app that reloads automatically. Only when asked specifically for a Vue app.". File: app.vue. Dependencies installed: vue@latest, nuxt@3.13.0, tailwindcss. Port: 3000.
|
||||
|
||||
4. streamlit-developer: "A streamlit app that reloads automatically.". File: app.py. Dependencies installed: streamlit, pandas, numpy, matplotlib, request, seaborn, plotly. Port: 8501.
|
||||
|
||||
5. gradio-developer: "A gradio app. Gradio Blocks/Interface should be called demo.". File: app.py. Dependencies installed: gradio, pandas, numpy, matplotlib, request, seaborn, plotly. Port: 7860.
|
||||
|
||||
Provide detail information about the artifact you're about to generate in the following JSON format with the following keys:
|
||||
|
||||
commentary: Describe what you're about to do and the steps you want to take for generating the artifact in great detail.
|
||||
template: Name of the template used to generate the artifact.
|
||||
title: Short title of the artifact. Max 3 words.
|
||||
description: Short description of the artifact. Max 1 sentence.
|
||||
additional_dependencies: Additional dependencies required by the artifact. Do not include dependencies that are already included in the template.
|
||||
has_additional_dependencies: Detect if additional dependencies that are not included in the template are required by the artifact.
|
||||
install_dependencies_command: Command to install additional dependencies required by the artifact.
|
||||
port: Port number used by the resulted artifact. Null when no ports are exposed.
|
||||
file_path: Relative path to the file, including the file name.
|
||||
code: Code generated by the artifact. Only runnable code is allowed.
|
||||
|
||||
Make sure to use the correct syntax for the programming language you're using. Make sure to generate only one code file. If you need to use CSS, make sure to include the CSS in the code file using Tailwind CSS syntax.
|
||||
`;
|
||||
|
||||
// detail information to execute code
|
||||
export type CodeArtifact = {
|
||||
commentary: string;
|
||||
template: string;
|
||||
title: string;
|
||||
description: string;
|
||||
additional_dependencies: string[];
|
||||
has_additional_dependencies: boolean;
|
||||
install_dependencies_command: string;
|
||||
port: number | null;
|
||||
file_path: string;
|
||||
code: string;
|
||||
files?: string[];
|
||||
};
|
||||
|
||||
export type CodeGeneratorToolOutput = {
|
||||
isError: boolean;
|
||||
artifact?: CodeArtifact;
|
||||
};
|
||||
|
||||
// Helper function
|
||||
async function generateArtifact(
|
||||
query: string,
|
||||
oldCode?: string,
|
||||
attachments?: string[],
|
||||
): Promise<CodeArtifact> {
|
||||
const userMessage = `
|
||||
${query}
|
||||
${oldCode ? `The existing code is: \n\`\`\`${oldCode}\`\`\`` : ""}
|
||||
${attachments ? `The attachments are: \n${attachments.join("\n")}` : ""}
|
||||
`;
|
||||
const messages: ChatMessage[] = [
|
||||
{ role: "system", content: CODE_GENERATION_PROMPT },
|
||||
{ role: "user", content: userMessage },
|
||||
];
|
||||
try {
|
||||
const response = await Settings.llm.chat({ messages });
|
||||
const content = response.message.content.toString();
|
||||
const jsonContent = content
|
||||
.replace(/^```json\s*|\s*```$/g, "")
|
||||
.replace(/^`+|`+$/g, "")
|
||||
.trim();
|
||||
const artifact = JSON.parse(jsonContent) as CodeArtifact;
|
||||
return artifact;
|
||||
} catch (error) {
|
||||
console.log("Failed to generate artifact", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export const codeGenerator = () => {
|
||||
return tool({
|
||||
name: "artifact",
|
||||
description:
|
||||
"Generate a code artifact based on the input. Don't call this tool if the user has not asked for code generation. E.g. if the user asks to write a description or specification, don't call this tool.",
|
||||
parameters: z.object({
|
||||
requirement: z
|
||||
.string()
|
||||
.describe("The description of the application you want to build."),
|
||||
oldCode: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("The existing code to be modified"),
|
||||
sandboxFiles: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.describe(
|
||||
"A list of sandbox file paths. Include these files if the code requires them.",
|
||||
),
|
||||
}),
|
||||
execute: async ({ requirement, oldCode, sandboxFiles }) => {
|
||||
try {
|
||||
const artifact = await generateArtifact(
|
||||
requirement,
|
||||
oldCode,
|
||||
sandboxFiles, // help the generated code use exact files
|
||||
);
|
||||
if (sandboxFiles) {
|
||||
artifact.files = sandboxFiles;
|
||||
}
|
||||
return {
|
||||
isError: false,
|
||||
artifact,
|
||||
} as JSONValue;
|
||||
} catch (error) {
|
||||
return {
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,112 +0,0 @@
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import { marked } from "marked";
|
||||
import path from "node:path";
|
||||
import { z } from "zod";
|
||||
import { getFileUrl, saveDocument } from "../helper";
|
||||
|
||||
const COMMON_STYLES = `
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.3;
|
||||
color: #333;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 0.7em;
|
||||
}
|
||||
code {
|
||||
background-color: #f4f4f4;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
pre {
|
||||
background-color: #f4f4f4;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
font-weight: bold;
|
||||
}
|
||||
img {
|
||||
max-width: 90%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 1em auto;
|
||||
border-radius: 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
const HTML_SPECIFIC_STYLES = `
|
||||
body {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
const HTML_TEMPLATE = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
${COMMON_STYLES}
|
||||
${HTML_SPECIFIC_STYLES}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{{content}}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
export type DocumentGeneratorParams = {
|
||||
/** Directory where generated documents will be saved */
|
||||
outputDir: string;
|
||||
/** Prefix for the file server URL */
|
||||
fileServerURLPrefix?: string;
|
||||
};
|
||||
|
||||
export const documentGenerator = (params: DocumentGeneratorParams) => {
|
||||
return tool({
|
||||
name: "document_generator",
|
||||
description:
|
||||
"Generate HTML document from markdown content. Return a file url to the document",
|
||||
parameters: z.object({
|
||||
originalContent: z
|
||||
.string()
|
||||
.describe("The original markdown content to convert"),
|
||||
fileName: z
|
||||
.string()
|
||||
.describe("The name of the document file (without extension)"),
|
||||
}),
|
||||
execute: async ({ originalContent, fileName }): Promise<string> => {
|
||||
const { outputDir, fileServerURLPrefix } = params;
|
||||
|
||||
const htmlContent = await marked(originalContent);
|
||||
const fileContent = HTML_TEMPLATE.replace("{{content}}", htmlContent);
|
||||
|
||||
const filePath = path.join(outputDir, `${fileName}.html`);
|
||||
await saveDocument(filePath, fileContent);
|
||||
const fileUrl = getFileUrl(filePath, { fileServerURLPrefix });
|
||||
|
||||
return `URL: ${fileUrl}`;
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import { search } from "duck-duck-scrape";
|
||||
import { z } from "zod";
|
||||
|
||||
export type DuckDuckGoToolOutput = Array<{
|
||||
title: string;
|
||||
description: string;
|
||||
url: string;
|
||||
}>;
|
||||
|
||||
export const duckduckgo = () => {
|
||||
return tool({
|
||||
name: "duckduckgo_search",
|
||||
description:
|
||||
"Use this function to search for information (only text) in the internet using DuckDuckGo.",
|
||||
parameters: z.object({
|
||||
query: z.string().describe("The query to search in DuckDuckGo."),
|
||||
region: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional, The region to be used for the search in [country-language] convention, ex us-en, uk-en, ru-ru, etc...",
|
||||
),
|
||||
maxResults: z
|
||||
.number()
|
||||
.default(10)
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional, The maximum number of results to be returned. Default is 10.",
|
||||
),
|
||||
}),
|
||||
execute: async ({
|
||||
query,
|
||||
region,
|
||||
maxResults = 10,
|
||||
}): Promise<DuckDuckGoToolOutput> => {
|
||||
const options = region ? { region } : {};
|
||||
const searchResults = await search(query, options);
|
||||
return searchResults.results.slice(0, maxResults).map((result) => {
|
||||
return {
|
||||
title: result.title,
|
||||
description: result.description,
|
||||
url: result.url,
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,234 +0,0 @@
|
||||
import { Settings } from "@llamaindex/core/global";
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import fs from "fs";
|
||||
import Papa from "papaparse";
|
||||
import path from "path";
|
||||
import { z } from "zod";
|
||||
import { getFileUrl, saveDocument } from "../helper";
|
||||
|
||||
export type MissingCell = {
|
||||
rowIndex: number;
|
||||
columnIndex: number;
|
||||
question: string;
|
||||
};
|
||||
|
||||
const CSV_EXTRACTION_PROMPT = `You are a data analyst. You are given a table with missing cells.
|
||||
Your task is to identify the missing cells and the questions needed to fill them.
|
||||
IMPORTANT: Column indices should be 0-based
|
||||
|
||||
# Instructions:
|
||||
- Understand the entire content of the table and the topics of the table.
|
||||
- Identify the missing cells and the meaning of the data in the cells.
|
||||
- For each missing cell, provide the row index and the correct column index (remember: first data column is 1).
|
||||
- For each missing cell, provide the question needed to fill the cell (it's important to provide the question that is relevant to the topic of the table).
|
||||
- Since the cell's value should be concise, the question should request a numerical answer or a specific value.
|
||||
- Finally, only return the answer in JSON format with the following schema:
|
||||
{
|
||||
"missing_cells": [
|
||||
{
|
||||
"rowIndex": number,
|
||||
"columnIndex": number,
|
||||
"question": string
|
||||
}
|
||||
]
|
||||
}
|
||||
- If there are no missing cells, return an empty array.
|
||||
- The answer is only the JSON object, nothing else and don't wrap it inside markdown code block.
|
||||
|
||||
# Example:
|
||||
# | | Name | Age | City |
|
||||
# |----|------|-----|------|
|
||||
# | 0 | John | | Paris|
|
||||
# | 1 | Mary | | |
|
||||
# | 2 | | 30 | |
|
||||
#
|
||||
# Your thoughts:
|
||||
# - The table is about people's names, ages, and cities.
|
||||
# - Row: 1, Column: 2 (Age column), Question: "How old is Mary? Please provide only the numerical answer."
|
||||
# - Row: 1, Column: 3 (City column), Question: "In which city does Mary live? Please provide only the city name."
|
||||
# Your answer:
|
||||
# {
|
||||
# "missing_cells": [
|
||||
# {
|
||||
# "rowIndex": 1,
|
||||
# "columnIndex": 2,
|
||||
# "question": "How old is Mary? Please provide only the numerical answer."
|
||||
# },
|
||||
# {
|
||||
# "rowIndex": 1,
|
||||
# "columnIndex": 3,
|
||||
# "question": "In which city does Mary live? Please provide only the city name."
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
|
||||
|
||||
# Here is your task:
|
||||
|
||||
- Table content:
|
||||
{table_content}
|
||||
|
||||
- Your answer:
|
||||
`;
|
||||
|
||||
export const extractMissingCells = () => {
|
||||
return tool({
|
||||
name: "extract_missing_cells",
|
||||
description:
|
||||
"Use this tool to extract missing cells in a CSV file and generate questions to fill them. This tool only works with local file path.",
|
||||
parameters: z.object({
|
||||
filePath: z.string().describe("The local file path to the CSV file."),
|
||||
}),
|
||||
execute: async ({ filePath }): Promise<MissingCell[]> => {
|
||||
let tableContent: string[][];
|
||||
try {
|
||||
tableContent = await readCsvFile(filePath);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
"Failed to read CSV file. Make sure that you are reading a local file path (not a sandbox path).",
|
||||
);
|
||||
}
|
||||
|
||||
const prompt = CSV_EXTRACTION_PROMPT.replace(
|
||||
"{table_content}",
|
||||
formatToMarkdownTable(tableContent),
|
||||
);
|
||||
|
||||
const llm = Settings.llm;
|
||||
const response = await llm.complete({ prompt });
|
||||
const parsedResponse = JSON.parse(response.text) as {
|
||||
missing_cells: MissingCell[];
|
||||
};
|
||||
if (!parsedResponse.missing_cells) {
|
||||
throw new Error(
|
||||
"The answer is not in the correct format. There should be a missing_cells array.",
|
||||
);
|
||||
}
|
||||
return parsedResponse.missing_cells;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export type FillMissingCellsParams = {
|
||||
/** Directory where generated documents will be saved */
|
||||
outputDir: string;
|
||||
|
||||
/** Prefix for the file server URL */
|
||||
fileServerURLPrefix?: string;
|
||||
};
|
||||
|
||||
export type FillMissingCellsToolOutput = {
|
||||
isSuccess: boolean;
|
||||
errorMessage?: string;
|
||||
fileUrl?: string;
|
||||
};
|
||||
|
||||
export const fillMissingCells = (params: FillMissingCellsParams) => {
|
||||
return tool({
|
||||
name: "fill_missing_cells",
|
||||
description:
|
||||
"Use this tool to fill missing cells in a CSV file with provided answers. This tool only works with local file path.",
|
||||
parameters: z.object({
|
||||
filePath: z.string().describe("The local file path to the CSV file."),
|
||||
cells: z
|
||||
.array(
|
||||
z.object({
|
||||
rowIndex: z.number(),
|
||||
columnIndex: z.number(),
|
||||
answer: z.string(),
|
||||
}),
|
||||
)
|
||||
.describe("Array of cells to fill with their answers"),
|
||||
}),
|
||||
execute: async ({ filePath, cells }): Promise<string> => {
|
||||
const { outputDir, fileServerURLPrefix } = params;
|
||||
|
||||
// Read the CSV file
|
||||
const fileContent = await fs.promises.readFile(filePath, "utf8");
|
||||
|
||||
// Parse CSV with PapaParse
|
||||
const parseResult = Papa.parse<string[]>(fileContent, {
|
||||
header: false, // Ensure the header is not treated as a separate object
|
||||
skipEmptyLines: false, // Ensure empty lines are not skipped
|
||||
});
|
||||
|
||||
if (parseResult.errors.length) {
|
||||
throw new Error(
|
||||
"Failed to parse CSV file: " + parseResult.errors[0]?.message,
|
||||
);
|
||||
}
|
||||
|
||||
const rows = parseResult.data;
|
||||
|
||||
// Fill the cells with answers
|
||||
for (const cell of cells) {
|
||||
// Adjust rowIndex to start from 1 for data rows
|
||||
const adjustedRowIndex = cell.rowIndex + 1;
|
||||
if (
|
||||
adjustedRowIndex < rows.length &&
|
||||
cell.columnIndex < (rows[adjustedRowIndex]?.length ?? 0) &&
|
||||
rows[adjustedRowIndex]
|
||||
) {
|
||||
rows[adjustedRowIndex][cell.columnIndex] = cell.answer;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back to CSV format
|
||||
const updatedContent = Papa.unparse(rows, {
|
||||
delimiter: parseResult.meta.delimiter,
|
||||
});
|
||||
|
||||
// Use the helper function to write the file
|
||||
const parsedPath = path.parse(filePath);
|
||||
const newFileName = `${parsedPath.name}-filled${parsedPath.ext}`;
|
||||
const newFilePath = path.join(outputDir, newFileName);
|
||||
|
||||
await saveDocument(newFilePath, updatedContent);
|
||||
const newFileUrl = getFileUrl(newFilePath, { fileServerURLPrefix });
|
||||
|
||||
return (
|
||||
"Successfully filled missing cells in the CSV file. File URL to show to the user: " +
|
||||
newFileUrl
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
async function readCsvFile(filePath: string): Promise<string[][]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(filePath, "utf8", (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedData = Papa.parse<string[]>(data, {
|
||||
skipEmptyLines: false,
|
||||
});
|
||||
|
||||
if (parsedData.errors.length) {
|
||||
reject(parsedData.errors);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure all rows have the same number of columns as the header
|
||||
const maxColumns = parsedData.data[0]?.length ?? 0;
|
||||
const paddedRows = parsedData.data.map((row) => {
|
||||
return [...row, ...Array(maxColumns - row.length).fill("")];
|
||||
});
|
||||
|
||||
resolve(paddedRows);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function formatToMarkdownTable(data: string[][]): string {
|
||||
if (data.length === 0) return "";
|
||||
|
||||
const maxColumns = data[0]?.length ?? 0;
|
||||
const headerRow = `| ${data[0]?.join(" | ") ?? ""} |`;
|
||||
const separatorRow = `| ${Array(maxColumns).fill("---").join(" | ")} |`;
|
||||
const dataRows = data.slice(1).map((row) => `| ${row.join(" | ")} |`);
|
||||
|
||||
return [headerRow, separatorRow, ...dataRows].join("\n");
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import { FormData } from "formdata-node";
|
||||
import got from "got";
|
||||
import path from "path";
|
||||
import { Readable } from "stream";
|
||||
import { z } from "zod";
|
||||
import { getFileUrl, saveDocument } from "../helper";
|
||||
|
||||
export type ImgGeneratorToolOutput = {
|
||||
isSuccess: boolean;
|
||||
imageUrl?: string;
|
||||
errorMessage?: string;
|
||||
};
|
||||
|
||||
export type ImgGeneratorToolParams = {
|
||||
/** Directory where generated images will be saved */
|
||||
outputDir: string;
|
||||
/** STABILITY_API_KEY key is required to run image generator. Get it here: https://platform.stability.ai/account/keys */
|
||||
apiKey: string;
|
||||
/** Output format of the generated image */
|
||||
outputFormat?: string;
|
||||
/** Prefix for the file server URL */
|
||||
fileServerURLPrefix?: string | undefined;
|
||||
};
|
||||
|
||||
export const imageGenerator = (params: ImgGeneratorToolParams) => {
|
||||
return tool({
|
||||
name: "image_generator",
|
||||
description: "Use this function to generate an image based on the prompt.",
|
||||
parameters: z.object({
|
||||
prompt: z.string().describe("The prompt to generate the image"),
|
||||
}),
|
||||
execute: async ({ prompt }): Promise<ImgGeneratorToolOutput> => {
|
||||
const { outputDir, apiKey, fileServerURLPrefix } = params;
|
||||
const outputFormat = params.outputFormat ?? "webp";
|
||||
|
||||
try {
|
||||
const buffer = await promptToImgBuffer(prompt, apiKey, outputFormat);
|
||||
const filename = `${crypto.randomUUID()}.${outputFormat}`;
|
||||
const filePath = path.join(outputDir, filename);
|
||||
await saveDocument(filePath, buffer);
|
||||
const imageUrl = getFileUrl(filePath, { fileServerURLPrefix });
|
||||
return { isSuccess: true, imageUrl };
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return {
|
||||
isSuccess: false,
|
||||
errorMessage: "Failed to generate image. Please try again.",
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
async function promptToImgBuffer(
|
||||
prompt: string,
|
||||
apiKey: string,
|
||||
outputFormat: string,
|
||||
): Promise<Buffer> {
|
||||
const form = new FormData();
|
||||
form.append("prompt", prompt);
|
||||
form.append("output_format", outputFormat);
|
||||
|
||||
const apiUrl = "https://api.stability.ai/v2beta/stable-image/generate/core";
|
||||
const buffer = await got
|
||||
.post(apiUrl, {
|
||||
body: form as unknown as Buffer | Readable | string,
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
Accept: "image/*",
|
||||
},
|
||||
})
|
||||
.buffer();
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
import { type Logs, Result, Sandbox } from "@e2b/code-interpreter";
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import fs from "fs";
|
||||
import path from "node:path";
|
||||
import { z } from "zod";
|
||||
import { getFileUrl, saveDocument } from "../helper";
|
||||
|
||||
export type InterpreterExtraType =
|
||||
| "html"
|
||||
| "markdown"
|
||||
| "svg"
|
||||
| "png"
|
||||
| "jpeg"
|
||||
| "pdf"
|
||||
| "latex"
|
||||
| "json"
|
||||
| "javascript";
|
||||
|
||||
export type InterpreterExtraResult = {
|
||||
type: InterpreterExtraType;
|
||||
content?: string;
|
||||
filename?: string;
|
||||
url?: string;
|
||||
};
|
||||
|
||||
export type InterpreterToolOutput = {
|
||||
isError: boolean;
|
||||
logs: Logs;
|
||||
text?: string;
|
||||
extraResult: InterpreterExtraResult[];
|
||||
retryCount?: number;
|
||||
};
|
||||
|
||||
export type InterpreterToolParams = {
|
||||
/** E2B API key required for authentication. Get yours at https://e2b.dev/docs/legacy/getting-started/api-key */
|
||||
apiKey: string;
|
||||
/** Directory where output files (charts, images, etc.) will be saved when code is executed */
|
||||
outputDir: string;
|
||||
/** Local directory containing files that need to be uploaded to the sandbox environment before code execution */
|
||||
uploadedFilesDir: string;
|
||||
/** Prefix for the file server URL */
|
||||
fileServerURLPrefix?: string;
|
||||
};
|
||||
|
||||
export const interpreter = (params: InterpreterToolParams) => {
|
||||
const { apiKey, outputDir, uploadedFilesDir, fileServerURLPrefix } = params;
|
||||
|
||||
return tool({
|
||||
name: "interpreter",
|
||||
description:
|
||||
"Execute python code in a Jupyter notebook cell and return any result, stdout, stderr, display_data, and error.",
|
||||
parameters: z.object({
|
||||
code: z.string().describe("The python code to execute in a single cell"),
|
||||
sandboxFiles: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.describe("List of local file paths to be used by the code"),
|
||||
retryCount: z
|
||||
.number()
|
||||
.default(0)
|
||||
.optional()
|
||||
.describe("The number of times the tool has been retried"),
|
||||
}),
|
||||
execute: async ({ code, sandboxFiles, retryCount = 0 }) => {
|
||||
if (retryCount >= 3) {
|
||||
return {
|
||||
isError: true,
|
||||
logs: { stdout: [], stderr: [] },
|
||||
text: "Max retries reached",
|
||||
extraResult: [],
|
||||
};
|
||||
}
|
||||
|
||||
const interpreter = await Sandbox.create({ apiKey });
|
||||
await uploadFilesToSandbox(interpreter, uploadedFilesDir, sandboxFiles);
|
||||
const exec = await interpreter.runCode(code);
|
||||
const extraResult = await getExtraResult(
|
||||
outputDir,
|
||||
exec.results[0],
|
||||
fileServerURLPrefix,
|
||||
);
|
||||
|
||||
return {
|
||||
isError: !!exec.error,
|
||||
logs: exec.logs,
|
||||
text: exec.text,
|
||||
extraResult,
|
||||
retryCount: retryCount + 1,
|
||||
} as InterpreterToolOutput;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
async function uploadFilesToSandbox(
|
||||
codeInterpreter: Sandbox,
|
||||
uploadedFilesDir: string,
|
||||
sandboxFiles: string[] = [],
|
||||
) {
|
||||
try {
|
||||
for (const filePath of sandboxFiles) {
|
||||
const fileName = path.basename(filePath);
|
||||
const localFilePath = path.join(uploadedFilesDir, fileName);
|
||||
const content = fs.readFileSync(localFilePath);
|
||||
const arrayBuffer = new Uint8Array(content).buffer;
|
||||
await codeInterpreter.files.write(filePath, arrayBuffer);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Got error when uploading files to sandbox", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function getExtraResult(
|
||||
outputDir: string,
|
||||
res?: Result,
|
||||
fileServerURLPrefix?: string,
|
||||
): Promise<InterpreterExtraResult[]> {
|
||||
if (!res) return [];
|
||||
const output: InterpreterExtraResult[] = [];
|
||||
|
||||
try {
|
||||
const formats = res.formats();
|
||||
const results = formats.map((f) => res[f as keyof Result]);
|
||||
|
||||
for (let i = 0; i < formats.length; i++) {
|
||||
const ext = formats[i];
|
||||
const data = results[i];
|
||||
switch (ext) {
|
||||
case "png":
|
||||
case "jpeg":
|
||||
case "svg":
|
||||
case "pdf": {
|
||||
const { filename, filePath } = await saveToDisk(outputDir, data, ext);
|
||||
const fileUrl = getFileUrl(filePath, { fileServerURLPrefix });
|
||||
output.push({
|
||||
type: ext as InterpreterExtraType,
|
||||
filename,
|
||||
url: fileUrl,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
output.push({
|
||||
type: ext as InterpreterExtraType,
|
||||
content: data,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error when parsing e2b response", error);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
async function saveToDisk(outputDir: string, base64Data: string, ext: string) {
|
||||
const filename = `${crypto.randomUUID()}.${ext}`;
|
||||
const buffer = Buffer.from(base64Data, "base64");
|
||||
const filePath = path.join(outputDir, filename);
|
||||
await saveDocument(filePath, buffer);
|
||||
return { filename, filePath };
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
import SwaggerParser from "@apidevtools/swagger-parser";
|
||||
import type { JSONValue } from "@llamaindex/core/global";
|
||||
import type { ToolMetadata } from "@llamaindex/core/llms";
|
||||
import { FunctionTool } from "@llamaindex/core/tools";
|
||||
import { type JSONSchemaType } from "ajv";
|
||||
import got from "got";
|
||||
|
||||
interface DomainHeaders {
|
||||
[key: string]: { [header: string]: string };
|
||||
}
|
||||
|
||||
type Input = {
|
||||
url: string;
|
||||
params: object;
|
||||
};
|
||||
|
||||
type APIInfo = {
|
||||
description: string;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export class OpenAPIActionTool {
|
||||
// cache the loaded specs by URL
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private static specs: Record<string, any> = {};
|
||||
|
||||
private readonly INVALID_URL_PROMPT =
|
||||
"This url did not include a hostname or scheme. Please determine the complete URL and try again.";
|
||||
|
||||
private createLoadSpecMetaData = (info: APIInfo) => {
|
||||
return {
|
||||
name: "load_openapi_spec",
|
||||
description: `Use this to retrieve the OpenAPI spec for the API named ${info.title} with the following description: ${info.description}. Call it before making any requests to the API.`,
|
||||
};
|
||||
};
|
||||
|
||||
private readonly createMethodCallMetaData = (
|
||||
method: "POST" | "PATCH" | "GET",
|
||||
info: APIInfo,
|
||||
) => {
|
||||
return {
|
||||
name: `${method.toLowerCase()}_request`,
|
||||
description: `Use this to call the ${method} method on the API named ${info.title}`,
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
url: {
|
||||
type: "string",
|
||||
description: `The url to make the ${method} request against`,
|
||||
},
|
||||
params: {
|
||||
type: "object",
|
||||
description:
|
||||
method === "GET"
|
||||
? "the URL parameters to provide with the get request"
|
||||
: `the key-value pairs to provide with the ${method} request`,
|
||||
},
|
||||
},
|
||||
required: ["url"],
|
||||
},
|
||||
} as ToolMetadata<JSONSchemaType<Input>>;
|
||||
};
|
||||
|
||||
constructor(
|
||||
public openapi_uri: string,
|
||||
public domainHeaders: DomainHeaders = {},
|
||||
) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async loadOpenapiSpec(url: string): Promise<any> {
|
||||
const api = await SwaggerParser.validate(url);
|
||||
return {
|
||||
servers: "servers" in api ? api.servers : "",
|
||||
info: { description: api.info.description, title: api.info.title },
|
||||
endpoints: api.paths,
|
||||
};
|
||||
}
|
||||
|
||||
async getRequest(input: Input): Promise<JSONValue> {
|
||||
if (!this.validUrl(input.url)) {
|
||||
return this.INVALID_URL_PROMPT;
|
||||
}
|
||||
try {
|
||||
const data = await got
|
||||
.get(input.url, {
|
||||
headers: this.getHeadersForUrl(input.url),
|
||||
searchParams: input.params as URLSearchParams,
|
||||
})
|
||||
.json();
|
||||
return data as JSONValue;
|
||||
} catch (error) {
|
||||
return error as JSONValue;
|
||||
}
|
||||
}
|
||||
|
||||
async postRequest(input: Input): Promise<JSONValue> {
|
||||
if (!this.validUrl(input.url)) {
|
||||
return this.INVALID_URL_PROMPT;
|
||||
}
|
||||
try {
|
||||
const res = await got.post(input.url, {
|
||||
headers: this.getHeadersForUrl(input.url),
|
||||
json: input.params,
|
||||
});
|
||||
return res.body as JSONValue;
|
||||
} catch (error) {
|
||||
return error as JSONValue;
|
||||
}
|
||||
}
|
||||
|
||||
async patchRequest(input: Input): Promise<JSONValue> {
|
||||
if (!this.validUrl(input.url)) {
|
||||
return this.INVALID_URL_PROMPT;
|
||||
}
|
||||
try {
|
||||
const res = await got.patch(input.url, {
|
||||
headers: this.getHeadersForUrl(input.url),
|
||||
json: input.params,
|
||||
});
|
||||
return res.body as JSONValue;
|
||||
} catch (error) {
|
||||
return error as JSONValue;
|
||||
}
|
||||
}
|
||||
|
||||
public async toToolFunctions() {
|
||||
if (!OpenAPIActionTool.specs[this.openapi_uri]) {
|
||||
console.log(`Loading spec for URL: ${this.openapi_uri}`);
|
||||
const spec = await this.loadOpenapiSpec(this.openapi_uri);
|
||||
OpenAPIActionTool.specs[this.openapi_uri] = spec;
|
||||
}
|
||||
const spec = OpenAPIActionTool.specs[this.openapi_uri];
|
||||
// TODO: read endpoints with parameters from spec and create one tool for each endpoint
|
||||
// For now, we just create a tool for each HTTP method which does not work well for passing parameters
|
||||
return [
|
||||
FunctionTool.from(() => {
|
||||
return spec;
|
||||
}, this.createLoadSpecMetaData(spec.info)),
|
||||
FunctionTool.from(
|
||||
this.getRequest.bind(this),
|
||||
this.createMethodCallMetaData("GET", spec.info),
|
||||
),
|
||||
FunctionTool.from(
|
||||
this.postRequest.bind(this),
|
||||
this.createMethodCallMetaData("POST", spec.info),
|
||||
),
|
||||
FunctionTool.from(
|
||||
this.patchRequest.bind(this),
|
||||
this.createMethodCallMetaData("PATCH", spec.info),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
private validUrl(url: string): boolean {
|
||||
const parsed = new URL(url);
|
||||
return !!parsed.protocol && !!parsed.hostname;
|
||||
}
|
||||
|
||||
private getDomain(url: string): string {
|
||||
const parsed = new URL(url);
|
||||
return parsed.hostname;
|
||||
}
|
||||
|
||||
private getHeadersForUrl(url: string): { [header: string]: string } {
|
||||
const domain = this.getDomain(url);
|
||||
return this.domainHeaders[domain] || {};
|
||||
}
|
||||
}
|
||||
|
||||
export const getOpenAPIActionTools = async (params: {
|
||||
openapiUri: string;
|
||||
domainHeaders: DomainHeaders;
|
||||
}) => {
|
||||
const { openapiUri, domainHeaders } = params;
|
||||
const openAPIActionTool = new OpenAPIActionTool(openapiUri, domainHeaders);
|
||||
return await openAPIActionTool.toToolFunctions();
|
||||
};
|
||||
@@ -1,122 +0,0 @@
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import { z } from "zod";
|
||||
|
||||
export type WeatherToolOutput = {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
generationtime_ms: number;
|
||||
utc_offset_seconds: number;
|
||||
timezone: string;
|
||||
timezone_abbreviation: string;
|
||||
elevation: number;
|
||||
current_units: {
|
||||
time: string;
|
||||
interval: string;
|
||||
temperature_2m: string;
|
||||
weather_code: string;
|
||||
};
|
||||
current: {
|
||||
time: string;
|
||||
interval: number;
|
||||
temperature_2m: number;
|
||||
weather_code: number;
|
||||
};
|
||||
hourly_units: {
|
||||
time: string;
|
||||
temperature_2m: string;
|
||||
weather_code: string;
|
||||
};
|
||||
hourly: {
|
||||
time: string[];
|
||||
temperature_2m: number[];
|
||||
weather_code: number[];
|
||||
};
|
||||
daily_units: {
|
||||
time: string;
|
||||
weather_code: string;
|
||||
};
|
||||
daily: {
|
||||
time: string[];
|
||||
weather_code: number[];
|
||||
};
|
||||
};
|
||||
|
||||
export const weather = () => {
|
||||
return tool({
|
||||
name: "weather",
|
||||
description: `
|
||||
Use this function to get the weather of any given location.
|
||||
Note that the weather code should follow WMO Weather interpretation codes (WW):
|
||||
0: Clear sky
|
||||
1, 2, 3: Mainly clear, partly cloudy, and overcast
|
||||
45, 48: Fog and depositing rime fog
|
||||
51, 53, 55: Drizzle: Light, moderate, and dense intensity
|
||||
56, 57: Freezing Drizzle: Light and dense intensity
|
||||
61, 63, 65: Rain: Slight, moderate and heavy intensity
|
||||
66, 67: Freezing Rain: Light and heavy intensity
|
||||
71, 73, 75: Snow fall: Slight, moderate, and heavy intensity
|
||||
77: Snow grains
|
||||
80, 81, 82: Rain showers: Slight, moderate, and violent
|
||||
85, 86: Snow showers slight and heavy
|
||||
95: Thunderstorm: Slight or moderate
|
||||
96, 99: Thunderstorm with slight and heavy hail
|
||||
`,
|
||||
parameters: z.object({
|
||||
location: z.string().describe("The location to get the weather"),
|
||||
}),
|
||||
execute: async ({ location }): Promise<WeatherToolOutput> => {
|
||||
return await getWeatherByLocation(location);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
async function getWeatherByLocation(
|
||||
location: string,
|
||||
): Promise<WeatherToolOutput> {
|
||||
const { latitude, longitude } = await getGeoLocation(location);
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
|
||||
const params = new URLSearchParams({
|
||||
latitude: latitude.toString(),
|
||||
longitude: longitude.toString(),
|
||||
current: "temperature_2m,weather_code",
|
||||
hourly: "temperature_2m,weather_code",
|
||||
daily: "weather_code",
|
||||
timezone,
|
||||
});
|
||||
|
||||
const apiUrl = `https://api.open-meteo.com/v1/forecast?${params}`;
|
||||
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Weather API request failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return (await response.json()) as WeatherToolOutput;
|
||||
}
|
||||
|
||||
async function getGeoLocation(
|
||||
location: string,
|
||||
): Promise<{ latitude: number; longitude: number }> {
|
||||
const params = new URLSearchParams({
|
||||
name: location,
|
||||
count: "10",
|
||||
language: "en",
|
||||
format: "json",
|
||||
});
|
||||
|
||||
const apiUrl = `https://geocoding-api.open-meteo.com/v1/search?${params}`;
|
||||
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Geocoding API request failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (!data.results?.length) {
|
||||
throw new Error(`No location found for: ${location}`);
|
||||
}
|
||||
|
||||
const { latitude, longitude } = data.results[0];
|
||||
return { latitude, longitude };
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { tool } from "@llamaindex/core/tools";
|
||||
import { default as wikipedia } from "wikipedia";
|
||||
import { z } from "zod";
|
||||
|
||||
export type WikiToolOutput = {
|
||||
title: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export const wiki = () => {
|
||||
return tool({
|
||||
name: "wikipedia",
|
||||
description: "Use this function to search Wikipedia",
|
||||
parameters: z.object({
|
||||
query: z.string().describe("The query to search for"),
|
||||
lang: z.string().describe("The language to search in").default("en"),
|
||||
}),
|
||||
execute: async ({ query, lang }): Promise<WikiToolOutput> => {
|
||||
wikipedia.setLang(lang);
|
||||
const searchResult = await wikipedia.search(query);
|
||||
const pageTitle = searchResult?.results[0]?.title;
|
||||
if (!pageTitle) return { title: "No search results.", content: "" };
|
||||
const result = await wikipedia.page(pageTitle, { autoSuggest: false });
|
||||
return { title: pageTitle, content: await result.content() };
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
import { Settings } from "@llamaindex/core/global";
|
||||
import { MockLLM } from "@llamaindex/core/utils";
|
||||
import { describe, expect, test } from "vitest";
|
||||
import {
|
||||
codeGenerator,
|
||||
type CodeGeneratorToolOutput,
|
||||
} from "../src/tools/code-generator";
|
||||
|
||||
Settings.llm = new MockLLM({
|
||||
responseMessage: `{
|
||||
"commentary": "Creating a simple Next.js page with a hello world message",
|
||||
"template": "nextjs-developer",
|
||||
"title": "Hello World App",
|
||||
"description": "A simple Next.js hello world application",
|
||||
"additional_dependencies": [],
|
||||
"has_additional_dependencies": false,
|
||||
"install_dependencies_command": "",
|
||||
"port": 3000,
|
||||
"file_path": "pages/index.tsx",
|
||||
"code": "export default function Home() { return <h1>Hello World</h1> }"
|
||||
}`,
|
||||
});
|
||||
|
||||
describe("Code Generator Tool", () => {
|
||||
test("generates Next.js application code", async () => {
|
||||
const generator = codeGenerator();
|
||||
const result = (await generator.call({
|
||||
requirement: "Create a simple Next.js hello world page",
|
||||
})) as CodeGeneratorToolOutput;
|
||||
|
||||
expect(result.isError).toBe(false);
|
||||
expect(result.artifact).toBeDefined();
|
||||
expect(result.artifact?.template).toBe("nextjs-developer");
|
||||
expect(result.artifact?.file_path).toBe("pages/index.tsx");
|
||||
expect(result.artifact?.code).toContain("export default");
|
||||
});
|
||||
});
|
||||
@@ -1,24 +0,0 @@
|
||||
import path from "path";
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { documentGenerator } from "../src/tools/document-generator";
|
||||
|
||||
// Mock the helper functions
|
||||
vi.mock("../src/helper", () => ({
|
||||
saveDocument: vi.fn().mockResolvedValue(undefined),
|
||||
getFileUrl: vi.fn().mockReturnValue("http://example.com/test-doc.html"),
|
||||
}));
|
||||
|
||||
describe("Document Generator Tool", () => {
|
||||
test("converts markdown to html document", async () => {
|
||||
const docGen = documentGenerator({
|
||||
outputDir: path.join(__dirname, "output"),
|
||||
});
|
||||
|
||||
const result = await docGen.call({
|
||||
originalContent: "# Hello World\nThis is a test",
|
||||
fileName: "test-doc",
|
||||
});
|
||||
|
||||
expect(result).toBe("URL: http://example.com/test-doc.html");
|
||||
});
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { duckduckgo, type DuckDuckGoToolOutput } from "../src/tools/duckduckgo";
|
||||
|
||||
describe("DuckDuckGo Tool", () => {
|
||||
test("performs search and returns results", async () => {
|
||||
const searchTool = duckduckgo();
|
||||
const results = (await searchTool.call({
|
||||
query: "OpenAI ChatGPT",
|
||||
maxResults: 3,
|
||||
})) as DuckDuckGoToolOutput;
|
||||
|
||||
expect(Array.isArray(results)).toBe(true);
|
||||
expect(results.length).toBeLessThanOrEqual(3);
|
||||
const firstResult = results[0];
|
||||
expect(firstResult).toHaveProperty("title");
|
||||
expect(firstResult).toHaveProperty("description");
|
||||
expect(firstResult).toHaveProperty("url");
|
||||
});
|
||||
});
|
||||
@@ -1,44 +0,0 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { fillMissingCells } from "../src/tools/form-filling";
|
||||
|
||||
vi.mock("fs", () => ({
|
||||
default: {
|
||||
readFile: vi.fn(),
|
||||
promises: {
|
||||
readFile: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("../src/helper", () => ({
|
||||
saveDocument: vi.fn(),
|
||||
getFileUrl: vi.fn().mockReturnValue("http://example.com/filled.csv"),
|
||||
}));
|
||||
|
||||
describe("Form Filling Tools", () => {
|
||||
test("fillMissingCells fills cells with provided answers", async () => {
|
||||
// Mock CSV content
|
||||
const mockCsvContent = "Name,Age,City\nJohn,,Paris\nMary,,";
|
||||
vi.mocked(fs.promises.readFile).mockResolvedValue(mockCsvContent);
|
||||
|
||||
const filler = fillMissingCells({
|
||||
outputDir: path.join(__dirname, "output"),
|
||||
});
|
||||
|
||||
const result = await filler.call({
|
||||
filePath: "test.csv",
|
||||
cells: [
|
||||
{
|
||||
rowIndex: 1,
|
||||
columnIndex: 1,
|
||||
answer: "25",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(result).toContain("Successfully filled missing cells");
|
||||
expect(result).toContain("http://example.com/filled.csv");
|
||||
});
|
||||
});
|
||||
@@ -1,45 +0,0 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import {
|
||||
imageGenerator,
|
||||
type ImgGeneratorToolOutput,
|
||||
} from "../src/tools/img-gen";
|
||||
|
||||
vi.mock("got", () => ({
|
||||
default: {
|
||||
post: vi.fn().mockReturnValue({
|
||||
buffer: vi.fn().mockResolvedValue(Buffer.from("mock-image-data")),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
describe("Image Generator Tool", () => {
|
||||
test("generates image from prompt", async () => {
|
||||
const imgTool = imageGenerator({
|
||||
apiKey: process.env.STABILITY_API_KEY!,
|
||||
outputDir: "output",
|
||||
fileServerURLPrefix: "http://localhost:3000",
|
||||
});
|
||||
|
||||
const result = (await imgTool.call({
|
||||
prompt: "a cute cat playing with yarn",
|
||||
})) as ImgGeneratorToolOutput;
|
||||
|
||||
expect(result.isSuccess).toBe(true);
|
||||
expect(result.imageUrl).toBeDefined();
|
||||
expect(result.errorMessage).toBeUndefined();
|
||||
});
|
||||
|
||||
test("does not throw error on valid prompt", async () => {
|
||||
const imgTool = imageGenerator({
|
||||
apiKey: process.env.STABILITY_API_KEY!,
|
||||
outputDir: "output",
|
||||
fileServerURLPrefix: "http://localhost:3000",
|
||||
});
|
||||
|
||||
expect(async () => {
|
||||
await imgTool.call({
|
||||
prompt: "a scenic mountain landscape",
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
import { Sandbox } from "@e2b/code-interpreter";
|
||||
import path from "path";
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import {
|
||||
interpreter,
|
||||
type InterpreterToolOutput,
|
||||
} from "../src/tools/interpreter";
|
||||
|
||||
vi.mock("@e2b/code-interpreter", () => ({
|
||||
Sandbox: {
|
||||
create: vi.fn().mockImplementation(() => ({
|
||||
runCode: vi.fn().mockResolvedValue({
|
||||
error: null,
|
||||
logs: {
|
||||
stdout: ["Hello, World!", "x = 2"],
|
||||
stderr: [],
|
||||
},
|
||||
text: "Hello, World!\nx = 2",
|
||||
results: [
|
||||
{
|
||||
formats: () => [],
|
||||
},
|
||||
],
|
||||
}),
|
||||
files: {
|
||||
write: vi.fn().mockResolvedValue(undefined),
|
||||
},
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
describe("Code Interpreter Tool", () => {
|
||||
test("executes simple python code", async () => {
|
||||
const interpreterTool = interpreter({
|
||||
apiKey: "mock-api-key",
|
||||
outputDir: path.join(__dirname, "output"),
|
||||
uploadedFilesDir: path.join(__dirname, "files"),
|
||||
});
|
||||
|
||||
const result = (await interpreterTool.call({
|
||||
code: "print('Hello, World!')\nx = 1 + 1\nprint(f'x = {x}')",
|
||||
})) as InterpreterToolOutput;
|
||||
|
||||
expect(Sandbox.create).toHaveBeenCalledWith({ apiKey: "mock-api-key" });
|
||||
expect(result.isError).toBe(false);
|
||||
expect(result.logs.stdout).toEqual(["Hello, World!", "x = 2"]);
|
||||
expect(result.retryCount).toBe(1);
|
||||
expect(result.extraResult).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -1,70 +0,0 @@
|
||||
import SwaggerParser from "@apidevtools/swagger-parser";
|
||||
import got from "got";
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { OpenAPIActionTool } from "../src/tools/openapi-action";
|
||||
|
||||
// Mock SwaggerParser and got
|
||||
vi.mock("@apidevtools/swagger-parser", () => ({
|
||||
default: {
|
||||
validate: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("got", () => ({
|
||||
default: {
|
||||
get: vi.fn(),
|
||||
post: vi.fn(),
|
||||
patch: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe("OpenAPI Action Tool", () => {
|
||||
test("loads and executes API requests", async () => {
|
||||
// Mock swagger spec
|
||||
vi.mocked(SwaggerParser.validate).mockResolvedValue({
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "Test API",
|
||||
description: "Test API Description",
|
||||
version: "1.0.0",
|
||||
},
|
||||
paths: {
|
||||
"/test": {
|
||||
get: {
|
||||
description: "Test endpoint",
|
||||
responses: {
|
||||
"200": {
|
||||
description: "Successful response",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Mock API response
|
||||
vi.mocked(got.get).mockReturnValue({
|
||||
json: () => Promise.resolve({ data: "test response" }),
|
||||
} as ReturnType<typeof got.get>);
|
||||
|
||||
const tool = new OpenAPIActionTool("https://api.test.com/openapi.json");
|
||||
const tools = await tool.toToolFunctions();
|
||||
|
||||
// Verify tools were created
|
||||
expect(tools).toHaveLength(4); // load_spec, get, post, patch
|
||||
|
||||
// Test GET request
|
||||
const result = await tool.getRequest({
|
||||
url: "https://api.test.com/test",
|
||||
params: { key: "value" },
|
||||
});
|
||||
|
||||
expect(got.get).toHaveBeenCalledWith(
|
||||
"https://api.test.com/test",
|
||||
expect.objectContaining({
|
||||
searchParams: { key: "value" },
|
||||
}),
|
||||
);
|
||||
expect(result).toEqual({ data: "test response" });
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { weather } from "../src/tools/weather";
|
||||
|
||||
describe("Weather Tool", () => {
|
||||
test("weather tool returns data for valid location", async () => {
|
||||
const weatherTool = weather();
|
||||
const result = await weatherTool.call({
|
||||
location: "London",
|
||||
});
|
||||
|
||||
expect(result).toHaveProperty("current");
|
||||
expect(result).toHaveProperty("hourly");
|
||||
expect(result).toHaveProperty("daily");
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { wiki } from "../src/tools/wiki";
|
||||
|
||||
describe("Wikipedia Tool", () => {
|
||||
test("wiki tool returns content for valid query", async () => {
|
||||
const wikipediaTool = wiki();
|
||||
const result = await wikipediaTool.call({
|
||||
query: "Albert Einstein",
|
||||
lang: "en",
|
||||
});
|
||||
|
||||
expect(result).toHaveProperty("title");
|
||||
expect(result).toHaveProperty("content");
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist/type",
|
||||
"tsBuildInfoFile": "./dist/.tsbuildinfo",
|
||||
"emitDeclarationOnly": true,
|
||||
"moduleResolution": "Bundler",
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["./src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
Generated
+19
-300
@@ -7,10 +7,6 @@ settings:
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
p-retry:
|
||||
specifier: ^6.2.1
|
||||
version: 6.2.1
|
||||
devDependencies:
|
||||
'@changesets/cli':
|
||||
specifier: ^2.27.5
|
||||
@@ -684,9 +680,6 @@ importers:
|
||||
'@llamaindex/together':
|
||||
specifier: ^0.0.5
|
||||
version: link:../packages/providers/together
|
||||
'@llamaindex/tools':
|
||||
specifier: ^0.0.1
|
||||
version: link:../packages/tools
|
||||
'@llamaindex/upstash':
|
||||
specifier: ^0.0.13
|
||||
version: link:../packages/providers/storage/upstash
|
||||
@@ -1273,9 +1266,6 @@ importers:
|
||||
bunchee:
|
||||
specifier: 6.4.0
|
||||
version: 6.4.0(typescript@5.7.3)
|
||||
vitest:
|
||||
specifier: ^2.1.5
|
||||
version: 2.1.5(@edge-runtime/vm@4.0.4)(@types/node@22.13.5)(happy-dom@15.11.7)(lightningcss@1.29.1)(msw@2.7.0(@types/node@22.13.5)(typescript@5.7.3))(terser@5.38.2)
|
||||
|
||||
packages/providers/mixedbread:
|
||||
dependencies:
|
||||
@@ -1307,12 +1297,6 @@ importers:
|
||||
remeda:
|
||||
specifier: ^2.17.3
|
||||
version: 2.20.1
|
||||
zod:
|
||||
specifier: ^3.24.2
|
||||
version: 3.24.2
|
||||
zod-to-json-schema:
|
||||
specifier: ^3.23.3
|
||||
version: 3.24.1(zod@3.24.2)
|
||||
devDependencies:
|
||||
bunchee:
|
||||
specifier: 6.4.0
|
||||
@@ -1329,9 +1313,6 @@ importers:
|
||||
openai:
|
||||
specifier: ^4.86.0
|
||||
version: 4.86.0(ws@8.18.0(bufferutil@4.0.9))(zod@3.24.2)
|
||||
zod:
|
||||
specifier: ^3.24.2
|
||||
version: 3.24.2
|
||||
devDependencies:
|
||||
bunchee:
|
||||
specifier: 6.4.0
|
||||
@@ -1702,6 +1683,9 @@ importers:
|
||||
notion-md-crawler:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.1
|
||||
papaparse:
|
||||
specifier: ^5.4.1
|
||||
version: 5.5.2
|
||||
unpdf:
|
||||
specifier: ^0.12.1
|
||||
version: 0.12.1
|
||||
@@ -1725,58 +1709,6 @@ importers:
|
||||
specifier: ^13.4.8
|
||||
version: 13.4.8
|
||||
|
||||
packages/tools:
|
||||
dependencies:
|
||||
'@apidevtools/swagger-parser':
|
||||
specifier: ^10.1.0
|
||||
version: 10.1.1(openapi-types@12.1.3)
|
||||
'@e2b/code-interpreter':
|
||||
specifier: ^1.0.4
|
||||
version: 1.0.4
|
||||
'@llamaindex/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@llamaindex/env':
|
||||
specifier: workspace:*
|
||||
version: link:../env
|
||||
ajv:
|
||||
specifier: ^8.12.0
|
||||
version: 8.17.1
|
||||
duck-duck-scrape:
|
||||
specifier: ^2.2.5
|
||||
version: 2.2.7
|
||||
formdata-node:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
got:
|
||||
specifier: ^14.4.1
|
||||
version: 14.4.6
|
||||
marked:
|
||||
specifier: ^14.1.2
|
||||
version: 14.1.4
|
||||
papaparse:
|
||||
specifier: ^5.4.1
|
||||
version: 5.5.2
|
||||
wikipedia:
|
||||
specifier: ^2.1.2
|
||||
version: 2.1.2
|
||||
zod:
|
||||
specifier: ^3.23.8
|
||||
version: 3.24.2
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^22.9.0
|
||||
version: 22.9.0
|
||||
'@types/papaparse':
|
||||
specifier: ^5.3.15
|
||||
version: 5.3.15
|
||||
bunchee:
|
||||
specifier: 6.4.0
|
||||
version: 6.4.0(typescript@5.7.3)
|
||||
vitest:
|
||||
specifier: ^2.1.5
|
||||
version: 2.1.5(@edge-runtime/vm@4.0.4)(@types/node@22.9.0)(happy-dom@15.11.7)(lightningcss@1.29.1)(msw@2.7.0(@types/node@22.9.0)(typescript@5.7.3))(terser@5.38.2)
|
||||
|
||||
packages/wasm-tools:
|
||||
dependencies:
|
||||
'@assemblyscript/loader':
|
||||
@@ -1996,26 +1928,10 @@ packages:
|
||||
'@anthropic-ai/sdk@0.37.0':
|
||||
resolution: {integrity: sha512-tHjX2YbkUBwEgg0JZU3EFSSAQPoK4qQR/NFYa8Vtzd5UAyXzZksCw2In69Rml4R/TyHPBfRYaLK35XiOe33pjw==}
|
||||
|
||||
'@apidevtools/json-schema-ref-parser@11.7.2':
|
||||
resolution: {integrity: sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@apidevtools/json-schema-ref-parser@11.9.3':
|
||||
resolution: {integrity: sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@apidevtools/openapi-schemas@2.1.0':
|
||||
resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
'@apidevtools/swagger-methods@3.0.2':
|
||||
resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==}
|
||||
|
||||
'@apidevtools/swagger-parser@10.1.1':
|
||||
resolution: {integrity: sha512-u/kozRnsPO/x8QtKYJOqoGtC4kH6yg1lfYkB9Au0WhYB0FNLpyFusttQtvhlwjtG3rOwiRz4D8DnnXa8iEpIKA==}
|
||||
peerDependencies:
|
||||
openapi-types: '>=7'
|
||||
|
||||
'@assemblyscript/loader@0.27.34':
|
||||
resolution: {integrity: sha512-aUc12nBRN04dHn439RiI0G9X8CeOzbVuKspiVL1O8yS82neU3zTYjVFi9mz2+ZpSD2Laa7H0sUJ91jfhzQERMw==}
|
||||
|
||||
@@ -2318,9 +2234,6 @@ packages:
|
||||
resolution: {integrity: sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@bufbuild/protobuf@2.2.3':
|
||||
resolution: {integrity: sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==}
|
||||
|
||||
'@bundled-es-modules/cookie@2.0.1':
|
||||
resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==}
|
||||
|
||||
@@ -2502,17 +2415,6 @@ packages:
|
||||
resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
|
||||
engines: {node: '>=0.1.90'}
|
||||
|
||||
'@connectrpc/connect-web@2.0.0-rc.3':
|
||||
resolution: {integrity: sha512-w88P8Lsn5CCsA7MFRl2e6oLY4J/5toiNtJns/YJrlyQaWOy3RO8pDgkz+iIkG98RPMhj2thuBvsd3Cn4DKKCkw==}
|
||||
peerDependencies:
|
||||
'@bufbuild/protobuf': ^2.2.0
|
||||
'@connectrpc/connect': 2.0.0-rc.3
|
||||
|
||||
'@connectrpc/connect@2.0.0-rc.3':
|
||||
resolution: {integrity: sha512-ARBt64yEyKbanyRETTjcjJuHr2YXorzQo0etyS5+P6oSeW8xEuzajA9g+zDnMcj1hlX2dQE93foIWQGfpru7gQ==}
|
||||
peerDependencies:
|
||||
'@bufbuild/protobuf': ^2.2.0
|
||||
|
||||
'@cspotcode/source-map-support@0.8.1':
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -2544,10 +2446,6 @@ packages:
|
||||
resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==}
|
||||
engines: {node: '>=14.17.0'}
|
||||
|
||||
'@e2b/code-interpreter@1.0.4':
|
||||
resolution: {integrity: sha512-8y82UMXBdf/hye8bX2Fn04JlL72rvOenVgsvMZ+cAJqo6Ijdl4EmzzuFpM4mz9s+EJ29+34lGHBp277tiLWuiA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@edge-runtime/primitives@5.1.1':
|
||||
resolution: {integrity: sha512-osrHE4ObQ3XFkvd1sGBLkheV2mcHUqJI/Bum2AWA0R3U78h9lif3xZAdl6eLD/XnW4xhsdwjPUejLusXbjvI4Q==}
|
||||
engines: {node: '>=16'}
|
||||
@@ -4855,10 +4753,6 @@ packages:
|
||||
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
'@sindresorhus/is@7.0.1':
|
||||
resolution: {integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sitespeed.io/tracium@0.3.3':
|
||||
resolution: {integrity: sha512-dNZafjM93Y+F+sfwTO5gTpsGXlnc/0Q+c2+62ViqP3gkMWvHEMSKkaEHgVJLcLg3i/g19GSIPziiKpgyne07Bw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -5503,9 +5397,6 @@ packages:
|
||||
'@types/node@22.9.0':
|
||||
resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==}
|
||||
|
||||
'@types/papaparse@5.3.15':
|
||||
resolution: {integrity: sha512-JHe6vF6x/8Z85nCX4yFdDslN11d+1pr12E526X8WAfhadOeaOTx5AuIkvDKIBopfvlzpzkdMx4YyvSKCM9oqtw==}
|
||||
|
||||
'@types/pg@8.11.11':
|
||||
resolution: {integrity: sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==}
|
||||
|
||||
@@ -5532,9 +5423,6 @@ packages:
|
||||
'@types/resolve@1.20.2':
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
|
||||
'@types/retry@0.12.2':
|
||||
resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==}
|
||||
|
||||
'@types/statuses@2.0.5':
|
||||
resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==}
|
||||
|
||||
@@ -6361,10 +6249,6 @@ packages:
|
||||
resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
cacheable-request@12.0.1:
|
||||
resolution: {integrity: sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -6377,9 +6261,6 @@ packages:
|
||||
resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-me-maybe@1.0.2:
|
||||
resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
|
||||
|
||||
callguard@2.0.0:
|
||||
resolution: {integrity: sha512-I3nd+fuj20FK1qu00ImrbH+II+8ULS6ioYr9igqR1xyqySoqc3DiHEyUM0mkoAdKeLGg2CtGnO8R3VRQX5krpQ==}
|
||||
|
||||
@@ -6633,9 +6514,6 @@ packages:
|
||||
commondir@1.0.1:
|
||||
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
|
||||
|
||||
compare-versions@6.1.1:
|
||||
resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==}
|
||||
|
||||
compute-scroll-into-view@3.1.1:
|
||||
resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==}
|
||||
|
||||
@@ -6959,9 +6837,6 @@ packages:
|
||||
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
duck-duck-scrape@2.2.7:
|
||||
resolution: {integrity: sha512-BEcglwnfx5puJl90KQfX+Q2q5vCguqyMpZcSRPBWk8OY55qWwV93+E+7DbIkrGDW4qkqPfUvtOUdi0lXz6lEMQ==}
|
||||
|
||||
duck@0.1.12:
|
||||
resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==}
|
||||
|
||||
@@ -6972,10 +6847,6 @@ packages:
|
||||
duplexify@4.1.3:
|
||||
resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==}
|
||||
|
||||
e2b@1.0.7:
|
||||
resolution: {integrity: sha512-7msagBbQ8tm51qaGp+hdaaaMjGG3zCzZtUS8bnz+LK7wdwtVTA1PmX+1Br9E3R7v6XIchnNWRpei+VjvGcfidA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
@@ -7844,10 +7715,6 @@ packages:
|
||||
resolution: {integrity: sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
got@14.4.6:
|
||||
resolution: {integrity: sha512-rnhwfM/PhMNJ1i17k3DuDqgj0cKx3IHxBKVv/WX1uDKqrhi2Gv3l7rhPThR/Cc6uU++dD97W9c8Y0qyw9x0jag==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
gpt-tokenizer@2.8.1:
|
||||
resolution: {integrity: sha512-8+a9ojzqfgiF3TK4oivGYjlycD8g5igLt8NQw3ndOIgLVKSGJDhUDNAfYSbtyyuTkha3R/R9F8XrwC7/B5TKfQ==}
|
||||
|
||||
@@ -8268,10 +8135,6 @@ packages:
|
||||
is-module@1.0.0:
|
||||
resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
|
||||
|
||||
is-network-error@1.1.0:
|
||||
resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
is-node-process@1.2.0:
|
||||
resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==}
|
||||
|
||||
@@ -8855,11 +8718,6 @@ packages:
|
||||
markdown-table@3.0.4:
|
||||
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
|
||||
|
||||
marked@14.1.4:
|
||||
resolution: {integrity: sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==}
|
||||
engines: {node: '>= 18'}
|
||||
hasBin: true
|
||||
|
||||
math-intrinsics@1.1.0:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -9464,11 +9322,6 @@ packages:
|
||||
resolution: {integrity: sha512-VVw8O5KrfvwqAFeNZEgBbdgA+AQaBlHcXEootWU7TWDaFWFI0VLfzyKMsRjnfdS3cVCpWmI04xLJonCvEv11VQ==}
|
||||
engines: {node: '>=0.4.10'}
|
||||
|
||||
needle@3.3.1:
|
||||
resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==}
|
||||
engines: {node: '>= 4.4.x'}
|
||||
hasBin: true
|
||||
|
||||
negotiator@1.0.0:
|
||||
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@@ -9749,18 +9602,9 @@ packages:
|
||||
zod:
|
||||
optional: true
|
||||
|
||||
openapi-fetch@0.9.8:
|
||||
resolution: {integrity: sha512-zM6elH0EZStD/gSiNlcPrzXcVQ/pZo3BDvC6CDwRDUt1dDzxlshpmQnpD6cZaJ39THaSmwVCxxRrPKNM1hHrDg==}
|
||||
|
||||
openapi-sampler@1.6.1:
|
||||
resolution: {integrity: sha512-s1cIatOqrrhSj2tmJ4abFYZQK6l5v+V4toO5q1Pa0DyN8mtyqy2I+Qrj5W9vOELEtybIMQs/TBZGVO/DtTFK8w==}
|
||||
|
||||
openapi-types@12.1.3:
|
||||
resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
|
||||
|
||||
openapi-typescript-helpers@0.0.8:
|
||||
resolution: {integrity: sha512-1eNjQtbfNi5Z/kFhagDIaIRj6qqDzhjNJKz8cmMW0CVdGwT6e1GLbAfgI0d28VTJa1A8jz82jm/4dG8qNoNS8g==}
|
||||
|
||||
opener@1.5.2:
|
||||
resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
|
||||
hasBin: true
|
||||
@@ -9805,10 +9649,6 @@ packages:
|
||||
resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
|
||||
engines: {node: '>=12.20'}
|
||||
|
||||
p-cancelable@4.0.1:
|
||||
resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
p-filter@2.1.0:
|
||||
resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -9837,10 +9677,6 @@ packages:
|
||||
resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
p-retry@6.2.1:
|
||||
resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==}
|
||||
engines: {node: '>=16.17'}
|
||||
|
||||
p-try@2.2.0:
|
||||
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -10691,10 +10527,6 @@ packages:
|
||||
resolution: {integrity: sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
retry@0.13.1:
|
||||
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
reusify@1.0.4:
|
||||
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
@@ -12401,33 +12233,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
'@apidevtools/json-schema-ref-parser@11.7.2':
|
||||
dependencies:
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
'@types/json-schema': 7.0.15
|
||||
js-yaml: 4.1.0
|
||||
|
||||
'@apidevtools/json-schema-ref-parser@11.9.3':
|
||||
dependencies:
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
'@types/json-schema': 7.0.15
|
||||
js-yaml: 4.1.0
|
||||
|
||||
'@apidevtools/openapi-schemas@2.1.0': {}
|
||||
|
||||
'@apidevtools/swagger-methods@3.0.2': {}
|
||||
|
||||
'@apidevtools/swagger-parser@10.1.1(openapi-types@12.1.3)':
|
||||
dependencies:
|
||||
'@apidevtools/json-schema-ref-parser': 11.7.2
|
||||
'@apidevtools/openapi-schemas': 2.1.0
|
||||
'@apidevtools/swagger-methods': 3.0.2
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
ajv: 8.17.1
|
||||
ajv-draft-04: 1.0.0(ajv@8.17.1)
|
||||
call-me-maybe: 1.0.2
|
||||
openapi-types: 12.1.3
|
||||
|
||||
'@assemblyscript/loader@0.27.34': {}
|
||||
|
||||
'@aws-crypto/crc32@3.0.0':
|
||||
@@ -13220,8 +13031,6 @@ snapshots:
|
||||
'@babel/helper-string-parser': 7.25.9
|
||||
'@babel/helper-validator-identifier': 7.25.9
|
||||
|
||||
'@bufbuild/protobuf@2.2.3': {}
|
||||
|
||||
'@bundled-es-modules/cookie@2.0.1':
|
||||
dependencies:
|
||||
cookie: 0.7.2
|
||||
@@ -13533,15 +13342,6 @@ snapshots:
|
||||
|
||||
'@colors/colors@1.6.0': {}
|
||||
|
||||
'@connectrpc/connect-web@2.0.0-rc.3(@bufbuild/protobuf@2.2.3)(@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.2.3))':
|
||||
dependencies:
|
||||
'@bufbuild/protobuf': 2.2.3
|
||||
'@connectrpc/connect': 2.0.0-rc.3(@bufbuild/protobuf@2.2.3)
|
||||
|
||||
'@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.2.3)':
|
||||
dependencies:
|
||||
'@bufbuild/protobuf': 2.2.3
|
||||
|
||||
'@cspotcode/source-map-support@0.8.1':
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
@@ -13582,10 +13382,6 @@ snapshots:
|
||||
|
||||
'@discoveryjs/json-ext@0.6.3': {}
|
||||
|
||||
'@e2b/code-interpreter@1.0.4':
|
||||
dependencies:
|
||||
e2b: 1.0.7
|
||||
|
||||
'@edge-runtime/primitives@5.1.1': {}
|
||||
|
||||
'@edge-runtime/vm@4.0.4':
|
||||
@@ -15836,8 +15632,6 @@ snapshots:
|
||||
|
||||
'@sindresorhus/is@5.6.0': {}
|
||||
|
||||
'@sindresorhus/is@7.0.1': {}
|
||||
|
||||
'@sitespeed.io/tracium@0.3.3':
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
@@ -16583,10 +16377,6 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.19.8
|
||||
|
||||
'@types/papaparse@5.3.15':
|
||||
dependencies:
|
||||
'@types/node': 22.9.0
|
||||
|
||||
'@types/pg@8.11.11':
|
||||
dependencies:
|
||||
'@types/node': 22.9.0
|
||||
@@ -16623,8 +16413,6 @@ snapshots:
|
||||
|
||||
'@types/resolve@1.20.2': {}
|
||||
|
||||
'@types/retry@0.12.2': {}
|
||||
|
||||
'@types/statuses@2.0.5': {}
|
||||
|
||||
'@types/tough-cookie@4.0.5': {}
|
||||
@@ -16650,10 +16438,10 @@ snapshots:
|
||||
'@types/node': 22.9.0
|
||||
optional: true
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
'@typescript-eslint/parser': 8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
'@typescript-eslint/parser': 8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
'@typescript-eslint/scope-manager': 8.24.0
|
||||
'@typescript-eslint/type-utils': 8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
'@typescript-eslint/utils': 8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
@@ -17678,16 +17466,6 @@ snapshots:
|
||||
normalize-url: 8.0.1
|
||||
responselike: 3.0.0
|
||||
|
||||
cacheable-request@12.0.1:
|
||||
dependencies:
|
||||
'@types/http-cache-semantics': 4.0.4
|
||||
get-stream: 9.0.1
|
||||
http-cache-semantics: 4.1.1
|
||||
keyv: 4.5.4
|
||||
mimic-response: 4.0.0
|
||||
normalize-url: 8.0.1
|
||||
responselike: 3.0.0
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@@ -17705,8 +17483,6 @@ snapshots:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
get-intrinsic: 1.2.7
|
||||
|
||||
call-me-maybe@1.0.2: {}
|
||||
|
||||
callguard@2.0.0: {}
|
||||
|
||||
callsites@3.1.0: {}
|
||||
@@ -17964,8 +17740,6 @@ snapshots:
|
||||
|
||||
commondir@1.0.1: {}
|
||||
|
||||
compare-versions@6.1.1: {}
|
||||
|
||||
compute-scroll-into-view@3.1.1: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
@@ -18254,11 +18028,6 @@ snapshots:
|
||||
|
||||
dotenv@16.4.7: {}
|
||||
|
||||
duck-duck-scrape@2.2.7:
|
||||
dependencies:
|
||||
html-entities: 2.5.2
|
||||
needle: 3.3.1
|
||||
|
||||
duck@0.1.12:
|
||||
dependencies:
|
||||
underscore: 1.13.7
|
||||
@@ -18276,15 +18045,6 @@ snapshots:
|
||||
readable-stream: 3.6.2
|
||||
stream-shift: 1.0.3
|
||||
|
||||
e2b@1.0.7:
|
||||
dependencies:
|
||||
'@bufbuild/protobuf': 2.2.3
|
||||
'@connectrpc/connect': 2.0.0-rc.3(@bufbuild/protobuf@2.2.3)
|
||||
'@connectrpc/connect-web': 2.0.0-rc.3(@bufbuild/protobuf@2.2.3)(@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.2.3))
|
||||
compare-versions: 6.1.1
|
||||
openapi-fetch: 0.9.8
|
||||
platform: 1.3.6
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
@@ -18571,12 +18331,12 @@ snapshots:
|
||||
dependencies:
|
||||
'@next/eslint-plugin-next': 15.1.0
|
||||
'@rushstack/eslint-patch': 1.10.5
|
||||
'@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
'@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
'@typescript-eslint/parser': 8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
eslint: 9.16.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.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-plugin-react: 7.37.2(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-plugin-react-hooks: 5.1.0(eslint@9.16.0(jiti@2.4.2))
|
||||
@@ -18596,7 +18356,7 @@ snapshots:
|
||||
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)(eslint@9.22.0(jiti@2.4.2))
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2))
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(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-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))
|
||||
eslint-plugin-react-hooks: 5.1.0(eslint@9.22.0(jiti@2.4.2))
|
||||
@@ -18625,7 +18385,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2)):
|
||||
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
|
||||
debug: 4.4.0
|
||||
@@ -18637,7 +18397,7 @@ snapshots:
|
||||
is-glob: 4.0.3
|
||||
stable-hash: 0.0.4
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2))
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.16.0(jiti@2.4.2))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -18653,18 +18413,18 @@ snapshots:
|
||||
is-glob: 4.0.3
|
||||
stable-hash: 0.0.4
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2))
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(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))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.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.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2)):
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.16.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
'@typescript-eslint/parser': 8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
eslint: 9.16.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.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.16.0(jiti@2.4.2))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -18679,7 +18439,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2)):
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.16.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.8
|
||||
@@ -18690,7 +18450,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 9.16.0(jiti@2.4.2)
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.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.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2)))(eslint@9.16.0(jiti@2.4.2))
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.16.0(jiti@2.4.2))
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
@@ -18702,13 +18462,13 @@ snapshots:
|
||||
string.prototype.trimend: 1.0.9
|
||||
tsconfig-paths: 3.15.0
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
'@typescript-eslint/parser': 8.24.0(eslint@9.16.0(jiti@2.4.2))(typescript@5.7.3)
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.22.0(jiti@2.4.2)):
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(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)):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.8
|
||||
@@ -19718,20 +19478,6 @@ snapshots:
|
||||
p-cancelable: 3.0.0
|
||||
responselike: 3.0.0
|
||||
|
||||
got@14.4.6:
|
||||
dependencies:
|
||||
'@sindresorhus/is': 7.0.1
|
||||
'@szmarczak/http-timer': 5.0.1
|
||||
cacheable-lookup: 7.0.0
|
||||
cacheable-request: 12.0.1
|
||||
decompress-response: 6.0.0
|
||||
form-data-encoder: 4.0.2
|
||||
http2-wrapper: 2.2.1
|
||||
lowercase-keys: 3.0.0
|
||||
p-cancelable: 4.0.1
|
||||
responselike: 3.0.0
|
||||
type-fest: 4.34.1
|
||||
|
||||
gpt-tokenizer@2.8.1: {}
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
@@ -20324,8 +20070,6 @@ snapshots:
|
||||
|
||||
is-module@1.0.0: {}
|
||||
|
||||
is-network-error@1.1.0: {}
|
||||
|
||||
is-node-process@1.2.0: {}
|
||||
|
||||
is-number-object@1.1.1:
|
||||
@@ -20895,8 +20639,6 @@ snapshots:
|
||||
|
||||
markdown-table@3.0.4: {}
|
||||
|
||||
marked@14.1.4: {}
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
md-utils-ts@2.0.0: {}
|
||||
@@ -21986,11 +21728,6 @@ snapshots:
|
||||
- socks
|
||||
- supports-color
|
||||
|
||||
needle@3.3.1:
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
sax: 1.4.1
|
||||
|
||||
negotiator@1.0.0: {}
|
||||
|
||||
neo-async@2.6.2: {}
|
||||
@@ -22305,20 +22042,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
openapi-fetch@0.9.8:
|
||||
dependencies:
|
||||
openapi-typescript-helpers: 0.0.8
|
||||
|
||||
openapi-sampler@1.6.1:
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
fast-xml-parser: 4.5.3
|
||||
json-pointer: 0.6.2
|
||||
|
||||
openapi-types@12.1.3: {}
|
||||
|
||||
openapi-typescript-helpers@0.0.8: {}
|
||||
|
||||
opener@1.5.2: {}
|
||||
|
||||
option@0.2.4: {}
|
||||
@@ -22390,8 +22119,6 @@ snapshots:
|
||||
|
||||
p-cancelable@3.0.0: {}
|
||||
|
||||
p-cancelable@4.0.1: {}
|
||||
|
||||
p-filter@2.1.0:
|
||||
dependencies:
|
||||
p-map: 2.1.0
|
||||
@@ -22418,12 +22145,6 @@ snapshots:
|
||||
|
||||
p-map@2.1.0: {}
|
||||
|
||||
p-retry@6.2.1:
|
||||
dependencies:
|
||||
'@types/retry': 0.12.2
|
||||
is-network-error: 1.1.0
|
||||
retry: 0.13.1
|
||||
|
||||
p-try@2.2.0: {}
|
||||
|
||||
pac-proxy-agent@7.1.0:
|
||||
@@ -23422,8 +23143,6 @@ snapshots:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
||||
retry@0.13.1: {}
|
||||
|
||||
reusify@1.0.4: {}
|
||||
|
||||
rfdc@1.4.1: {}
|
||||
|
||||
@@ -190,9 +190,6 @@
|
||||
},
|
||||
{
|
||||
"path": "./packages/providers/perplexity/tsconfig.json"
|
||||
},
|
||||
{
|
||||
"path": "./packages/tools/tsconfig.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user