From 10895d3cdc8bfe55e045b4589c4c8fc54120d176 Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Fri, 10 Jan 2025 17:56:35 +0530 Subject: [PATCH 01/34] feat: add support for llamaindex (TS) --- js/src/frameworks/llamaindex.spec.ts | 76 +++++++++++++++++ js/src/frameworks/llamaindex.ts | 123 +++++++++++++++++++++++++++ js/src/index.ts | 2 + 3 files changed, 201 insertions(+) create mode 100644 js/src/frameworks/llamaindex.spec.ts create mode 100644 js/src/frameworks/llamaindex.ts diff --git a/js/src/frameworks/llamaindex.spec.ts b/js/src/frameworks/llamaindex.spec.ts new file mode 100644 index 00000000000..e76c4a75d21 --- /dev/null +++ b/js/src/frameworks/llamaindex.spec.ts @@ -0,0 +1,76 @@ +import { beforeAll, describe, expect, it } from "@jest/globals"; +import { getTestConfig } from "../../config/getTestConfig"; +import { LlamaIndexToolSet } from "./llamaindex"; +import { ActionExecuteResponse } from "../sdk/models/actions"; +import { z } from "zod"; + +describe("Apps class tests", () => { + let langchainToolSet: LlamaIndexToolSet; + beforeAll(() => { + langchainToolSet = new LlamaIndexToolSet({ + // apiKey: getTestConfig().COMPOSIO_API_KEY, + apiKey: "dbosseffg2hmhuydsm1tej", + baseUrl: getTestConfig().BACKEND_HERMES_URL, + }); + }); + + it("getools", async () => { + const tools = await langchainToolSet.getTools({ + apps: ["GITHUB"], + }); + expect(tools).toBeInstanceOf(Array); + }); + it("check if tools are coming", async () => { + const tools = await langchainToolSet.getTools({ + actions: ["GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER"], + }); + expect(tools.length).toBe(1); + }); + it("check if getTools, actions are coming", async () => { + const tools = await langchainToolSet.getTools({ + actions: ["GITHUB_GITHUB_API_ROOT"], + }); + + expect(tools.length).toBe(1); + }); + it("Should create custom action to star a repository", async () => { + await langchainToolSet.createAction({ + actionName: "starRepositoryCustomAction", + toolName: "github", + description: "This action stars a repository", + inputParams: z.object({ + owner: z.string(), + repo: z.string(), + }), + callback: async ( + inputParams, + _authCredentials, + executeRequest + ): Promise => { + const res = await executeRequest({ + endpoint: `/user/starred/${inputParams.owner}/${inputParams.repo}`, + method: "PUT", + parameters: [], + }); + return res; + }, + }); + + const tools = await langchainToolSet.getTools({ + actions: ["starRepositoryCustomAction"], + }); + + await expect(tools.length).toBe(1); + const actionOuput = await langchainToolSet.executeAction({ + action: "starRepositoryCustomAction", + params: { + owner: "composioHQ", + repo: "composio", + }, + entityId: "default", + connectedAccountId: "4364bbb6-3382-4bb6-b4be-e7ff440f90b4", + }); + + expect(actionOuput).toHaveProperty("successful", true); + }); +}); diff --git a/js/src/frameworks/llamaindex.ts b/js/src/frameworks/llamaindex.ts new file mode 100644 index 00000000000..6f83b4b0d85 --- /dev/null +++ b/js/src/frameworks/llamaindex.ts @@ -0,0 +1,123 @@ +import { FunctionTool, OpenAI, OpenAIAgent, type JSONValue } from "llamaindex"; +import { z } from "zod"; +import { ComposioToolSet as BaseComposioToolSet } from "../sdk/base.toolset"; +import { COMPOSIO_BASE_URL } from "../sdk/client/core/OpenAPI"; +import { TELEMETRY_LOGGER } from "../sdk/utils/telemetry"; +import { TELEMETRY_EVENTS } from "../sdk/utils/telemetry/events"; +import { ZToolSchemaFilter } from "../types/base_toolset"; +import { Optional, Sequence } from "../types/util"; + +export class LlamaIndexToolSet extends BaseComposioToolSet { + /** + * Composio toolset for LlamaIndex framework. + * + */ + static FRAMEWORK_NAME = "llamaindex"; + static DEFAULT_ENTITY_ID = "default"; + fileName: string = "js/src/frameworks/llamaindex.ts"; + private llm: OpenAI; + + constructor( + config: { + apiKey?: Optional; + baseUrl?: Optional; + entityId?: string; + runtime?: string; + } = {} + ) { + super({ + apiKey: config.apiKey || null, + baseUrl: config.baseUrl || COMPOSIO_BASE_URL, + runtime: config?.runtime || null, + entityId: config.entityId || LlamaIndexToolSet.DEFAULT_ENTITY_ID, + }); + this.llm = new OpenAI({ + apiKey: config.apiKey || process.env.OPENAI_API_KEY, + }); + } + + private _wrapTool( + schema: any, + entityId: Optional = null + ): FunctionTool, JSONValue | Promise> { + return FunctionTool.from( + async (params: Record) => { + const result = await this.executeAction({ + action: schema.name, + params, + entityId: entityId || this.entityId, + }); + return JSON.parse(JSON.stringify(result)) as JSONValue; + }, + { + name: schema.name, + description: schema.description, + parameters: { + type: "object", + properties: schema.parameters.properties || {}, + required: schema.parameters.required || [], + }, + } + ); + } + + async getTools( + filters: z.infer = {}, + entityId: Optional = null + ): Promise< + Sequence< + FunctionTool, JSONValue | Promise> + > + > { + TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { + method: "getTools", + file: this.fileName, + params: { filters, entityId }, + }); + + const tools = await this.getToolsSchema(filters, entityId); + return tools.map((tool) => { + const wrappedTool = this._wrapTool(tool, entityId || this.entityId); + // Add additional properties for better logging + Object.assign(wrappedTool, { + name: tool.name, + description: tool.description, + parameters: tool.parameters, + }); + return wrappedTool; + }); + } + + async executeToolCall( + tool: { name: string; parameters: Record }, + entityId: Optional = null + ): Promise { + TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { + method: "executeToolCall", + file: this.fileName, + params: { tool, entityId }, + }); + + return JSON.stringify( + await this.executeAction({ + action: tool.name, + params: tool.parameters, + entityId: entityId || this.entityId, + }) + ); + } + + async createAgent( + systemPrompt: string, + tools?: FunctionTool, Promise>[], + entityId: Optional = null + ) { + const agentTools = tools || (await this.getTools({}, entityId)); + + return new OpenAIAgent({ + llm: this.llm, + tools: agentTools, + systemPrompt, + }); + } +} diff --git a/js/src/index.ts b/js/src/index.ts index de301a49998..78b59c279a6 100644 --- a/js/src/index.ts +++ b/js/src/index.ts @@ -1,6 +1,7 @@ import { CloudflareToolSet } from "./frameworks/cloudflare"; import { LangchainToolSet } from "./frameworks/langchain"; import { LangGraphToolSet } from "./frameworks/langgraph"; +import { LlamaIndexToolSet } from "./frameworks/llamaindex"; import { OpenAIToolSet } from "./frameworks/openai"; import { VercelAIToolSet } from "./frameworks/vercel"; import { ComposioToolSet } from "./sdk/base.toolset"; @@ -26,6 +27,7 @@ export { ConnectionRequest, LangGraphToolSet, LangchainToolSet, + LlamaIndexToolSet, OpenAIToolSet, VercelAIToolSet, }; From f33976d516b6886f66523b7abca04ceb5a1605d9 Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Fri, 10 Jan 2025 23:29:44 +0530 Subject: [PATCH 02/34] fix: llamaindex tests --- js/src/frameworks/llamaindex.spec.ts | 29 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/js/src/frameworks/llamaindex.spec.ts b/js/src/frameworks/llamaindex.spec.ts index e76c4a75d21..795652aa900 100644 --- a/js/src/frameworks/llamaindex.spec.ts +++ b/js/src/frameworks/llamaindex.spec.ts @@ -1,40 +1,39 @@ import { beforeAll, describe, expect, it } from "@jest/globals"; +import { z } from "zod"; import { getTestConfig } from "../../config/getTestConfig"; -import { LlamaIndexToolSet } from "./llamaindex"; import { ActionExecuteResponse } from "../sdk/models/actions"; -import { z } from "zod"; +import { LlamaIndexToolSet } from "./llamaindex"; describe("Apps class tests", () => { - let langchainToolSet: LlamaIndexToolSet; + let llamaindexToolSet: LlamaIndexToolSet; beforeAll(() => { - langchainToolSet = new LlamaIndexToolSet({ - // apiKey: getTestConfig().COMPOSIO_API_KEY, - apiKey: "dbosseffg2hmhuydsm1tej", + llamaindexToolSet = new LlamaIndexToolSet({ + apiKey: getTestConfig().COMPOSIO_API_KEY, baseUrl: getTestConfig().BACKEND_HERMES_URL, }); }); it("getools", async () => { - const tools = await langchainToolSet.getTools({ - apps: ["GITHUB"], + const tools = await llamaindexToolSet.getTools({ + apps: ["github"], }); expect(tools).toBeInstanceOf(Array); }); it("check if tools are coming", async () => { - const tools = await langchainToolSet.getTools({ - actions: ["GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER"], + const tools = await llamaindexToolSet.getTools({ + actions: ["GITHUB_GITHUB_API_ROOT"], }); expect(tools.length).toBe(1); }); it("check if getTools, actions are coming", async () => { - const tools = await langchainToolSet.getTools({ + const tools = await llamaindexToolSet.getTools({ actions: ["GITHUB_GITHUB_API_ROOT"], }); expect(tools.length).toBe(1); }); it("Should create custom action to star a repository", async () => { - await langchainToolSet.createAction({ + await llamaindexToolSet.createAction({ actionName: "starRepositoryCustomAction", toolName: "github", description: "This action stars a repository", @@ -56,19 +55,19 @@ describe("Apps class tests", () => { }, }); - const tools = await langchainToolSet.getTools({ + const tools = await llamaindexToolSet.getTools({ actions: ["starRepositoryCustomAction"], }); await expect(tools.length).toBe(1); - const actionOuput = await langchainToolSet.executeAction({ + const actionOuput = await llamaindexToolSet.executeAction({ action: "starRepositoryCustomAction", params: { owner: "composioHQ", repo: "composio", }, entityId: "default", - connectedAccountId: "4364bbb6-3382-4bb6-b4be-e7ff440f90b4", + connectedAccountId: "9442cab3-d54f-4903-976c-ee67ef506c9b", }); expect(actionOuput).toHaveProperty("successful", true); From b7a848188bd3abb501cf55d5aa32d96fa412a8ef Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Fri, 10 Jan 2025 23:58:02 +0530 Subject: [PATCH 03/34] feat: add LlamaIndex TS framework support --- js/src/frameworks/llamaindex.spec.ts | 2 +- js/src/frameworks/llamaindex.ts | 40 +--------------------------- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/js/src/frameworks/llamaindex.spec.ts b/js/src/frameworks/llamaindex.spec.ts index 795652aa900..6fa3c8bf32c 100644 --- a/js/src/frameworks/llamaindex.spec.ts +++ b/js/src/frameworks/llamaindex.spec.ts @@ -8,7 +8,7 @@ describe("Apps class tests", () => { let llamaindexToolSet: LlamaIndexToolSet; beforeAll(() => { llamaindexToolSet = new LlamaIndexToolSet({ - apiKey: getTestConfig().COMPOSIO_API_KEY, + apiKey: getTestConfig().COMPOSIO_API_KEY, baseUrl: getTestConfig().BACKEND_HERMES_URL, }); }); diff --git a/js/src/frameworks/llamaindex.ts b/js/src/frameworks/llamaindex.ts index 6f83b4b0d85..9e996088ce4 100644 --- a/js/src/frameworks/llamaindex.ts +++ b/js/src/frameworks/llamaindex.ts @@ -1,4 +1,4 @@ -import { FunctionTool, OpenAI, OpenAIAgent, type JSONValue } from "llamaindex"; +import { FunctionTool, type JSONValue } from "llamaindex"; import { z } from "zod"; import { ComposioToolSet as BaseComposioToolSet } from "../sdk/base.toolset"; import { COMPOSIO_BASE_URL } from "../sdk/client/core/OpenAPI"; @@ -15,7 +15,6 @@ export class LlamaIndexToolSet extends BaseComposioToolSet { static FRAMEWORK_NAME = "llamaindex"; static DEFAULT_ENTITY_ID = "default"; fileName: string = "js/src/frameworks/llamaindex.ts"; - private llm: OpenAI; constructor( config: { @@ -31,9 +30,6 @@ export class LlamaIndexToolSet extends BaseComposioToolSet { runtime: config?.runtime || null, entityId: config.entityId || LlamaIndexToolSet.DEFAULT_ENTITY_ID, }); - this.llm = new OpenAI({ - apiKey: config.apiKey || process.env.OPENAI_API_KEY, - }); } private _wrapTool( @@ -78,7 +74,6 @@ export class LlamaIndexToolSet extends BaseComposioToolSet { const tools = await this.getToolsSchema(filters, entityId); return tools.map((tool) => { const wrappedTool = this._wrapTool(tool, entityId || this.entityId); - // Add additional properties for better logging Object.assign(wrappedTool, { name: tool.name, description: tool.description, @@ -87,37 +82,4 @@ export class LlamaIndexToolSet extends BaseComposioToolSet { return wrappedTool; }); } - - async executeToolCall( - tool: { name: string; parameters: Record }, - entityId: Optional = null - ): Promise { - TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { - method: "executeToolCall", - file: this.fileName, - params: { tool, entityId }, - }); - - return JSON.stringify( - await this.executeAction({ - action: tool.name, - params: tool.parameters, - entityId: entityId || this.entityId, - }) - ); - } - - async createAgent( - systemPrompt: string, - tools?: FunctionTool, Promise>[], - entityId: Optional = null - ) { - const agentTools = tools || (await this.getTools({}, entityId)); - - return new OpenAIAgent({ - llm: this.llm, - tools: agentTools, - systemPrompt, - }); - } } From 769477f7b2bb9eaa2882b1012b7aa17cb8c83b7f Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Sat, 11 Jan 2025 00:31:31 +0530 Subject: [PATCH 04/34] fix: added type to schema --- js/src/frameworks/llamaindex.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/js/src/frameworks/llamaindex.ts b/js/src/frameworks/llamaindex.ts index 9e996088ce4..3deffaa7c4b 100644 --- a/js/src/frameworks/llamaindex.ts +++ b/js/src/frameworks/llamaindex.ts @@ -7,6 +7,12 @@ import { TELEMETRY_EVENTS } from "../sdk/utils/telemetry/events"; import { ZToolSchemaFilter } from "../types/base_toolset"; import { Optional, Sequence } from "../types/util"; +type ToolSchema = { + name: string; + description: string; + parameters: Record; + }; + export class LlamaIndexToolSet extends BaseComposioToolSet { /** * Composio toolset for LlamaIndex framework. @@ -33,7 +39,7 @@ export class LlamaIndexToolSet extends BaseComposioToolSet { } private _wrapTool( - schema: any, + schema: ToolSchema, entityId: Optional = null ): FunctionTool, JSONValue | Promise> { return FunctionTool.from( From 57535ffb113fd51294d65028a2f0d5f8027ce5a7 Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Sat, 11 Jan 2025 00:36:12 +0530 Subject: [PATCH 05/34] fix: lint --- js/src/frameworks/llamaindex.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/src/frameworks/llamaindex.ts b/js/src/frameworks/llamaindex.ts index 3deffaa7c4b..4c6b98c6faf 100644 --- a/js/src/frameworks/llamaindex.ts +++ b/js/src/frameworks/llamaindex.ts @@ -8,10 +8,10 @@ import { ZToolSchemaFilter } from "../types/base_toolset"; import { Optional, Sequence } from "../types/util"; type ToolSchema = { - name: string; - description: string; - parameters: Record; - }; + name: string; + description: string; + parameters: Record; +}; export class LlamaIndexToolSet extends BaseComposioToolSet { /** From d60252281a5705dbd7ccabe4bc51545ddf14a5a1 Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Sat, 11 Jan 2025 00:43:16 +0530 Subject: [PATCH 06/34] fix: add llamaindex to peerDependencies --- js/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/js/package.json b/js/package.json index a3f45c05bbb..d802e446a53 100644 --- a/js/package.json +++ b/js/package.json @@ -40,6 +40,7 @@ "@langchain/openai": "^0.2.5", "ai": "^3.2.22", "langchain": "^0.2.11", + "llamaindex": "^0.8.31", "openai": "^4.50.0" }, "dependencies": { From 2d8a8ba94c406afd74ab23f6ad7957f971c15230 Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Mon, 20 Jan 2025 18:22:07 +0530 Subject: [PATCH 07/34] feat: SP --- js/package.json | 4 +- js/pnpm-lock.yaml | 4937 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 4765 insertions(+), 176 deletions(-) diff --git a/js/package.json b/js/package.json index d802e446a53..8656a8a9171 100644 --- a/js/package.json +++ b/js/package.json @@ -82,6 +82,7 @@ "globals": "^15.13.0", "jest": "^29.7.0", "jest-html-reporters": "^3.1.7", + "llamaindex": "^0.8.31", "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.1.0", "regenerator-runtime": "^0.14.1", @@ -100,5 +101,6 @@ }, "publishConfig": { "access": "public" - } + }, + "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" } diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 102fe296f88..f53aac8022d 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -46,7 +46,7 @@ importers: version: 8.4.2 openai: specifier: ^4.50.0 - version: 4.51.0 + version: 4.79.1(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) pusher-js: specifier: 8.4.0-rc2 version: 8.4.0-rc2 @@ -138,6 +138,9 @@ importers: jest-html-reporters: specifier: ^3.1.7 version: 3.1.7 + llamaindex: + specifier: ^0.8.31 + version: 0.8.31(@aws-sdk/credential-providers@3.731.1)(@huggingface/transformers@3.3.1)(bufferutil@4.0.8)(tree-sitter@0.22.4)(typescript@5.4.5)(utf-8-validate@6.0.4)(web-tree-sitter@0.24.7)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)) prettier: specifier: ^3.4.2 version: 3.4.2 @@ -270,10 +273,217 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@anthropic-ai/sdk@0.32.1': + resolution: {integrity: sha512-U9JwTrDvdQ9iWuABVsMLj8nJVwAyQz6QXvgLsVhryhCEPkLsbcP/MXxm+jYcAwLoV8ESbaTTjnD4kuAFa+Hyjg==} + '@apidevtools/json-schema-ref-parser@11.7.0': resolution: {integrity: sha512-pRrmXMCwnmrkS3MLgAIW5dXRzeTv6GLjkjb4HmxNnvAKXN1Nfzp4KmGADBQvlVUcqi+a5D+hfGDLLnd5NnYxog==} engines: {node: '>= 16'} + '@aws-crypto/crc32@3.0.0': + resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@3.0.0': + resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-cognito-identity@3.731.1': + resolution: {integrity: sha512-hlYxRERFNxa4Jplh8rjxbCvk6e4ybNKu2wQdiK46GS2N6io9Z62/CNqx3bMiqmjhk92LWXnYcpYwI2MG/WOEMQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sagemaker@3.731.1': + resolution: {integrity: sha512-DF0H/t1HisxMaU7BZxs9dAXZtfngEW3dMRWdYnp199WJKmgTcKoF3y3V8IpMd2mwWBgspXvG3uOJaJXZgTFQRQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sso-oidc@3.731.1': + resolution: {integrity: sha512-jli6vZ3U33L5AHkBqQmB5pO9+R+qfWxsnc1VOsYsNwWVrrR6kA7WS+N+r19BZGHE6Rzo/fWo0KsHH1fc9mGjaw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sso@3.731.0': + resolution: {integrity: sha512-O4C/UYGgqMsBg21MMApFdgyh8BX568hQhbdoNFmRVTBoSnCZ3w+H4a1wBPX4Gyl0NX+ab6Xxo9rId8HiyPXJ0A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/core@3.731.0': + resolution: {integrity: sha512-ithBN1VWASkvAIlozJmenqDvNnFddr/SZXAs58+jCnBHgy3tXLHABZGVNCjetZkHRqNdXEO1kirnoxaFeXMeDA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-cognito-identity@3.731.1': + resolution: {integrity: sha512-4MdhrZFkMxS/5ZUXaf6NIVa7N3NV259Q10jvfd6AzePd6sq10stJSyShvV7nC1dc/XneHammpYdXV2hlh6Almw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-env@3.731.0': + resolution: {integrity: sha512-h0WWZg4QMLgFVyIvQrC43zpVqsUWg1mPM1clpogP43B8+wEhDEQ4qWRzvFs3dQ4cqx/FLyDUZZF4cqgd94z7kw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-http@3.731.0': + resolution: {integrity: sha512-iRtrjtcYaWgbvtu2cvDhIsPWXZGvhy1Hgks4682MEBNTc9AUwlfvDrYz2EEnTtJJyrbOdEHVrYrzqD8qPyVLCg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-ini@3.731.1': + resolution: {integrity: sha512-0M0ejuqW8iHNcTH2ZXSY9m+I7Y06qVkj6k3vfQU9XaB//mTUCxxfGfqWAtgfr7Yi73egABTcPc0jyPdcvSW4Kw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-node@3.731.1': + resolution: {integrity: sha512-5c0ZiagMTPmWilXNffeXJCLoCEz97jilHr3QJWwf2GaTay4tzN+Ld71rpdfEenzUR7fuxEWFfVlwQbFOzFNYHg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-process@3.731.0': + resolution: {integrity: sha512-6yNMY6q3xHLbs2f2+C6GhvMrjTgtFBiPJJqKaPLsTIhlTRvh4sK8pGm3ITcma0jOxtPDIuoPfBAV8N8XVMBlZg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-sso@3.731.1': + resolution: {integrity: sha512-p1tp+rMUf5YNQLr8rVRmDgNtKGYLL0KCdq3K2hwwvFnx9MjReF1sA4lfm3xWsxBQM+j3QN9AvMQqBzDJ+NOSdw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.731.1': + resolution: {integrity: sha512-+ynAvEGWDR5ZJFxgpwwzhvlQ3WQ7BleWXU6JwpIw3yFrD4eZEn85b8DZC1aEz7C9kb1HSV6B3gpqHqlyS6wj8g==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-providers@3.731.1': + resolution: {integrity: sha512-Rjb14vXPa3flBJu9YDZkld0pYuR15DESMWGvCtQgGhcgpY8QH7vzxPU2C224SgYYkP0JM+7SRfadbcI5seTFuw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-host-header@3.731.0': + resolution: {integrity: sha512-ndAJsm5uWPPJRZowLKpB1zuL17qWlWVtCJP4I/ynBkq1PU1DijDXBul2UZaG6Mpvsgms1NXo/h9noHuK7T3v8w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-logger@3.731.0': + resolution: {integrity: sha512-IIZrOdjbY2vKzPJPrwE7FoFQCIPEL6UqURi8LEaiVyCag4p2fvaTN5pgKuQtGC2+iYd/HHcGT4qn2bAqF5Jmmw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.731.0': + resolution: {integrity: sha512-y6FLASB1iKWuR5tUipMyo77bt0lEl3OnCrrd2xw/H24avq1HhJjjPR0HHhJE6QKJzF/FYXeV88tcyPSMe32VDw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-user-agent@3.731.0': + resolution: {integrity: sha512-Ngr2Gz0aec/uduoKaO3srN52SYkEHndYtFzkK/gDUyQwQzi4ha2eIisxPiuHEX6RvXT31V9ouqn/YtVkt0R76A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/nested-clients@3.731.1': + resolution: {integrity: sha512-/L8iVrulnXZl+kgmTn+oxRxNnhcSIbf+r12C06vGUq60w0YMidLvxJZN7vt8H9SnCAGCHqud2MS7ExCEvhc0gA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/protocol-http@3.374.0': + resolution: {integrity: sha512-9WpRUbINdGroV3HiZZIBoJvL2ndoWk39OfwxWs2otxByppJZNN14bg/lvCx5e8ggHUti7IBk5rb0nqQZ4m05pg==} + engines: {node: '>=14.0.0'} + deprecated: This package has moved to @smithy/protocol-http + + '@aws-sdk/region-config-resolver@3.731.0': + resolution: {integrity: sha512-XlDpRNkDVHF59f07JmkuAidEv//m3hT6/JL85h0l3+zrpaRWhf8n8lVUyAPNq35ZujK8AcorYM+93u7hdWsliQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/signature-v4@3.374.0': + resolution: {integrity: sha512-2xLJvSdzcZZAg0lsDLUAuSQuihzK0dcxIK7WmfuJeF7DGKJFmp9czQmz5f3qiDz6IDQzvgK1M9vtJSVCslJbyQ==} + engines: {node: '>=14.0.0'} + deprecated: This package has moved to @smithy/signature-v4 + + '@aws-sdk/token-providers@3.731.1': + resolution: {integrity: sha512-t34GOPwBZsX7zGHjiTXmMHGY3kHM7fLiQ60Jqk0On9P0ASHTDE5U75RgCXboE3u+qEv9wyKyaqMNyMWj9qQlFg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/types@3.731.0': + resolution: {integrity: sha512-NrdkJg6oOUbXR2r9WvHP408CLyvST8cJfp1/jP9pemtjvjPoh6NukbCtiSFdOOb1eryP02CnqQWItfJC1p2Y/Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-endpoints@3.731.0': + resolution: {integrity: sha512-riztxTAfncFS9yQWcBJffGgOgLoKSa63ph+rxWJxKl6BHAmWEvHICj1qDcVmnWfIcvJ5cClclY75l9qKaUH7rQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-locate-window@3.723.0': + resolution: {integrity: sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-user-agent-browser@3.731.0': + resolution: {integrity: sha512-EnYXxTkCNCjTTBjW/pelRPv4Thsi9jepoB6qQjPMA9/ixrZ71BhhQecz9kgqzZLR9BPCwb6hgJ/Yd702jqJ4aQ==} + + '@aws-sdk/util-user-agent-node@3.731.0': + resolution: {integrity: sha512-Rze78Ym5Bx7aWMvmZE2iL3JPo2INNCC5N9rLVx98Gg1G0ZaxclVRUvJrh1AojNlOFxU+otkxAe7FA3Foy2iLLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/util-utf8-browser@3.259.0': + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + + '@azure/abort-controller@2.1.2': + resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} + engines: {node: '>=18.0.0'} + + '@azure/core-auth@1.9.0': + resolution: {integrity: sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==} + engines: {node: '>=18.0.0'} + + '@azure/core-client@1.9.2': + resolution: {integrity: sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==} + engines: {node: '>=18.0.0'} + + '@azure/core-http-compat@2.1.2': + resolution: {integrity: sha512-5MnV1yqzZwgNLLjlizsU3QqOeQChkIXw781Fwh1xdAqJR5AA32IUaq6xv1BICJvfbHoa+JYcaij2HFkhLbNTJQ==} + engines: {node: '>=18.0.0'} + + '@azure/core-paging@1.6.2': + resolution: {integrity: sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==} + engines: {node: '>=18.0.0'} + + '@azure/core-rest-pipeline@1.18.2': + resolution: {integrity: sha512-IkTf/DWKyCklEtN/WYW3lqEsIaUDshlzWRlZNNwSYtFcCBQz++OtOjxNpm8rr1VcbMS6RpjybQa3u6B6nG0zNw==} + engines: {node: '>=18.0.0'} + + '@azure/core-tracing@1.2.0': + resolution: {integrity: sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==} + engines: {node: '>=18.0.0'} + + '@azure/core-util@1.11.0': + resolution: {integrity: sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==} + engines: {node: '>=18.0.0'} + + '@azure/cosmos@4.2.0': + resolution: {integrity: sha512-acfAQTYLxgB/iZK7XvTVYe9NPk6DECEgcIXDQhyn7Uo4dGxeeW5D3YqLjLJrrzND5Iawer3eUQ5/iiLWvTGAxQ==} + engines: {node: '>=18.0.0'} + + '@azure/identity@4.6.0': + resolution: {integrity: sha512-ANpO1iAvcZmpD4QY7/kaE/P2n66pRXsDp3nMUC6Ow3c9KfXOZF7qMU9VgqPw8m7adP7TVIbVyrCEmD9cth3KQQ==} + engines: {node: '>=18.0.0'} + + '@azure/logger@1.1.4': + resolution: {integrity: sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==} + engines: {node: '>=18.0.0'} + + '@azure/msal-browser@4.0.1': + resolution: {integrity: sha512-jqiwVJPArnEOUhmc+dvo481OP8b2PMcsu3EtGtxt7sxmKgFtdQyGDCndj+2me62JVG/HEgArEgKyMA7L0aNhdA==} + engines: {node: '>=0.8.0'} + + '@azure/msal-common@14.16.0': + resolution: {integrity: sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==} + engines: {node: '>=0.8.0'} + + '@azure/msal-common@15.0.1': + resolution: {integrity: sha512-JELxEK3Pnc4Rq8u+mI9u6o37auSpSOPCB7jaq7QziOAKi9WliWEmZZORCFHPbwf2xKitpHBXTz/0uerj17NsSQ==} + engines: {node: '>=0.8.0'} + + '@azure/msal-node@2.16.2': + resolution: {integrity: sha512-An7l1hEr0w1HMMh1LU+rtDtqL7/jw74ORlc9Wnh06v7TU/xpG39/Zdr1ZJu3QpjUfKJ+E0/OXMW8DRSWTlh7qQ==} + engines: {node: '>=16'} + + '@azure/search-documents@12.1.0': + resolution: {integrity: sha512-IzD+hfqGqFtXymHXm4RzrZW2MsSH2M7RLmZsKaKVi7SUxbeYTUeX+ALk8gVzkM8ykb7EzlDLWCNErKfAa57rYQ==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.24.7': resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} @@ -457,6 +667,29 @@ packages: '@dabh/diagnostics@2.0.3': resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@datastax/astra-db-ts@1.5.0': + resolution: {integrity: sha512-Z9pEVyyHfglh8XAKrIASxdvORdei4pLUKDDGarqYvBkA9B9rKdqqdN+4I42Dz8paU5uscu8FwM5mc+Ly/U6jfA==} + engines: {node: '>=14.0.0'} + + '@discordjs/collection@2.1.1': + resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==} + engines: {node: '>=18'} + + '@discordjs/rest@2.4.2': + resolution: {integrity: sha512-9bOvXYLQd5IBg/kKGuEFq3cstVxAMJ6wMxO2U3wjrgO+lHv8oNCT+BBRpuzVQh7BoXKvk/gpajceGvQUiRoJ8g==} + engines: {node: '>=18'} + + '@discordjs/util@1.1.1': + resolution: {integrity: sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==} + engines: {node: '>=18'} + + '@discoveryjs/json-ext@0.6.3': + resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==} + engines: {node: '>=14.17.0'} + + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -495,6 +728,32 @@ packages: resolution: {integrity: sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'} + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@google-cloud/vertexai@1.9.0': + resolution: {integrity: sha512-8brlcJwFXI4fPuBtsDNQqCdWZmz8gV9jeEKOU0vc5H2SjehCQpXK/NwuSEr916zbhlBHtg/sU37qQQdgvh5BRA==} + engines: {node: '>=18.0.0'} + + '@google/generative-ai@0.21.0': + resolution: {integrity: sha512-7XhUbtnlkSEZK15kN3t+tzIMxsbKm/dSkKBFalj+20NvPKe1kBY7mR2P7vuijEn+f06z5+A8bVGKO0v39cr6Wg==} + engines: {node: '>=18.0.0'} + + '@graphql-typed-document-node/core@3.2.0': + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@grpc/grpc-js@1.12.5': + resolution: {integrity: sha512-d3iiHxdpg5+ZcJ6jnDSOT8Z0O0VMVGy34jAnYLUX8yd36b1qn8f1TwOA/Lc7TsOh03IkPJ38eGI5qD2EjNkoEA==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.13': + resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} + engines: {node: '>=6'} + hasBin: true + '@hey-api/client-axios@0.2.3': resolution: {integrity: sha512-v1BoTozp8LQ9JawZF9atXdmaBdQEvoIf39pIYf/0WSdkZSv0rUJDVXxNWHnDDs+S1/6pOfbOhM/0VXD5YJqr8w==} peerDependencies: @@ -507,6 +766,24 @@ packages: peerDependencies: typescript: ^5.x + '@huggingface/inference@2.8.1': + resolution: {integrity: sha512-EfsNtY9OR6JCNaUa5bZu2mrs48iqeTz0Gutwf+fU0Kypx33xFQB4DKMhp8u4Ee6qVbLbNWvTHuWwlppLQl4p4Q==} + engines: {node: '>=18'} + + '@huggingface/jinja@0.1.3': + resolution: {integrity: sha512-9KsiorsdIK8+7VmlamAT7Uh90zxAhC/SeKaKc80v58JhtPYuwaJpmR/ST7XAUxrHAFqHTCoTH5aJnJDwSL6xIQ==} + engines: {node: '>=18'} + + '@huggingface/jinja@0.3.2': + resolution: {integrity: sha512-F2FvuIc+w1blGsaqJI/OErRbWH6bVJDCBI8Rm5D86yZ2wlwrGERsfIaru7XUv9eYC3DMP3ixDRRtF0h6d8AZcQ==} + engines: {node: '>=18'} + + '@huggingface/tasks@0.12.30': + resolution: {integrity: sha512-A1ITdxbEzx9L8wKR8pF7swyrTLxWNDFIGDLUWInxvks2ruQ8PLRBZe8r0EcjC3CDdtlj9jV1V4cgV35K/iy3GQ==} + + '@huggingface/transformers@3.3.1': + resolution: {integrity: sha512-ypduhicsjFQAIcYPBicojDGz9jpvU+abCuoRFYj/V9glTmMVLlGxCwssAGSGmoC+T+FV9JFI5U8i2H+zpOxVbg==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -527,6 +804,111 @@ packages: resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} engines: {node: '>=18.18'} + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@inquirer/checkbox@2.5.0': resolution: {integrity: sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==} engines: {node: '>=18'} @@ -583,6 +965,14 @@ packages: resolution: {integrity: sha512-xUQ14WQGR/HK5ei+2CvgcwoH9fQ4PgPGmVFSN0pc1+fVyDL3MREhyAY7nxEErSu6CkllBM3D7e3e+kOvtu+eIg==} engines: {node: '>=18'} + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + '@istanbuljs/load-nyc-config@1.1.0': resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} @@ -684,6 +1074,9 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + '@jsdevtools/ono@7.1.3': resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} @@ -699,6 +1092,99 @@ packages: resolution: {integrity: sha512-cXWgKE3sdWLSqAa8ykbCcUsUF1Kyr5J3HOWYGuobhPEycXW4WI++d5DhzdpL238mzoEXTi90VqfSCra37l5YqA==} engines: {node: '>=18'} + '@llamaindex/anthropic@0.0.29': + resolution: {integrity: sha512-KbMbKDJbpCdoYToh722mHf2IaOC2fZb8YflD2QQszNNRDDR0C4crEHXws5eCPYB1CVGgqvSkb+3eWlWc6eLRsg==} + + '@llamaindex/clip@0.0.29': + resolution: {integrity: sha512-966pS5GPDGrpiv9TiZ0V+MaHXnP/JdFo1uBk4UvovBDr1VQ0oFjq3Hn0waprVniIV9jDwj6eRLS5Rl4dKdPIqw==} + peerDependencies: + '@huggingface/transformers': ^3.0.2 + + '@llamaindex/cloud@2.0.21': + resolution: {integrity: sha512-3zADFI4EjODGNETefNFMTzVhwIs2bBgS7l7Pln5cQQ6iVeZZSAp1dzTFyLBVlGh89/pvuhLm/hY9Ci7W2/1tMg==} + peerDependencies: + '@llamaindex/core': 0.4.20 + '@llamaindex/env': 0.1.25 + + '@llamaindex/core@0.4.20': + resolution: {integrity: sha512-IeZgtyyZk0tWuvF/HYeBFWPS0R6VH3uXFIWErESdNe22BUANtScSfhe+kubN3IFjhl5Wf1+ozqtyJCfNe4TW6A==} + + '@llamaindex/deepinfra@0.0.29': + resolution: {integrity: sha512-Kz6WVwNwJuB+rJDVXBB6G0LUTzVGpZWEbRXFx+D8MKvBF6XNJT8Omm/V93umzpvLGJQ6c29tSPTFDHrGZF7i5w==} + + '@llamaindex/env@0.1.25': + resolution: {integrity: sha512-wtvAhIAbRhEB66Zp8rMRUpnT1DRbEIyUFH9Ob82lw1nrT4vC0Snb5Seu2tzqfL6Oqu6W4Ea/8mphYwYMEphFdA==} + peerDependencies: + '@aws-crypto/sha256-js': ^5.2.0 + '@huggingface/transformers': ^3.0.2 + gpt-tokenizer: ^2.5.0 + js-tiktoken: ^1.0.12 + pathe: ^1.1.2 + tiktoken: '*' + peerDependenciesMeta: + '@aws-crypto/sha256-js': + optional: true + '@huggingface/transformers': + optional: true + js-tiktoken: + optional: true + pathe: + optional: true + tiktoken: + optional: true + + '@llamaindex/groq@0.0.44': + resolution: {integrity: sha512-Vs7wnxHSv0kAttdEo+fbvJgzp9XGTAL0DPk5OXk6lOLt5eJ87yjfIAuF+ExUFUWpYNXb015OG//3w8oaiNd01Q==} + + '@llamaindex/huggingface@0.0.29': + resolution: {integrity: sha512-wI/madnVw7aq2t0OMEWN8W+hfupzvm9SMgLi/qFTc8BzqyeMaE78XxcQ9yIXHD6+m4cXJPBR4lJDwrNwW+Od4A==} + peerDependencies: + '@huggingface/transformers': ^3.0.2 + + '@llamaindex/node-parser@0.0.21': + resolution: {integrity: sha512-xatUGHFIoji2RVImK9DJAtP+bSVmGtHqQnqcDlUTxj1rnOK7btqDvxoK6Y7aqIe7hotbC3DplPjmKjLvYmQJiw==} + peerDependencies: + '@llamaindex/core': 0.4.20 + '@llamaindex/env': 0.1.25 + tree-sitter: ^0.22.0 + web-tree-sitter: ^0.24.3 + + '@llamaindex/ollama@0.0.36': + resolution: {integrity: sha512-xcSxF5/C0sQD50j2k8UYNOHXoEkJPu/kN8Lrdij8s/qfIGitERk8Ao3bya0Njm3grch2CXtZnrKbmgkBBoUs2g==} + + '@llamaindex/openai@0.1.45': + resolution: {integrity: sha512-o8n+8hu6cDTfAfO7tmdx7pyMaQ9HZqpIeVK9I2JNEiVj41Vru6C71rV6ZXLTHf3aWXdm1SvC3EOxPygJcbxp+A==} + + '@llamaindex/portkey-ai@0.0.29': + resolution: {integrity: sha512-QTaxOvYemyZbrNQcdLBE4oCGXhwO+RafUxHxO+6Ki+tNhazvC28M54+kl0tHC4B451VcxWJWUJO+hUTe7gnL4Q==} + + '@llamaindex/readers@1.0.22': + resolution: {integrity: sha512-LT2gRU6dvMO8sSPHeqAGE82HNAn040id7/orRl6FZN+QRRr7lEXrZg+C0rONIPdx6/3sPt+s0U4vi9hdAwetOA==} + peerDependencies: + '@llamaindex/core': 0.4.20 + '@llamaindex/env': 0.1.25 + + '@llamaindex/replicate@0.0.29': + resolution: {integrity: sha512-w8USPeXZuV+YCovfXdyMTjnFy5RmNiJWx5GCp/twoBdvCSJZCCHXXjzlbqVMMG9FTsCL0KjbBDPIKrncq6p4ag==} + + '@llamaindex/vllm@0.0.15': + resolution: {integrity: sha512-YIplTh2Ah66ubQ+dYCbVdUcAb1mBh9YX5reSe+cxixSxTQ2j93nNOfg5h9+4e6vhWWQqvtcH7f1sN395hcUjEw==} + + '@mapbox/node-pre-gyp@1.0.11': + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + + '@mistralai/mistralai@1.3.6': + resolution: {integrity: sha512-2y7U5riZq+cIjKpxGO9y417XuZv9CpBXEAvbjRMzWPGhXY7U1ZXj4VO4H9riS2kFZqTR2yLEKSE6/pGWVVIqgQ==} + peerDependencies: + zod: '>= 3' + + '@mixedbread-ai/sdk@2.2.11': + resolution: {integrity: sha512-NJiY6BVPR+s/DTzUPQS1Pv418trOmII/8hftmIqxXlYaKbIrgJimQfwCW9M6Y21YPcMA8zTQGYZHm4IWlMjIQw==} + + '@mongodb-js/saslprep@1.1.9': + resolution: {integrity: sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -711,10 +1197,65 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@notionhq/client@2.2.15': + resolution: {integrity: sha512-XhdSY/4B1D34tSco/GION+23GMjaS9S2zszcqYkMHo8RcWInymF6L1x+Gk7EmHdrSxNFva2WM8orhC4BwQCwgw==} + engines: {node: '>=12'} + '@opentelemetry/api@1.9.0': resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} + '@petamoriken/float16@3.9.1': + resolution: {integrity: sha512-j+ejhYwY6PeB+v1kn7lZFACUIG97u90WxMuGosILFsl9d4Ovi0sjk0GlPfoEcx+FzvXZDAfioD+NGnnPamXgMA==} + + '@pinecone-database/pinecone@4.1.0': + resolution: {integrity: sha512-WoVsbvmCgvZfjm/nCasJXuQ/tw0es5BpedLHvRScAm6xJ/nL07s3B0TrsM8m8rACTiUgbdYsdLY1W6cEBhS9xA==} + engines: {node: '>=18.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@qdrant/js-client-rest@1.13.0': + resolution: {integrity: sha512-bewMtnXlGvhhnfXsp0sLoLXOGvnrCM15z9lNlG0Snp021OedNAnRtKkerjk5vkOcbQWUmJHXYCuxDfcT93aSkA==} + engines: {node: '>=18.0.0', pnpm: '>=8'} + peerDependencies: + typescript: '>=4.7' + + '@qdrant/openapi-typescript-fetch@1.2.6': + resolution: {integrity: sha512-oQG/FejNpItrxRHoyctYvT3rwGZOnK4jr3JdppO/c78ktDvkWiPXPHNsrDf33K9sZdRb6PR7gi4noIapu5q4HA==} + engines: {node: '>=18.0.0', pnpm: '>=8'} + '@rollup/plugin-commonjs@25.0.8': resolution: {integrity: sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==} engines: {node: '>=14.0.0'} @@ -868,6 +1409,20 @@ packages: cpu: [x64] os: [win32] + '@sapphire/async-queue@1.5.5': + resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@sapphire/snowflake@3.5.5': + resolution: {integrity: sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@selderee/plugin-htmlparser2@0.11.0': + resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} + + '@sevinf/maybe@0.5.0': + resolution: {integrity: sha512-ARhyoYDnY1LES3vYI0fiG6e9esWfTNcXcO6+MPJJXcnyMV3bim4lnFt45VXouV7y82F4x3YH8nOQ6VztuvUiWg==} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -877,65 +1432,276 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - '@swc/core-darwin-arm64@1.7.10': - resolution: {integrity: sha512-TYp4x/9w/C/yMU1olK5hTKq/Hi7BjG71UJ4V1U1WxI1JA3uokjQ/GoktDfmH5V5pX4dgGSOJwUe2RjoN8Z/XnA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] + '@smithy/abort-controller@4.0.1': + resolution: {integrity: sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==} + engines: {node: '>=18.0.0'} - '@swc/core-darwin-x64@1.7.10': - resolution: {integrity: sha512-P3LJjAWh5yLc6p5IUwV5LgRfA3R1oDCZDMabYyb2BVQuJTD4MfegW9DhBcUUF5dhBLwq3191KpLVzE+dLTbiXw==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] + '@smithy/config-resolver@4.0.1': + resolution: {integrity: sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==} + engines: {node: '>=18.0.0'} - '@swc/core-linux-arm-gnueabihf@1.7.10': - resolution: {integrity: sha512-yGOFjE7w/akRTmqGY3FvWYrqbxO7OB2N2FHj2LO5HtzXflfoABb5RyRvdEquX+17J6mEpu4EwjYNraTD/WHIEQ==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] + '@smithy/core@3.1.1': + resolution: {integrity: sha512-hhUZlBWYuh9t6ycAcN90XOyG76C1AzwxZZgaCVPMYpWqqk9uMFo7HGG5Zu2cEhCJn7DdOi5krBmlibWWWPgdsw==} + engines: {node: '>=18.0.0'} - '@swc/core-linux-arm64-gnu@1.7.10': - resolution: {integrity: sha512-SPWsgWHfdWKKjLrYlvhxcdBJ7Ruy6crJbPoE9NfD95eJEjMnS2yZTqj2ChFsY737WeyhWYlHzgYhYOVCp83YwQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] + '@smithy/credential-provider-imds@4.0.1': + resolution: {integrity: sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==} + engines: {node: '>=18.0.0'} - '@swc/core-linux-arm64-musl@1.7.10': - resolution: {integrity: sha512-PUi50bkNqnBL3Z/Zq6jSfwgN9A/taA6u2Zou0tjDJi7oVdpjdr7SxNgCGzMJ/nNg5D/IQn1opM1jktMvpsPAuQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] + '@smithy/eventstream-codec@1.1.0': + resolution: {integrity: sha512-3tEbUb8t8an226jKB6V/Q2XU/J53lCwCzULuBPEaF4JjSh+FlCMp7TmogE/Aij5J9DwlsZ4VAD/IRDuQ/0ZtMw==} - '@swc/core-linux-x64-gnu@1.7.10': - resolution: {integrity: sha512-Sc+pY55gknCAmBQBR6DhlA7jZSxHaLSDb5Sevzi6DOFMXR79NpA6zWTNKwp1GK2AnRIkbAfvYLgOxS5uWTFVpg==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] + '@smithy/fetch-http-handler@5.0.1': + resolution: {integrity: sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==} + engines: {node: '>=18.0.0'} - '@swc/core-linux-x64-musl@1.7.10': - resolution: {integrity: sha512-g5NKx2LXaGd0K26hmEts1Cvb7ptIvq3MHSgr6/D1tRPcDZw1Sp0dYsmyOv0ho4F5GOJyiCooG3oE9FXdb7jIpQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] + '@smithy/hash-node@4.0.1': + resolution: {integrity: sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==} + engines: {node: '>=18.0.0'} - '@swc/core-win32-arm64-msvc@1.7.10': - resolution: {integrity: sha512-plRIsOcfy9t9Q/ivm5DA7I0HaIvfAWPbI+bvVRrr3C/1K2CSqnqZJjEWOAmx2LiyipijNnEaFYuLBp0IkGuJpg==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] + '@smithy/invalid-dependency@4.0.1': + resolution: {integrity: sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==} + engines: {node: '>=18.0.0'} - '@swc/core-win32-ia32-msvc@1.7.10': - resolution: {integrity: sha512-GntrVNT23viHtbfzmlK8lfBiKeajH24GzbDT7qXhnoO20suUPcyYZxyvCb4gWM2zu8ZBTPHNlqfrNsriQCZ+lQ==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] + '@smithy/is-array-buffer@1.1.0': + resolution: {integrity: sha512-twpQ/n+3OWZJ7Z+xu43MJErmhB/WO/mMTnqR6PwWQShvSJ/emx5d1N59LQZk6ZpTAeuRWrc+eHhkzTp9NFjNRQ==} + engines: {node: '>=14.0.0'} - '@swc/core-win32-x64-msvc@1.7.10': - resolution: {integrity: sha512-uXIF8GuSappe1imm6Lf7pHGepfCBjDQlS+qTqvEGE0wZAsL1IVATK9P/cH/OCLfJXeQDTLeSYmrpwjtXNt46tQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.0.0': + resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.0.1': + resolution: {integrity: sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.0.2': + resolution: {integrity: sha512-Z9m67CXizGpj8CF/AW/7uHqYNh1VXXOn9Ap54fenWsCa0HnT4cJuE61zqG3cBkTZJDCy0wHJphilI41co/PE5g==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.0.3': + resolution: {integrity: sha512-TiKwwQTwUDeDtwWW8UWURTqu7s6F3wN2pmziLU215u7bqpVT9Mk2oEvURjpRLA+5XeQhM68R5BpAGzVtomsqgA==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.0.1': + resolution: {integrity: sha512-Fh0E2SOF+S+P1+CsgKyiBInAt3o2b6Qk7YOp2W0Qx2XnfTdfMuSDKUEcnrtpxCzgKJnqXeLUZYqtThaP0VGqtA==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.0.1': + resolution: {integrity: sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.0.1': + resolution: {integrity: sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.0.2': + resolution: {integrity: sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.0.1': + resolution: {integrity: sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@1.2.0': + resolution: {integrity: sha512-GfGfruksi3nXdFok5RhgtOnWe5f6BndzYfmEXISD+5gAGdayFGpjWu5pIqIweTudMtse20bGbc+7MFZXT1Tb8Q==} + engines: {node: '>=14.0.0'} + + '@smithy/protocol-http@5.0.1': + resolution: {integrity: sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.0.1': + resolution: {integrity: sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.0.1': + resolution: {integrity: sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.0.1': + resolution: {integrity: sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.0.1': + resolution: {integrity: sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@1.1.0': + resolution: {integrity: sha512-fDo3m7YqXBs7neciOePPd/X9LPm5QLlDMdIC4m1H6dgNLnXfLMFNIxEfPyohGA8VW9Wn4X8lygnPSGxDZSmp0Q==} + engines: {node: '>=14.0.0'} + + '@smithy/signature-v4@5.0.1': + resolution: {integrity: sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.1.2': + resolution: {integrity: sha512-0yApeHWBqocelHGK22UivZyShNxFbDNrgREBllGh5Ws0D0rg/yId/CJfeoKKpjbfY2ju8j6WgDUGZHYQmINZ5w==} + engines: {node: '>=18.0.0'} + + '@smithy/types@1.2.0': + resolution: {integrity: sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==} + engines: {node: '>=14.0.0'} + + '@smithy/types@4.1.0': + resolution: {integrity: sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.0.1': + resolution: {integrity: sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.0.0': + resolution: {integrity: sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.0.0': + resolution: {integrity: sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.0.0': + resolution: {integrity: sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@1.1.0': + resolution: {integrity: sha512-9m6NXE0ww+ra5HKHCHig20T+FAwxBAm7DIdwc/767uGWbRcY720ybgPacQNB96JMOI7xVr/CDa3oMzKmW4a+kw==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.0.0': + resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.0.0': + resolution: {integrity: sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.0.3': + resolution: {integrity: sha512-7c5SF1fVK0EOs+2EOf72/qF199zwJflU1d02AevwKbAUPUZyE9RUZiyJxeUmhVxfKDWdUKaaVojNiaDQgnHL9g==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.0.3': + resolution: {integrity: sha512-CVnD42qYD3JKgDlImZ9+On+MqJHzq9uJgPbMdeBE8c2x8VJ2kf2R3XO/yVFx+30ts5lD/GlL0eFIShY3x9ROgQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.0.1': + resolution: {integrity: sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@1.1.0': + resolution: {integrity: sha512-7UtIE9eH0u41zpB60Jzr0oNCQ3hMJUabMcKRUVjmyHTXiWDE4vjSqN6qlih7rCNeKGbioS7f/y2Jgym4QZcKFg==} + engines: {node: '>=14.0.0'} + + '@smithy/util-hex-encoding@4.0.0': + resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@1.1.0': + resolution: {integrity: sha512-6hhckcBqVgjWAqLy2vqlPZ3rfxLDhFWEmM7oLh2POGvsi7j0tHkbN7w4DFhuBExVJAbJ/qqxqZdRY6Fu7/OezQ==} + engines: {node: '>=14.0.0'} + + '@smithy/util-middleware@4.0.1': + resolution: {integrity: sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.0.1': + resolution: {integrity: sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.0.2': + resolution: {integrity: sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@1.1.0': + resolution: {integrity: sha512-/jL/V1xdVRt5XppwiaEU8Etp5WHZj609n0xMTuehmCqdoOFbId1M+aEeDWZsQ+8JbEB/BJ6ynY2SlYmOaKtt8w==} + engines: {node: '>=14.0.0'} + + '@smithy/util-uri-escape@4.0.0': + resolution: {integrity: sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@1.1.0': + resolution: {integrity: sha512-p/MYV+JmqmPyjdgyN2UxAeYDj9cBqCjp0C/NsTWnnjoZUVqoeZ6IrW915L9CAKWVECgv9lVQGc4u/yz26/bI1A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.0.0': + resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==} + engines: {node: '>=18.0.0'} + + '@smithy/util-waiter@4.0.2': + resolution: {integrity: sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==} + engines: {node: '>=18.0.0'} + + '@swc/core-darwin-arm64@1.7.10': + resolution: {integrity: sha512-TYp4x/9w/C/yMU1olK5hTKq/Hi7BjG71UJ4V1U1WxI1JA3uokjQ/GoktDfmH5V5pX4dgGSOJwUe2RjoN8Z/XnA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.7.10': + resolution: {integrity: sha512-P3LJjAWh5yLc6p5IUwV5LgRfA3R1oDCZDMabYyb2BVQuJTD4MfegW9DhBcUUF5dhBLwq3191KpLVzE+dLTbiXw==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.7.10': + resolution: {integrity: sha512-yGOFjE7w/akRTmqGY3FvWYrqbxO7OB2N2FHj2LO5HtzXflfoABb5RyRvdEquX+17J6mEpu4EwjYNraTD/WHIEQ==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.7.10': + resolution: {integrity: sha512-SPWsgWHfdWKKjLrYlvhxcdBJ7Ruy6crJbPoE9NfD95eJEjMnS2yZTqj2ChFsY737WeyhWYlHzgYhYOVCp83YwQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.7.10': + resolution: {integrity: sha512-PUi50bkNqnBL3Z/Zq6jSfwgN9A/taA6u2Zou0tjDJi7oVdpjdr7SxNgCGzMJ/nNg5D/IQn1opM1jktMvpsPAuQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-x64-gnu@1.7.10': + resolution: {integrity: sha512-Sc+pY55gknCAmBQBR6DhlA7jZSxHaLSDb5Sevzi6DOFMXR79NpA6zWTNKwp1GK2AnRIkbAfvYLgOxS5uWTFVpg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.7.10': + resolution: {integrity: sha512-g5NKx2LXaGd0K26hmEts1Cvb7ptIvq3MHSgr6/D1tRPcDZw1Sp0dYsmyOv0ho4F5GOJyiCooG3oE9FXdb7jIpQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.7.10': + resolution: {integrity: sha512-plRIsOcfy9t9Q/ivm5DA7I0HaIvfAWPbI+bvVRrr3C/1K2CSqnqZJjEWOAmx2LiyipijNnEaFYuLBp0IkGuJpg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.7.10': + resolution: {integrity: sha512-GntrVNT23viHtbfzmlK8lfBiKeajH24GzbDT7qXhnoO20suUPcyYZxyvCb4gWM2zu8ZBTPHNlqfrNsriQCZ+lQ==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.7.10': + resolution: {integrity: sha512-uXIF8GuSappe1imm6Lf7pHGepfCBjDQlS+qTqvEGE0wZAsL1IVATK9P/cH/OCLfJXeQDTLeSYmrpwjtXNt46tQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] '@swc/core@1.7.10': resolution: {integrity: sha512-l0xrFwBQ9atizhmV94yC2nwcecTk/oftofwMNPiFMGe56dqdmi2ArHaTV3PCtMlgaUH6rGCehoRMt5OrCI1ktg==} @@ -1025,6 +1791,12 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/lodash@4.17.14': + resolution: {integrity: sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==} + + '@types/long@4.0.2': + resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} + '@types/mute-stream@0.0.4': resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} @@ -1037,9 +1809,15 @@ packages: '@types/node@20.14.2': resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==} + '@types/node@22.10.7': + resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==} + '@types/node@22.5.4': resolution: {integrity: sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==} + '@types/pg@8.11.10': + resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -1052,6 +1830,9 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/triple-beam@1.3.5': resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} @@ -1061,6 +1842,12 @@ packages: '@types/uuid@9.0.8': resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + '@types/webidl-conversions@7.0.3': + resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + + '@types/whatwg-url@11.0.5': + resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + '@types/winston@2.4.4': resolution: {integrity: sha512-BVGCztsypW8EYwJ+Hq+QNYiT/MUyCif0ouBH+flrY66O5W+KIXAMML6E/0fJpm7VjIzgangahl5S03bJJQGrZw==} deprecated: This is a stub types definition. winston provides its own type definitions, so you do not need this installed. @@ -1136,6 +1923,13 @@ packages: resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@upstash/vector@1.2.0': + resolution: {integrity: sha512-70uyxuYdddpssgCEH3jEh5i29Lt9DhcJx4fvddv1B5x9ROHJacqW+JGMjbuzFfYBavJeu/uSxFdEa8l48ZKMkQ==} + + '@vladfrangu/async_event_emitter@2.4.6': + resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + '@vue/compiler-core@3.4.36': resolution: {integrity: sha512-qBkndgpwFKdupmOPoiS10i7oFdN7a+4UNDlezD0GlQ1kuA1pNrscg9g12HnB5E8hrWSuEftRsbJhL1HI2zpJhg==} @@ -1210,12 +2004,25 @@ packages: '@webassemblyjs/wast-printer@1.12.1': resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} + '@xmldom/xmldom@0.8.10': + resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} + engines: {node: '>=10.0.0'} + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + '@zilliz/milvus2-sdk-node@2.5.4': + resolution: {integrity: sha512-wDXIMA586UW/9V08Siz6s/IHrNfkKlZKPYGk+ynixZ5iXdjH8DKEWTISJ3pEM09HrZe9svZvlrDCbHKsr5ZqwQ==} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + abort-controller-x@0.4.3: + resolution: {integrity: sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==} + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -1244,6 +2051,14 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + agentkeepalive@4.5.0: resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} engines: {node: '>= 8.0.0'} @@ -1277,6 +2092,12 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + already@2.2.1: + resolution: {integrity: sha512-qk6RIVMS/R1yTvBzfIL1T76PsIL7DIVCINoLuFw2YXKLpLtsTobqdChMs8m3OhuPS3CEE3+Ra5ibYiqdyogbsQ==} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -1285,6 +2106,10 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + ansi-sequence-parser@1.1.1: resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} @@ -1300,10 +2125,25 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -1316,6 +2156,10 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + assemblyai@4.8.0: + resolution: {integrity: sha512-TRIcthDBdJ+lj1ohLa516Kr/BO2AQn+IhBBl/eeomZGZym90aEC6qirc337hEPUxmmINSJ8XTSY4xwy51HmDGA==} + engines: {node: '>=18'} + async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} @@ -1334,6 +2178,9 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} + b4a@1.6.7: + resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} + babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1362,13 +2209,50 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bare-events@2.5.4: + resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} + + bare-fs@4.0.1: + resolution: {integrity: sha512-ilQs4fm/l9eMfWY2dY0WCIUplSUp7U0CT1vrqMg1MUdeZl4fypu5UP0XcDBK5WBQPJAKP1b7XEodISmekH/CEg==} + engines: {bare: '>=1.7.0'} + + bare-os@3.4.0: + resolution: {integrity: sha512-9Ous7UlnKbe3fMi7Y+qh0DwAup6A1JkYgPnjvMDNOlmnxNRQvQ/7Nst+OnUQKzk0iAT0m9BisbDVp9gCv8+ETA==} + engines: {bare: '>=1.6.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.6.4: + resolution: {integrity: sha512-G6i3A74FjNq4nVrrSTUz5h3vgXzBJnjmWAVlBWaZETkgu+LgKd7AiyOml3EDJY1AHlIbBHKDXE+TUT53Ff8OaA==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + + bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1391,9 +2275,22 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + bson@6.10.1: + resolution: {integrity: sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA==} + engines: {node: '>=16.20.1'} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bufferutil@4.0.8: resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} engines: {node: '>=6.14.2'} @@ -1406,10 +2303,25 @@ packages: magicast: optional: true + call-bind-apply-helpers@1.0.1: + resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} + engines: {node: '>= 0.4'} + + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} + engines: {node: '>= 0.4'} + + callguard@2.0.0: + resolution: {integrity: sha512-I3nd+fuj20FK1qu00ImrbH+II+8ULS6ioYr9igqR1xyqySoqc3DiHEyUM0mkoAdKeLGg2CtGnO8R3VRQX5krpQ==} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camelcase@4.1.0: + resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} + engines: {node: '>=4'} + camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -1421,6 +2333,10 @@ packages: caniuse-lite@1.0.30001633: resolution: {integrity: sha512-6sT0yf/z5jqf8tISAgpJDrmwOpLsrpnyCdD/lOZKvKkkJK4Dn0X5i7KF7THEZhOq+30bmhwBlNEaqPUiHiKtZg==} + canvas@2.11.2: + resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} + engines: {node: '>=6'} + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1444,10 +2360,35 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + chromadb-default-embed@2.13.2: + resolution: {integrity: sha512-mhqo5rLjkF2KkxAV0WS82vNIXWpVMzvz5y5ayIB2FxcebUbEBNlcRh6XSSqYChWMfJ9us1ZzLQU8RXqsy3sKaA==} + + chromadb@1.9.2: + resolution: {integrity: sha512-JNeLKlrsPxld7oPJCNeF73yHyyYeyP950enWRkTa6WsJ6UohH2NQ1vXZu6lWO9WuA9EMypITyZFZ8KtcTV3y2Q==} + engines: {node: '>=14.17.0'} + peerDependencies: + '@google/generative-ai': ^0.1.1 + cohere-ai: ^5.0.0 || ^6.0.0 || ^7.0.0 + openai: ^3.0.0 || ^4.0.0 + peerDependenciesMeta: + '@google/generative-ai': + optional: true + cohere-ai: + optional: true + openai: + optional: true + chrome-trace-event@1.0.4: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} @@ -1488,6 +2429,9 @@ packages: code-red@1.0.4: resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + cohere-ai@7.14.0: + resolution: {integrity: sha512-hSo2/tFV29whjFFtVtdS7kHmtUsjfMO1sgwE/d5bhOE4O7Vkj5G1R9lLIqkIprp/+rrvCq3HGvEaOgry7xRcDA==} + collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} @@ -1507,9 +2451,17 @@ packages: color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + color@3.2.1: resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + colors@1.4.0: resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} engines: {node: '>=0.1.90'} @@ -1545,9 +2497,15 @@ packages: resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} engines: {node: ^14.18.0 || >=16.10.0} + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + create-jest@29.7.0: resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1556,6 +2514,9 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1571,6 +2532,12 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csv-parse@5.6.0: + resolution: {integrity: sha512-l3nz3euub2QMg5ouu5U09Ew9Wf6/wQ8I++ch1loQ0ljmzhmfZYrH9fflS22i/PQEvsPvxCwxgz5q7UB8K1JO4Q==} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + debug@4.3.5: resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} @@ -1584,6 +2551,14 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + decompress-response@4.2.1: + resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} + engines: {node: '>=8'} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dedent@1.5.3: resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} peerDependencies: @@ -1592,6 +2567,10 @@ packages: babel-plugin-macros: optional: true + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1610,6 +2589,9 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -1617,6 +2599,10 @@ packages: destr@2.0.3: resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -1632,10 +2618,42 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} + dingbat-to-unicode@1.0.1: + resolution: {integrity: sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==} + + discord-api-types@0.37.116: + resolution: {integrity: sha512-g+BH/m0hyS/JzL+e0aM+z2o9UtwfyUZ0hqeyc+6sNwdMx+NtQkqULRV/oj9ynAefpRb+cpOjmWaYec4B1I0Hqg==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} + duck@0.1.12: + resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -1651,13 +2669,23 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enabled@2.0.0: resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.17.0: resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==} engines: {node: '>=10.13.0'} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + entities@5.0.0: resolution: {integrity: sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==} engines: {node: '>=0.12'} @@ -1668,9 +2696,21 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es-module-lexer@1.5.3: resolution: {integrity: sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -1775,10 +2815,17 @@ packages: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + expect@29.7.0: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} @@ -1786,6 +2833,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -1796,6 +2846,13 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.0.5: + resolution: {integrity: sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==} + + fast-xml-parser@4.4.1: + resolution: {integrity: sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==} + hasBin: true + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -1805,6 +2862,10 @@ packages: fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + fetch-h2@3.0.2: + resolution: {integrity: sha512-Lo6UPdMKKc9Ond7yjG2vq0mnocspOLh1oV6+XZdtfdexacvMSz5xm3WoQhTAdoR2+UqPlyMNqcqfecipoD+l/A==} + engines: {node: '>=12'} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -1828,6 +2889,9 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} + flatbuffers@1.12.0: + resolution: {integrity: sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ==} + flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} @@ -1843,9 +2907,17 @@ packages: debug: optional: true + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + form-data-encoder@1.7.2: resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + form-data-encoder@4.0.2: + resolution: {integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==} + engines: {node: '>= 18'} + form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -1854,14 +2926,28 @@ packages: resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} engines: {node: '>= 12.20'} + formdata-node@6.0.3: + resolution: {integrity: sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==} + engines: {node: '>= 18'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} + fs-extra@2.1.2: + resolution: {integrity: sha512-9ztMtDZtSKC78V8mev+k31qaTabbmuH5jatdvPBMikrFHvw5BqlYnQIn/WGK3WHeRooSTkRvLa2IPlaHjPq5Sg==} + fs-minipass@2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} + fs-promise@2.0.3: + resolution: {integrity: sha512-oDrTLBQAcRd+p/tSRWvqitKegLPsvqr7aehs5N9ILWFM9az5y5Uh71jKdZ/DTMC4Kel7+GNCQyFCx/IftRv8yg==} + deprecated: Use mz or fs-extra^3.0 with Promise Support + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1873,6 +2959,23 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gcp-metadata@6.1.0: + resolution: {integrity: sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==} + engines: {node: '>=14'} + + generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -1881,10 +2984,18 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-intrinsic@1.2.7: + resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} + engines: {node: '>= 0.4'} + get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -1897,6 +3008,9 @@ packages: resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} hasBin: true + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1908,6 +3022,10 @@ packages: glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -1929,12 +3047,42 @@ packages: resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} engines: {node: '>=18'} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + google-auth-library@9.15.0: + resolution: {integrity: sha512-7ccSEJFDFO7exFbO6NRyC+xH8/mZ1GZGG2xxx9iHxZWcjUjJpjWxIMw3cofAKcueZ6DATiukmmprD7yavQHOyQ==} + engines: {node: '>=14'} - graphemer@1.4.0: + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + gpt-tokenizer@2.8.1: + resolution: {integrity: sha512-8+a9ojzqfgiF3TK4oivGYjlycD8g5igLt8NQw3ndOIgLVKSGJDhUDNAfYSbtyyuTkha3R/R9F8XrwC7/B5TKfQ==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + graphql-request@6.1.0: + resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} + peerDependencies: + graphql: 14 - 16 + + graphql@16.10.0: + resolution: {integrity: sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + + groq-sdk@0.8.0: + resolution: {integrity: sha512-hSgCjZCkoM4CY/TWfsaNlh512svWRR2td4HGpmEV8MbVEVrxZARJq5BHt8gbEF9Gex092/X7VJvaQpha0dIC8g==} + + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + + guid-typescript@1.0.9: + resolution: {integrity: sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==} + handlebars@4.7.8: resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} engines: {node: '>=0.4.7'} @@ -1948,6 +3096,13 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1955,6 +3110,25 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-to-text@9.0.5: + resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==} + engines: {node: '>=14'} + + htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -1970,10 +3144,16 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -1991,9 +3171,15 @@ packages: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + infobox-parser@3.6.4: + resolution: {integrity: sha512-d2lTlxKZX7WsYxk9/UPt51nkmZv5tbC75SSw4hfHqZ3LpRAn6ug0oru9xI2X+S78va3aUAze3xl/UqMuwLmJUw==} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + inquirer@10.2.2: resolution: {integrity: sha512-tyao/4Vo36XnUItZ7DnUXX4f1jVao2mSrleV/5IPtW/XAEA26hRVsbc68nuTEKWcr5vMP/1mVoT2O7u8H4v1Vg==} engines: {node: '>=18'} @@ -2061,9 +3247,15 @@ packages: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isomorphic-fetch@3.0.0: + resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -2088,6 +3280,9 @@ packages: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jake@10.9.2: resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} engines: {node: '>=10'} @@ -2237,9 +3432,15 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + js-base64@3.7.2: + resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==} + js-tiktoken@1.0.12: resolution: {integrity: sha512-L7wURW1fH9Qaext0VzaUDpFGVQgjkdE3Dgsy9/+yXyGEpBKnylTd0mU0bfbNkKDlXRb6TEsZkwuflu1B8uQbJQ==} + js-tiktoken@1.0.16: + resolution: {integrity: sha512-nUVdO5k/M9llWpiaZlBBDdtmr6qWXwSD6fgaDu2zM8UP+OXxx9V37lFkI6w0/1IuaDx7WffZ37oYd9KvcWKElg==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2251,11 +3452,17 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsbi@4.3.0: + resolution: {integrity: sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==} + jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -2265,6 +3472,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} @@ -2284,6 +3494,9 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true + jsonfile@2.4.0: + resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} + jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -2291,6 +3504,25 @@ packages: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} + jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + + jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + + jwa@2.0.0: + resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==} + + jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + + jws@4.0.0: + resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -2498,6 +3730,9 @@ packages: openai: optional: true + leac@0.6.0: + resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -2506,9 +3741,24 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + llamaindex@0.8.31: + resolution: {integrity: sha512-hL5yZqDhfetLJOHJwwWa63HF7CBuZhQVjOh+arCRi+Cnlm9BpI1ma7OefxxjuvrzREOyNmJ9tnFII8wUv5mUvA==} + engines: {node: '>=18.0.0'} + peerDependencies: + pg: ^8.12.0 + pgvector: 0.2.0 + peerDependenciesMeta: + pg: + optional: true + pgvector: + optional: true + loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} engines: {node: '>=6.11.5'} @@ -2524,29 +3774,79 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + logform@2.6.1: resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==} engines: {node: '>= 12.0.0'} + long@4.0.0: + resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} + + long@5.2.4: + resolution: {integrity: sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + lop@0.4.2: + resolution: {integrity: sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@9.1.2: + resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==} + engines: {node: 14 || >=16.14} + lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + magic-bytes.js@1.10.0: + resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==} + magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} @@ -2557,14 +3857,29 @@ packages: makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + mammoth@1.9.0: + resolution: {integrity: sha512-F+0NxzankQV9XSUAuVKvkdQK0GbtGGuqVnND9aVf9VSeUA82LQa29GjLqYU6Eez8LHqSJG3eGiDW3224OKdpZg==} + engines: {node: '>=12.0.0'} + hasBin: true + marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} engines: {node: '>= 12'} hasBin: true + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md-utils-ts@2.0.0: + resolution: {integrity: sha512-sMG6JtX0ebcRMHxYTcmgsh0/m6o8hGdQHFE2OgjvflRZlQM51CGGj/uuk056D+12BlCiW0aTpt/AdlDNtgQiew==} + mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -2592,6 +3907,14 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} + mimic-response@2.1.0: + resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} + engines: {node: '>=8'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2614,18 +3937,64 @@ packages: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} + minizlib@3.0.1: + resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==} + engines: {node: '>= 18'} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mlly@1.7.1: resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + mongodb-connection-string-url@3.0.2: + resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==} + + mongodb@6.12.0: + resolution: {integrity: sha512-RM7AHlvYfS7jv7+BXund/kR64DryVI+cHbVAy9P61fnb1RcWZqOW1/Wj2YhqMCx+MuYhqTRGv7AwHBzmsCKBfA==} + engines: {node: '>=16.20.1'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.188.0 + '@mongodb-js/zstd': ^1.1.0 || ^2.0.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: '>=6.0.0 <7' + snappy: ^7.2.2 + socks: ^2.7.1 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -2640,6 +4009,12 @@ packages: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nan@2.22.0: + resolution: {integrity: sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==} + nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2650,12 +4025,35 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + nice-grpc-client-middleware-retry@3.1.9: + resolution: {integrity: sha512-BgbsNjuppxD6hoeCfO5gkBA/G69Tq5d9QX35QLdA46NSjKllelC+FlcgSPMlO9VQKCAPDfp4zzzDJZTNtbvzVw==} + + nice-grpc-common@2.0.2: + resolution: {integrity: sha512-7RNWbls5kAL1QVUOXvBsv1uO0wPQK3lHv+cY1gwkTzirnG1Nop4cBJZubpgziNbaVc/bl9QJcyvsf/NQxa3rjQ==} + + nice-grpc@2.1.10: + resolution: {integrity: sha512-Nujs/4wWJvE5OSxWPp3M5H+zHJAgsWMo38bMNfKQP1VDeCChp7MiKTkhJBV5JZvrBIkPhYQCLIbfvVqEoSuTuA==} + + node-abi@3.73.0: + resolution: {integrity: sha512-z8iYzQGBu35ZkTQ9mtR8RqugJZ9RCLn8fv3d7LsgDBzOijGQP3RdKTX4LA7LXw03ZhU5z0l4xfhIMgSES31+cg==} + engines: {node: '>=10'} + + node-addon-api@6.1.0: + resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + + node-addon-api@8.3.0: + resolution: {integrity: sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==} + engines: {node: ^18 || ^20 || >= 21} + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -2676,16 +4074,28 @@ packages: resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + notion-md-crawler@1.0.0: + resolution: {integrity: sha512-mdB6zn/i32qO2C7X7wZLDpWvFryO3bPYMuBfFgmTPomnfEtIejdQJNVaZzw2GapM82lfWZ5dfsZp3s3UL4p1Fg==} + npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -2694,14 +4104,32 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + deprecated: This package is no longer supported. + nypm@0.3.8: resolution: {integrity: sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==} engines: {node: ^14.16.0 || >=16.10.0} hasBin: true + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} + engines: {node: '>= 0.4'} + + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + ohash@1.1.3: resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + ollama@0.5.12: + resolution: {integrity: sha512-flVH1fn1c9NF7VV3bW9kSu0E+bYc40b4DxL/gS2Debhao35osJFRDiPOj9sIWTMvcyj78Paw1OuhfIe7uhDWfQ==} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -2716,6 +4144,32 @@ packages: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} + onnx-proto@4.0.4: + resolution: {integrity: sha512-aldMOB3HRoo6q/phyB6QRQxSt895HNNw82BNyZ2CMh4bjeKv7g/c+VpAFtJuEMVfYLMbRx61hbuqnKceLeDcDA==} + + onnxruntime-common@1.14.0: + resolution: {integrity: sha512-3LJpegM2iMNRX2wUmtYfeX/ytfOzNwAWKSq1HbRrKc9+uqG/FsEA0bbKZl1btQeZaXhC26l44NWpNUeXPII7Ew==} + + onnxruntime-common@1.20.1: + resolution: {integrity: sha512-YiU0s0IzYYC+gWvqD1HzLc46Du1sXpSiwzKb63PACIJr6LfL27VsXSXQvt68EzD3V0D5Bc0vyJTjmMxp0ylQiw==} + + onnxruntime-common@1.21.0-dev.20241212-1f88284f96: + resolution: {integrity: sha512-zD6mQJfgeezbNKV2fiN/ZqB+LKdixJ7sKc5vu6PdqMU+bZk581g5XqrhoYNwe/RDJdFGQSMKK9+gUg4Mep+jKw==} + + onnxruntime-node@1.14.0: + resolution: {integrity: sha512-5ba7TWomIV/9b6NH/1x/8QEeowsb+jBEvFzU6z0T4mNsFwdPqXeFUM7uxC6QeSRkEbWu3qEB0VMjrvzN/0S9+w==} + os: [win32, darwin, linux] + + onnxruntime-node@1.20.1: + resolution: {integrity: sha512-di/I4HDXRw+FLgq+TyHmQEDd3cEp9iFFZm0r4uJ1Wd7b/WE1VXtKWo8yemex347c6GNF/3Pv86ZfPhIWxORr0w==} + os: [win32, darwin, linux] + + onnxruntime-web@1.14.0: + resolution: {integrity: sha512-Kcqf43UMfW8mCydVGcX9OMXI2VN17c0p6XvR7IPSZzBf/6lteBzXHvcEVWDPmCKuGombl997HgLqj91F11DzXw==} + + onnxruntime-web@1.21.0-dev.20250114-228dd16893: + resolution: {integrity: sha512-fUnedxS63NYwNkQJlvdD55jVcOtyM+Qzw1SGt9Pj3jZVaIwR4mltx/5C0yvwdue44BTSV7M5Q0qnhL6/30ewqA==} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -2733,9 +4187,24 @@ packages: zod: optional: true + openai@4.79.1: + resolution: {integrity: sha512-M7P5/PKnT/S/B5v0D64giC9mjyxFYkqlCuQFzR5hkdzMdqUuHf8T1gHhPGPF5oAvu4+PO3TvJv/qhZoS2bqAkw==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + openapi-types@12.1.3: resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + option@0.2.4: + resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2780,6 +4249,15 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + papaparse@5.5.1: + resolution: {integrity: sha512-EuEKUhyxrHVozD7g3/ztsJn6qaKse8RPfR6buNB2dMJvdtXNhcw8jccVi/LxNEY3HVrV6GO6Z4OoeCG9Iy9wpA==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -2788,6 +4266,9 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parseley@0.12.1: + resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -2815,15 +4296,37 @@ packages: resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} engines: {node: '>=0.10.0'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + peberminta@0.9.0: + resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} + perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-numeric@1.0.2: + resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} + engines: {node: '>=4'} + + pg-protocol@1.7.0: + resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==} + + pg-types@4.0.2: + resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} + engines: {node: '>=10'} + picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} @@ -2846,10 +4349,40 @@ packages: pkg-types@1.1.1: resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} + platform@1.3.6: + resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + + portkey-ai@0.1.16: + resolution: {integrity: sha512-EY4FRp6PZSD75Q1o1qc08DfPNTG9FnkUPN3Z1/lEvaq9iFpSO5UekcagUZaKSVhao311qjBjns+kF0rS9ht7iA==} + postcss@8.4.41: resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} engines: {node: ^10 || ^12 || >=14} + postgres-array@3.0.2: + resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==} + engines: {node: '>=12'} + + postgres-bytea@3.0.0: + resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==} + engines: {node: '>= 6'} + + postgres-date@2.1.0: + resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==} + engines: {node: '>=12'} + + postgres-interval@3.0.0: + resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==} + engines: {node: '>=12'} + + postgres-range@1.1.4: + resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} + + prebuild-install@7.1.2: + resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} + engines: {node: '>=10'} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2873,13 +4406,37 @@ packages: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + priorityqueuejs@2.0.0: + resolution: {integrity: sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} + protobufjs@6.11.4: + resolution: {integrity: sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==} + hasBin: true + + protobufjs@7.4.0: + resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} + engines: {node: '>=12.0.0'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2890,15 +4447,32 @@ packages: pusher-js@8.4.0-rc2: resolution: {integrity: sha512-d87GjOEEl9QgO5BWmViSqW0LOzPvybvX6WA9zLUstNdB57jVJuR27zHkRnrav2a3+zAMlHbP2Og8wug+rG8T+g==} + qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + + rake-modified@1.0.8: + resolution: {integrity: sha512-rj/1t+EyI8Ly52eaCeSy5hoNpdNnDlNQ/+jll2DypR6nkuxotMbaupzwbuMSaXzuSL1I2pYVYy7oPus/Ls49ag==} + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -2906,10 +4480,17 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2917,10 +4498,24 @@ packages: regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + remeda@2.19.2: + resolution: {integrity: sha512-192lSeU0P91TIsYOX+MZ2x8I+enSkVVF0YhUhABix0CZWl+1+3/zn4b3L2d/BiWBTa6RsIeJgvLJj5nYTiTXGA==} + + replicate@1.0.1: + resolution: {integrity: sha512-EY+rK1YR5bKHcM9pd6WyaIbv6m2aRIvHfHDh51j/LahlHTLKemTYXF6ptif2sLa+YospupAsIoxw8Ndt5nI3vg==} + engines: {git: '>=2.11.0', node: '>=18.0.0', npm: '>=7.19.0', yarn: '>=1.7.0'} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -2953,6 +4548,15 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + rollup-plugin-dts@6.1.1: resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} engines: {node: '>=16'} @@ -2997,6 +4601,9 @@ packages: rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -3014,6 +4621,13 @@ packages: secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + selderee@0.11.0: + resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} + + semaphore@1.1.0: + resolution: {integrity: sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==} + engines: {node: '>=0.8.0'} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3034,6 +4648,20 @@ packages: serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + sharp@0.32.6: + resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} + engines: {node: '>=14.15.0'} + + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -3045,6 +4673,22 @@ packages: shiki@0.14.7: resolution: {integrity: sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -3052,6 +4696,15 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@3.1.1: + resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -3080,6 +4733,9 @@ packages: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} + sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -3095,6 +4751,13 @@ packages: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} + stoppable@1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + + streamx@2.21.1: + resolution: {integrity: sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==} + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -3103,6 +4766,13 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -3110,6 +4780,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + strip-bom@4.0.0: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} @@ -3122,10 +4796,17 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -3163,10 +4844,27 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + tar-fs@2.1.2: + resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} + + tar-fs@3.0.8: + resolution: {integrity: sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} + terser-webpack-plugin@5.3.10: resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} engines: {node: '>= 10.13.0'} @@ -3192,9 +4890,22 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -3202,6 +4913,9 @@ packages: tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-arraybuffer@1.0.1: + resolution: {integrity: sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==} + to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -3210,9 +4924,20 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@5.0.0: + resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + engines: {node: '>=18'} + + tree-sitter@0.22.4: + resolution: {integrity: sha512-usbHZP9/oxNsUY65MQUsduGRqDHQOou1cagUSwjhoSYAmSahjQDAVsh9s+SlZkn8X8+O1FULRGwHu7AFP3kjzg==} + triple-beam@1.4.1: resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} engines: {node: '>= 14.0.0'} @@ -3223,6 +4948,9 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-error@1.0.6: + resolution: {integrity: sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==} + ts-jest@29.2.4: resolution: {integrity: sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==} engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} @@ -3268,9 +4996,15 @@ packages: '@swc/wasm': optional: true + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + tweetnacl@1.0.3: resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} @@ -3286,6 +5020,13 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} + type-fest@4.32.0: + resolution: {integrity: sha512-rfgpoi08xagF3JSdtJlCwMq9DGNDE0IMh3Mkpc1wUypg9vPi786AiqeBBKcqvIkq42azsBM85N490fyZjeUftw==} + engines: {node: '>=16'} + + typed-emitter@2.1.0: + resolution: {integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==} + typedoc@0.25.13: resolution: {integrity: sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==} engines: {node: '>= 16'} @@ -3316,16 +5057,37 @@ packages: engines: {node: '>=0.8.0'} hasBin: true + underscore@1.13.7: + resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==} + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@5.28.5: + resolution: {integrity: sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==} + engines: {node: '>=14.0'} + + undici@6.19.8: + resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} + engines: {node: '>=18.17'} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + unpdf@0.12.1: + resolution: {integrity: sha512-ktP8+TTLDBrlu/j8rQVNbHoMMpFXzkVAkb1rt/JdshFC3jOHdZjuGCNl/voPL0kraUrUOH7ZC88kVxMvlvDBzA==} + update-browserslist-db@1.0.16: resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true @@ -3335,6 +5097,12 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-join@4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + use-sync-external-store@1.2.2: resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} peerDependencies: @@ -3351,11 +5119,19 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true - v8-compile-cache-lib@3.0.1: + uuidv7@0.6.3: + resolution: {integrity: sha512-zV3eW2NlXTsun/aJ7AixxZjH/byQcH/r3J99MI0dDEkU2cJIBJxhEWUHDTpOaLPRNhebPZoeHuykYREkI9HafA==} + hasBin: true + + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} v8-to-istanbul@9.3.0: @@ -3383,6 +5159,10 @@ packages: resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} engines: {node: '>=10.13.0'} + weaviate-client@3.3.4: + resolution: {integrity: sha512-aHZwgJR+HHV/xmLwFJ57Ny1OuhE7EC1sheHZueJoOKfn+iov031XwuZ5oH6WIYQY0tGqvs6hTmXwgdy51ZuXkg==} + engines: {node: '>=18.0.0'} + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -3391,9 +5171,16 @@ packages: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} + web-tree-sitter@0.24.7: + resolution: {integrity: sha512-CdC/TqVFbXqR+C51v38hv6wOPatKEUGxa39scAeFSm98wIhZxAYonhRQPSMmfZ2w7JDI0zQDdzdmgtNk06/krQ==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + webpack-sources@3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} @@ -3408,6 +5195,13 @@ packages: webpack-cli: optional: true + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-url@14.1.0: + resolution: {integrity: sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==} + engines: {node: '>=18'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -3416,6 +5210,16 @@ packages: engines: {node: '>= 8'} hasBin: true + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + wikipedia@2.1.2: + resolution: {integrity: sha512-RAYaMpXC9/E873RaSEtlEa8dXK4e0p5k98GKOd210MtkE5emm6fcnwD+N6ZA4cuffjDWagvhaQKtp/mGp2BOVQ==} + engines: {node: '>=10'} + + wink-nlp@2.3.2: + resolution: {integrity: sha512-PsK/nOjI0nfC23HbpJa/eeca+wvmx2SVvH2hIhOJSDe0hbsyOwwImmRgYvv6BwsGN7/8aCHoeNzCac9xAsrvaw==} + winston-transport@4.7.1: resolution: {integrity: sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==} engines: {node: '>= 12.0.0'} @@ -3439,6 +5243,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -3458,6 +5266,10 @@ packages: utf-8-validate: optional: true + xmlbuilder@10.1.1: + resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==} + engines: {node: '>=4.0'} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3468,6 +5280,10 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + yaml@2.4.5: resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} engines: {node: '>= 14'} @@ -3503,6 +5319,11 @@ packages: peerDependencies: zod: ^3.23.3 + zod-to-json-schema@3.24.1: + resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==} + peerDependencies: + zod: ^3.24.1 + zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} @@ -3589,12 +5410,635 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + '@anthropic-ai/sdk@0.32.1': + dependencies: + '@types/node': 18.19.34 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + '@apidevtools/json-schema-ref-parser@11.7.0': dependencies: '@jsdevtools/ono': 7.1.3 '@types/json-schema': 7.0.15 js-yaml: 4.1.0 + '@aws-crypto/crc32@3.0.0': + dependencies: + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.731.0 + tslib: 1.14.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-locate-window': 3.723.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.6.3 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.731.0 + tslib: 2.6.3 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.6.3 + + '@aws-crypto/util@3.0.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.6.3 + + '@aws-sdk/client-cognito-identity@3.731.1': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/credential-provider-node': 3.731.1 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.1 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.2 + '@smithy/middleware-retry': 4.0.3 + '@smithy/middleware-serde': 4.0.1 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.2 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.3 + '@smithy/util-defaults-mode-node': 4.0.3 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sagemaker@3.731.1': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/credential-provider-node': 3.731.1 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.1 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.2 + '@smithy/middleware-retry': 4.0.3 + '@smithy/middleware-serde': 4.0.1 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.2 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.3 + '@smithy/util-defaults-mode-node': 4.0.3 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + '@smithy/util-waiter': 4.0.2 + '@types/uuid': 9.0.8 + tslib: 2.6.3 + uuid: 9.0.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso-oidc@3.731.1': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/credential-provider-node': 3.731.1 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.1 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.2 + '@smithy/middleware-retry': 4.0.3 + '@smithy/middleware-serde': 4.0.1 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.2 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.3 + '@smithy/util-defaults-mode-node': 4.0.3 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.731.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.1 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.2 + '@smithy/middleware-retry': 4.0.3 + '@smithy/middleware-serde': 4.0.1 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.2 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.3 + '@smithy/util-defaults-mode-node': 4.0.3 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/core': 3.1.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/signature-v4': 5.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/util-middleware': 4.0.1 + fast-xml-parser: 4.4.1 + tslib: 2.6.3 + + '@aws-sdk/credential-provider-cognito-identity@3.731.1': + dependencies: + '@aws-sdk/client-cognito-identity': 3.731.1 + '@aws-sdk/types': 3.731.0 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-env@3.731.0': + dependencies: + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/credential-provider-http@3.731.0': + dependencies: + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/node-http-handler': 4.0.2 + '@smithy/property-provider': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/util-stream': 4.0.2 + tslib: 2.6.3 + + '@aws-sdk/credential-provider-ini@3.731.1': + dependencies: + '@aws-sdk/core': 3.731.0 + '@aws-sdk/credential-provider-env': 3.731.0 + '@aws-sdk/credential-provider-http': 3.731.0 + '@aws-sdk/credential-provider-process': 3.731.0 + '@aws-sdk/credential-provider-sso': 3.731.1 + '@aws-sdk/credential-provider-web-identity': 3.731.1 + '@aws-sdk/nested-clients': 3.731.1 + '@aws-sdk/types': 3.731.0 + '@smithy/credential-provider-imds': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.731.1': + dependencies: + '@aws-sdk/credential-provider-env': 3.731.0 + '@aws-sdk/credential-provider-http': 3.731.0 + '@aws-sdk/credential-provider-ini': 3.731.1 + '@aws-sdk/credential-provider-process': 3.731.0 + '@aws-sdk/credential-provider-sso': 3.731.1 + '@aws-sdk/credential-provider-web-identity': 3.731.1 + '@aws-sdk/types': 3.731.0 + '@smithy/credential-provider-imds': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.731.0': + dependencies: + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/credential-provider-sso@3.731.1': + dependencies: + '@aws-sdk/client-sso': 3.731.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/token-providers': 3.731.1 + '@aws-sdk/types': 3.731.0 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.731.1': + dependencies: + '@aws-sdk/core': 3.731.0 + '@aws-sdk/nested-clients': 3.731.1 + '@aws-sdk/types': 3.731.0 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-providers@3.731.1': + dependencies: + '@aws-sdk/client-cognito-identity': 3.731.1 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/credential-provider-cognito-identity': 3.731.1 + '@aws-sdk/credential-provider-env': 3.731.0 + '@aws-sdk/credential-provider-http': 3.731.0 + '@aws-sdk/credential-provider-ini': 3.731.1 + '@aws-sdk/credential-provider-node': 3.731.1 + '@aws-sdk/credential-provider-process': 3.731.0 + '@aws-sdk/credential-provider-sso': 3.731.1 + '@aws-sdk/credential-provider-web-identity': 3.731.1 + '@aws-sdk/nested-clients': 3.731.1 + '@aws-sdk/types': 3.731.0 + '@smithy/credential-provider-imds': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/middleware-host-header@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/middleware-logger@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/middleware-recursion-detection@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/middleware-user-agent@3.731.0': + dependencies: + '@aws-sdk/core': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@smithy/core': 3.1.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/nested-clients@3.731.1': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.731.0 + '@aws-sdk/middleware-host-header': 3.731.0 + '@aws-sdk/middleware-logger': 3.731.0 + '@aws-sdk/middleware-recursion-detection': 3.731.0 + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/region-config-resolver': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@aws-sdk/util-endpoints': 3.731.0 + '@aws-sdk/util-user-agent-browser': 3.731.0 + '@aws-sdk/util-user-agent-node': 3.731.0 + '@smithy/config-resolver': 4.0.1 + '@smithy/core': 3.1.1 + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/hash-node': 4.0.1 + '@smithy/invalid-dependency': 4.0.1 + '@smithy/middleware-content-length': 4.0.1 + '@smithy/middleware-endpoint': 4.0.2 + '@smithy/middleware-retry': 4.0.3 + '@smithy/middleware-serde': 4.0.1 + '@smithy/middleware-stack': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/node-http-handler': 4.0.2 + '@smithy/protocol-http': 5.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-base64': 4.0.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-body-length-node': 4.0.0 + '@smithy/util-defaults-mode-browser': 4.0.3 + '@smithy/util-defaults-mode-node': 4.0.3 + '@smithy/util-endpoints': 3.0.1 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/protocol-http@3.374.0': + dependencies: + '@smithy/protocol-http': 1.2.0 + tslib: 2.6.3 + + '@aws-sdk/region-config-resolver@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-config-provider': 4.0.0 + '@smithy/util-middleware': 4.0.1 + tslib: 2.6.3 + + '@aws-sdk/signature-v4@3.374.0': + dependencies: + '@smithy/signature-v4': 1.1.0 + tslib: 2.6.3 + + '@aws-sdk/token-providers@3.731.1': + dependencies: + '@aws-sdk/nested-clients': 3.731.1 + '@aws-sdk/types': 3.731.0 + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.731.0': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/util-endpoints@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/types': 4.1.0 + '@smithy/util-endpoints': 3.0.1 + tslib: 2.6.3 + + '@aws-sdk/util-locate-window@3.723.0': + dependencies: + tslib: 2.6.3 + + '@aws-sdk/util-user-agent-browser@3.731.0': + dependencies: + '@aws-sdk/types': 3.731.0 + '@smithy/types': 4.1.0 + bowser: 2.11.0 + tslib: 2.6.3 + + '@aws-sdk/util-user-agent-node@3.731.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.731.0 + '@aws-sdk/types': 3.731.0 + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@aws-sdk/util-utf8-browser@3.259.0': + dependencies: + tslib: 2.6.3 + + '@azure/abort-controller@2.1.2': + dependencies: + tslib: 2.6.3 + + '@azure/core-auth@1.9.0': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-util': 1.11.0 + tslib: 2.6.3 + + '@azure/core-client@1.9.2': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.9.0 + '@azure/core-rest-pipeline': 1.18.2 + '@azure/core-tracing': 1.2.0 + '@azure/core-util': 1.11.0 + '@azure/logger': 1.1.4 + tslib: 2.6.3 + transitivePeerDependencies: + - supports-color + + '@azure/core-http-compat@2.1.2': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-client': 1.9.2 + '@azure/core-rest-pipeline': 1.18.2 + transitivePeerDependencies: + - supports-color + + '@azure/core-paging@1.6.2': + dependencies: + tslib: 2.6.3 + + '@azure/core-rest-pipeline@1.18.2': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.9.0 + '@azure/core-tracing': 1.2.0 + '@azure/core-util': 1.11.0 + '@azure/logger': 1.1.4 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + tslib: 2.6.3 + transitivePeerDependencies: + - supports-color + + '@azure/core-tracing@1.2.0': + dependencies: + tslib: 2.6.3 + + '@azure/core-util@1.11.0': + dependencies: + '@azure/abort-controller': 2.1.2 + tslib: 2.6.3 + + '@azure/cosmos@4.2.0': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.9.0 + '@azure/core-rest-pipeline': 1.18.2 + '@azure/core-tracing': 1.2.0 + '@azure/core-util': 1.11.0 + fast-json-stable-stringify: 2.1.0 + jsbi: 4.3.0 + priorityqueuejs: 2.0.0 + semaphore: 1.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - supports-color + + '@azure/identity@4.6.0': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.9.0 + '@azure/core-client': 1.9.2 + '@azure/core-rest-pipeline': 1.18.2 + '@azure/core-tracing': 1.2.0 + '@azure/core-util': 1.11.0 + '@azure/logger': 1.1.4 + '@azure/msal-browser': 4.0.1 + '@azure/msal-node': 2.16.2 + events: 3.3.0 + jws: 4.0.0 + open: 8.4.2 + stoppable: 1.1.0 + tslib: 2.6.3 + transitivePeerDependencies: + - supports-color + + '@azure/logger@1.1.4': + dependencies: + tslib: 2.6.3 + + '@azure/msal-browser@4.0.1': + dependencies: + '@azure/msal-common': 15.0.1 + + '@azure/msal-common@14.16.0': {} + + '@azure/msal-common@15.0.1': {} + + '@azure/msal-node@2.16.2': + dependencies: + '@azure/msal-common': 14.16.0 + jsonwebtoken: 9.0.2 + uuid: 8.3.2 + + '@azure/search-documents@12.1.0': + dependencies: + '@azure/core-auth': 1.9.0 + '@azure/core-client': 1.9.2 + '@azure/core-http-compat': 2.1.2 + '@azure/core-paging': 1.6.2 + '@azure/core-rest-pipeline': 1.18.2 + '@azure/core-tracing': 1.2.0 + '@azure/core-util': 1.11.0 + '@azure/logger': 1.1.4 + events: 3.3.0 + tslib: 2.6.3 + transitivePeerDependencies: + - supports-color + '@babel/code-frame@7.24.7': dependencies: '@babel/highlight': 7.24.7 @@ -3810,6 +6254,36 @@ snapshots: enabled: 2.0.0 kuler: 2.0.0 + '@datastax/astra-db-ts@1.5.0': + dependencies: + fetch-h2: 3.0.2 + safe-stable-stringify: 2.4.3 + typed-emitter: 2.1.0 + uuidv7: 0.6.3 + + '@discordjs/collection@2.1.1': {} + + '@discordjs/rest@2.4.2': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/util': 1.1.1 + '@sapphire/async-queue': 1.5.5 + '@sapphire/snowflake': 3.5.5 + '@vladfrangu/async_event_emitter': 2.4.6 + discord-api-types: 0.37.116 + magic-bytes.js: 1.10.0 + tslib: 2.6.3 + undici: 6.19.8 + + '@discordjs/util@1.1.1': {} + + '@discoveryjs/json-ext@0.6.3': {} + + '@emnapi/runtime@1.3.1': + dependencies: + tslib: 2.6.3 + optional: true + '@eslint-community/eslint-utils@4.4.1(eslint@9.16.0(jiti@1.21.6))': dependencies: eslint: 9.16.0(jiti@1.21.6) @@ -3853,6 +6327,33 @@ snapshots: '@faker-js/faker@8.4.1': {} + '@fastify/busboy@2.1.1': {} + + '@google-cloud/vertexai@1.9.0': + dependencies: + google-auth-library: 9.15.0 + transitivePeerDependencies: + - encoding + - supports-color + + '@google/generative-ai@0.21.0': {} + + '@graphql-typed-document-node/core@3.2.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + + '@grpc/grpc-js@1.12.5': + dependencies: + '@grpc/proto-loader': 0.7.13 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.13': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.4 + protobufjs: 7.4.0 + yargs: 17.7.2 + '@hey-api/client-axios@0.2.3(axios@1.7.2)': dependencies: axios: 1.7.2 @@ -3867,6 +6368,23 @@ snapshots: transitivePeerDependencies: - magicast + '@huggingface/inference@2.8.1': + dependencies: + '@huggingface/tasks': 0.12.30 + + '@huggingface/jinja@0.1.3': {} + + '@huggingface/jinja@0.3.2': {} + + '@huggingface/tasks@0.12.30': {} + + '@huggingface/transformers@3.3.1': + dependencies: + '@huggingface/jinja': 0.3.2 + onnxruntime-node: 1.20.1 + onnxruntime-web: 1.21.0-dev.20250114-228dd16893 + sharp: 0.33.5 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -3880,36 +6398,111 @@ snapshots: '@humanwhocodes/retry@0.4.1': {} - '@inquirer/checkbox@2.5.0': - dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/figures': 1.0.5 - '@inquirer/type': 1.5.3 - ansi-escapes: 4.3.2 - yoctocolors-cjs: 2.1.2 + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true - '@inquirer/confirm@3.2.0': - dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true - '@inquirer/core@9.1.0': - dependencies: - '@inquirer/figures': 1.0.5 - '@inquirer/type': 1.5.3 - '@types/mute-stream': 0.0.4 - '@types/node': 22.5.4 - '@types/wrap-ansi': 3.0.0 - ansi-escapes: 4.3.2 - cli-spinners: 2.9.2 - cli-width: 4.1.0 - mute-stream: 1.0.0 - signal-exit: 4.1.0 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.2 + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true - '@inquirer/editor@2.2.0': + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.1 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + + '@inquirer/checkbox@2.5.0': + dependencies: + '@inquirer/core': 9.1.0 + '@inquirer/figures': 1.0.5 + '@inquirer/type': 1.5.3 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + + '@inquirer/confirm@3.2.0': + dependencies: + '@inquirer/core': 9.1.0 + '@inquirer/type': 1.5.3 + + '@inquirer/core@9.1.0': + dependencies: + '@inquirer/figures': 1.0.5 + '@inquirer/type': 1.5.3 + '@types/mute-stream': 0.0.4 + '@types/node': 22.5.4 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + + '@inquirer/editor@2.2.0': dependencies: '@inquirer/core': 9.1.0 '@inquirer/type': 1.5.3 @@ -3977,6 +6570,19 @@ snapshots: dependencies: mute-stream: 1.0.0 + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + '@istanbuljs/load-nyc-config@1.1.0': dependencies: camelcase: 5.3.1 @@ -4178,6 +6784,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@js-sdsl/ordered-map@4.4.2': {} + '@jsdevtools/ono@7.1.3': {} '@langchain/core@0.2.21(langchain@0.2.13(axios@1.7.2)(handlebars@4.7.8)(ignore@5.3.2)(openai@4.51.0)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(openai@4.51.0)': @@ -4233,137 +6841,771 @@ snapshots: - langchain - openai + '@llamaindex/anthropic@0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)': + dependencies: + '@anthropic-ai/sdk': 0.32.1 + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + remeda: 2.19.2 + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - encoding + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + + '@llamaindex/clip@0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)': + dependencies: + '@huggingface/transformers': 3.3.1 + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/openai': 0.1.45(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - encoding + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + - ws + - zod + + '@llamaindex/cloud@2.0.21(@llamaindex/core@0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(@llamaindex/env@0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))': + dependencies: + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + + '@llamaindex/core@0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)': + dependencies: + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@types/node': 22.10.7 + magic-bytes.js: 1.10.0 + zod: 3.23.8 + zod-to-json-schema: 3.24.1(zod@3.23.8) + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + + '@llamaindex/deepinfra@0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)': + dependencies: + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/openai': 0.1.45(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - encoding + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + - ws + - zod + + '@llamaindex/env@0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)': + dependencies: + gpt-tokenizer: 2.8.1 + optionalDependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@huggingface/transformers': 3.3.1 + js-tiktoken: 1.0.16 + pathe: 1.1.2 + + '@llamaindex/groq@0.0.44(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)': + dependencies: + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/openai': 0.1.45(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + groq-sdk: 0.8.0 + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - encoding + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + - ws + - zod + + '@llamaindex/huggingface@0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)': + dependencies: + '@huggingface/inference': 2.8.1 + '@huggingface/transformers': 3.3.1 + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/openai': 0.1.45(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - encoding + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + - ws + - zod + + '@llamaindex/node-parser@0.0.21(@llamaindex/core@0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(@llamaindex/env@0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(tree-sitter@0.22.4)(web-tree-sitter@0.24.7)': + dependencies: + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + html-to-text: 9.0.5 + tree-sitter: 0.22.4 + web-tree-sitter: 0.24.7 + + '@llamaindex/ollama@0.0.36(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)': + dependencies: + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + ollama: 0.5.12 + remeda: 2.19.2 + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + + '@llamaindex/openai@0.1.45(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)': + dependencies: + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + openai: 4.79.1(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - encoding + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + - ws + - zod + + '@llamaindex/portkey-ai@0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)': + dependencies: + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + portkey-ai: 0.1.16 + remeda: 2.19.2 + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + + '@llamaindex/readers@1.0.22(@aws-sdk/credential-providers@3.731.1)(@llamaindex/core@0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(@llamaindex/env@0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(bufferutil@4.0.8)(utf-8-validate@6.0.4)': + dependencies: + '@azure/cosmos': 4.2.0 + '@discordjs/rest': 2.4.2 + '@discoveryjs/json-ext': 0.6.3 + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + assemblyai: 4.8.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + csv-parse: 5.6.0 + discord-api-types: 0.37.116 + mammoth: 1.9.0 + mongodb: 6.12.0(@aws-sdk/credential-providers@3.731.1) + notion-md-crawler: 1.0.0 + papaparse: 5.5.1 + unpdf: 0.12.1 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - bufferutil + - encoding + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + - supports-color + - utf-8-validate + + '@llamaindex/replicate@0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)': + dependencies: + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + replicate: 1.0.1 + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + + '@llamaindex/vllm@0.0.15(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)': + dependencies: + '@llamaindex/openai': 0.1.45(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + transitivePeerDependencies: + - '@aws-crypto/sha256-js' + - '@huggingface/transformers' + - encoding + - gpt-tokenizer + - js-tiktoken + - pathe + - tiktoken + - ws + - zod + + '@mapbox/node-pre-gyp@1.0.11': + dependencies: + detect-libc: 2.0.3 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.6.3 + tar: 6.2.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@mistralai/mistralai@1.3.6(zod@3.23.8)': + dependencies: + zod: 3.23.8 + + '@mixedbread-ai/sdk@2.2.11': + dependencies: + form-data: 4.0.0 + formdata-node: 6.0.3 + js-base64: 3.7.2 + node-fetch: 2.7.0 + qs: 6.11.2 + url-join: 4.0.1 + transitivePeerDependencies: + - encoding + + '@mongodb-js/saslprep@1.1.9': + dependencies: + sparse-bitfield: 3.0.3 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - '@nodelib/fs.stat@2.0.5': {} + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@notionhq/client@2.2.15': + dependencies: + '@types/node-fetch': 2.6.11 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@opentelemetry/api@1.9.0': {} + + '@petamoriken/float16@3.9.1': {} + + '@pinecone-database/pinecone@4.1.0': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@qdrant/js-client-rest@1.13.0(typescript@5.4.5)': + dependencies: + '@qdrant/openapi-typescript-fetch': 1.2.6 + '@sevinf/maybe': 0.5.0 + typescript: 5.4.5 + undici: 5.28.5 + + '@qdrant/openapi-typescript-fetch@1.2.6': {} + + '@rollup/plugin-commonjs@25.0.8(rollup@4.28.1)': + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.28.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 8.1.0 + is-reference: 1.2.1 + magic-string: 0.30.11 + optionalDependencies: + rollup: 4.28.1 + + '@rollup/plugin-json@6.1.0(rollup@4.28.1)': + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.28.1) + optionalDependencies: + rollup: 4.28.1 + + '@rollup/plugin-node-resolve@15.3.0(rollup@4.28.1)': + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.28.1) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.8 + optionalDependencies: + rollup: 4.28.1 + + '@rollup/plugin-replace@6.0.1(rollup@4.28.1)': + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.28.1) + magic-string: 0.30.11 + optionalDependencies: + rollup: 4.28.1 + + '@rollup/plugin-typescript@12.1.2(rollup@4.28.1)(tslib@2.6.3)(typescript@5.4.5)': + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.28.1) + resolve: 1.22.8 + typescript: 5.4.5 + optionalDependencies: + rollup: 4.28.1 + tslib: 2.6.3 + + '@rollup/pluginutils@5.1.3(rollup@4.28.1)': + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.28.1 + + '@rollup/rollup-android-arm-eabi@4.28.1': + optional: true + + '@rollup/rollup-android-arm64@4.28.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.28.1': + optional: true + + '@rollup/rollup-darwin-x64@4.28.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.28.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.28.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.28.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.28.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.28.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.28.1': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.28.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.28.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.28.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.28.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.28.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.28.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.28.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.28.1': + optional: true + + '@sapphire/async-queue@1.5.5': {} + + '@sapphire/snowflake@3.5.5': {} + + '@selderee/plugin-htmlparser2@0.11.0': + dependencies: + domhandler: 5.0.3 + selderee: 0.11.0 + + '@sevinf/maybe@0.5.0': {} + + '@sinclair/typebox@0.27.8': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@smithy/abort-controller@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/config-resolver@4.0.1': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-config-provider': 4.0.0 + '@smithy/util-middleware': 4.0.1 + tslib: 2.6.3 + + '@smithy/core@3.1.1': + dependencies: + '@smithy/middleware-serde': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-stream': 4.0.2 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 + + '@smithy/credential-provider-imds@4.0.1': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + tslib: 2.6.3 + + '@smithy/eventstream-codec@1.1.0': + dependencies: + '@aws-crypto/crc32': 3.0.0 + '@smithy/types': 1.2.0 + '@smithy/util-hex-encoding': 1.1.0 + tslib: 2.6.3 + + '@smithy/fetch-http-handler@5.0.1': + dependencies: + '@smithy/protocol-http': 5.0.1 + '@smithy/querystring-builder': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-base64': 4.0.0 + tslib: 2.6.3 + + '@smithy/hash-node@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 + + '@smithy/invalid-dependency@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/is-array-buffer@1.1.0': + dependencies: + tslib: 2.6.3 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.6.3 + + '@smithy/is-array-buffer@4.0.0': + dependencies: + tslib: 2.6.3 + + '@smithy/middleware-content-length@4.0.1': + dependencies: + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/middleware-endpoint@4.0.2': + dependencies: + '@smithy/core': 3.1.1 + '@smithy/middleware-serde': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + '@smithy/url-parser': 4.0.1 + '@smithy/util-middleware': 4.0.1 + tslib: 2.6.3 + + '@smithy/middleware-retry@4.0.3': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/service-error-classification': 4.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-retry': 4.0.1 + tslib: 2.6.3 + uuid: 9.0.1 + + '@smithy/middleware-serde@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/middleware-stack@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/node-config-provider@4.0.1': + dependencies: + '@smithy/property-provider': 4.0.1 + '@smithy/shared-ini-file-loader': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/node-http-handler@4.0.2': + dependencies: + '@smithy/abort-controller': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/querystring-builder': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/property-provider@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/protocol-http@1.2.0': + dependencies: + '@smithy/types': 1.2.0 + tslib: 2.6.3 + + '@smithy/protocol-http@5.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 + + '@smithy/querystring-builder@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + '@smithy/util-uri-escape': 4.0.0 + tslib: 2.6.3 + + '@smithy/querystring-parser@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 - '@nodelib/fs.walk@1.2.8': + '@smithy/service-error-classification@4.0.1': dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 + '@smithy/types': 4.1.0 - '@opentelemetry/api@1.9.0': {} + '@smithy/shared-ini-file-loader@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 - '@rollup/plugin-commonjs@25.0.8(rollup@4.28.1)': + '@smithy/signature-v4@1.1.0': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.1) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.30.11 - optionalDependencies: - rollup: 4.28.1 + '@smithy/eventstream-codec': 1.1.0 + '@smithy/is-array-buffer': 1.1.0 + '@smithy/types': 1.2.0 + '@smithy/util-hex-encoding': 1.1.0 + '@smithy/util-middleware': 1.1.0 + '@smithy/util-uri-escape': 1.1.0 + '@smithy/util-utf8': 1.1.0 + tslib: 2.6.3 - '@rollup/plugin-json@6.1.0(rollup@4.28.1)': + '@smithy/signature-v4@5.0.1': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.1) - optionalDependencies: - rollup: 4.28.1 + '@smithy/is-array-buffer': 4.0.0 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-hex-encoding': 4.0.0 + '@smithy/util-middleware': 4.0.1 + '@smithy/util-uri-escape': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 - '@rollup/plugin-node-resolve@15.3.0(rollup@4.28.1)': + '@smithy/smithy-client@4.1.2': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.1) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.8 - optionalDependencies: - rollup: 4.28.1 + '@smithy/core': 3.1.1 + '@smithy/middleware-endpoint': 4.0.2 + '@smithy/middleware-stack': 4.0.1 + '@smithy/protocol-http': 5.0.1 + '@smithy/types': 4.1.0 + '@smithy/util-stream': 4.0.2 + tslib: 2.6.3 - '@rollup/plugin-replace@6.0.1(rollup@4.28.1)': + '@smithy/types@1.2.0': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.1) - magic-string: 0.30.11 - optionalDependencies: - rollup: 4.28.1 + tslib: 2.6.3 - '@rollup/plugin-typescript@12.1.2(rollup@4.28.1)(tslib@2.6.3)(typescript@5.4.5)': + '@smithy/types@4.1.0': dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.28.1) - resolve: 1.22.8 - typescript: 5.4.5 - optionalDependencies: - rollup: 4.28.1 tslib: 2.6.3 - '@rollup/pluginutils@5.1.3(rollup@4.28.1)': + '@smithy/url-parser@4.0.1': dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 4.0.2 - optionalDependencies: - rollup: 4.28.1 + '@smithy/querystring-parser': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 - '@rollup/rollup-android-arm-eabi@4.28.1': - optional: true + '@smithy/util-base64@4.0.0': + dependencies: + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 - '@rollup/rollup-android-arm64@4.28.1': - optional: true + '@smithy/util-body-length-browser@4.0.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-darwin-arm64@4.28.1': - optional: true + '@smithy/util-body-length-node@4.0.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-darwin-x64@4.28.1': - optional: true + '@smithy/util-buffer-from@1.1.0': + dependencies: + '@smithy/is-array-buffer': 1.1.0 + tslib: 2.6.3 - '@rollup/rollup-freebsd-arm64@4.28.1': - optional: true + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.6.3 - '@rollup/rollup-freebsd-x64@4.28.1': - optional: true + '@smithy/util-buffer-from@4.0.0': + dependencies: + '@smithy/is-array-buffer': 4.0.0 + tslib: 2.6.3 - '@rollup/rollup-linux-arm-gnueabihf@4.28.1': - optional: true + '@smithy/util-config-provider@4.0.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-linux-arm-musleabihf@4.28.1': - optional: true + '@smithy/util-defaults-mode-browser@4.0.3': + dependencies: + '@smithy/property-provider': 4.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + bowser: 2.11.0 + tslib: 2.6.3 - '@rollup/rollup-linux-arm64-gnu@4.28.1': - optional: true + '@smithy/util-defaults-mode-node@4.0.3': + dependencies: + '@smithy/config-resolver': 4.0.1 + '@smithy/credential-provider-imds': 4.0.1 + '@smithy/node-config-provider': 4.0.1 + '@smithy/property-provider': 4.0.1 + '@smithy/smithy-client': 4.1.2 + '@smithy/types': 4.1.0 + tslib: 2.6.3 - '@rollup/rollup-linux-arm64-musl@4.28.1': - optional: true + '@smithy/util-endpoints@3.0.1': + dependencies: + '@smithy/node-config-provider': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 - '@rollup/rollup-linux-loongarch64-gnu@4.28.1': - optional: true + '@smithy/util-hex-encoding@1.1.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': - optional: true + '@smithy/util-hex-encoding@4.0.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-linux-riscv64-gnu@4.28.1': - optional: true + '@smithy/util-middleware@1.1.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-linux-s390x-gnu@4.28.1': - optional: true + '@smithy/util-middleware@4.0.1': + dependencies: + '@smithy/types': 4.1.0 + tslib: 2.6.3 - '@rollup/rollup-linux-x64-gnu@4.28.1': - optional: true + '@smithy/util-retry@4.0.1': + dependencies: + '@smithy/service-error-classification': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 - '@rollup/rollup-linux-x64-musl@4.28.1': - optional: true + '@smithy/util-stream@4.0.2': + dependencies: + '@smithy/fetch-http-handler': 5.0.1 + '@smithy/node-http-handler': 4.0.2 + '@smithy/types': 4.1.0 + '@smithy/util-base64': 4.0.0 + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-hex-encoding': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.6.3 - '@rollup/rollup-win32-arm64-msvc@4.28.1': - optional: true + '@smithy/util-uri-escape@1.1.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-win32-ia32-msvc@4.28.1': - optional: true + '@smithy/util-uri-escape@4.0.0': + dependencies: + tslib: 2.6.3 - '@rollup/rollup-win32-x64-msvc@4.28.1': - optional: true + '@smithy/util-utf8@1.1.0': + dependencies: + '@smithy/util-buffer-from': 1.1.0 + tslib: 2.6.3 - '@sinclair/typebox@0.27.8': {} + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.6.3 - '@sinonjs/commons@3.0.1': + '@smithy/util-utf8@4.0.0': dependencies: - type-detect: 4.0.8 + '@smithy/util-buffer-from': 4.0.0 + tslib: 2.6.3 - '@sinonjs/fake-timers@10.3.0': + '@smithy/util-waiter@4.0.2': dependencies: - '@sinonjs/commons': 3.0.1 + '@smithy/abort-controller': 4.0.1 + '@smithy/types': 4.1.0 + tslib: 2.6.3 '@swc/core-darwin-arm64@1.7.10': optional: true @@ -4507,6 +7749,10 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/lodash@4.17.14': {} + + '@types/long@4.0.2': {} + '@types/mute-stream@0.0.4': dependencies: '@types/node': 20.14.2 @@ -4524,10 +7770,20 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/node@22.10.7': + dependencies: + undici-types: 6.20.0 + '@types/node@22.5.4': dependencies: undici-types: 6.19.8 + '@types/pg@8.11.10': + dependencies: + '@types/node': 20.14.2 + pg-protocol: 1.7.0 + pg-types: 4.0.2 + '@types/resolve@1.20.2': {} '@types/retry@0.12.0': {} @@ -4538,12 +7794,20 @@ snapshots: '@types/stack-utils@2.0.3': {} + '@types/tough-cookie@4.0.5': {} + '@types/triple-beam@1.3.5': {} '@types/uuid@10.0.0': {} '@types/uuid@9.0.8': {} + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@11.0.5': + dependencies: + '@types/webidl-conversions': 7.0.3 + '@types/winston@2.4.4': dependencies: winston: 3.14.0 @@ -4638,6 +7902,10 @@ snapshots: '@typescript-eslint/types': 8.17.0 eslint-visitor-keys: 4.2.0 + '@upstash/vector@1.2.0': {} + + '@vladfrangu/async_event_emitter@2.4.6': {} + '@vue/compiler-core@3.4.36': dependencies: '@babel/parser': 7.25.3 @@ -4768,10 +8036,28 @@ snapshots: '@webassemblyjs/ast': 1.12.1 '@xtuc/long': 4.2.2 + '@xmldom/xmldom@0.8.10': {} + '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} + '@zilliz/milvus2-sdk-node@2.5.4': + dependencies: + '@grpc/grpc-js': 1.12.5 + '@grpc/proto-loader': 0.7.13 + '@petamoriken/float16': 3.9.1 + dayjs: 1.11.13 + generic-pool: 3.9.0 + lru-cache: 9.1.2 + protobufjs: 7.4.0 + winston: 3.14.0 + + abbrev@1.1.1: + optional: true + + abort-controller-x@0.4.3: {} + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -4792,6 +8078,15 @@ snapshots: acorn@8.14.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + optional: true + + agent-base@7.1.3: {} + agentkeepalive@4.5.0: dependencies: humanize-ms: 1.2.1 @@ -4833,12 +8128,23 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.5 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + already@2.2.1: {} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 ansi-regex@5.0.1: {} + ansi-regex@6.1.0: {} + ansi-sequence-parser@1.1.1: {} ansi-styles@3.2.1: @@ -4851,11 +8157,24 @@ snapshots: ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 + aproba@2.0.0: + optional: true + + are-we-there-yet@2.0.0: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + optional: true + arg@4.1.3: {} argparse@1.0.10: @@ -4868,6 +8187,13 @@ snapshots: dependencies: dequal: 2.0.3 + assemblyai@4.8.0(bufferutil@4.0.8)(utf-8-validate@6.0.4): + dependencies: + ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + async@3.2.5: {} asynckit@0.4.0: {} @@ -4888,6 +8214,8 @@ snapshots: axobject-query@4.1.0: {} + b4a@1.6.7: {} + babel-jest@29.7.0(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -4945,10 +8273,49 @@ snapshots: balanced-match@1.0.2: {} + bare-events@2.5.4: + optional: true + + bare-fs@4.0.1: + dependencies: + bare-events: 2.5.4 + bare-path: 3.0.0 + bare-stream: 2.6.4(bare-events@2.5.4) + transitivePeerDependencies: + - bare-buffer + optional: true + + bare-os@3.4.0: + optional: true + + bare-path@3.0.0: + dependencies: + bare-os: 3.4.0 + optional: true + + bare-stream@2.6.4(bare-events@2.5.4): + dependencies: + streamx: 2.21.1 + optionalDependencies: + bare-events: 2.5.4 + optional: true + base64-js@1.5.1: {} + bignumber.js@9.1.2: {} + binary-extensions@2.3.0: {} + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bluebird@3.4.7: {} + + bowser@2.11.0: {} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -4977,8 +8344,22 @@ snapshots: dependencies: node-int64: 0.4.0 + bson@6.10.1: {} + + buffer-equal-constant-time@1.0.1: {} + buffer-from@1.1.2: {} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bufferutil@4.0.8: dependencies: node-gyp-build: 4.8.1 @@ -4999,14 +8380,38 @@ snapshots: pkg-types: 1.1.1 rc9: 2.1.2 + call-bind-apply-helpers@1.0.1: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.3: + dependencies: + call-bind-apply-helpers: 1.0.1 + get-intrinsic: 1.2.7 + + callguard@2.0.0: {} + callsites@3.1.0: {} + camelcase@4.1.0: {} + camelcase@5.3.1: {} camelcase@6.3.0: {} caniuse-lite@1.0.30001633: {} + canvas@2.11.2: + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + nan: 2.22.0 + simple-get: 3.1.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -5036,8 +8441,33 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chownr@1.1.4: {} + chownr@2.0.0: {} + chownr@3.0.0: {} + + chromadb-default-embed@2.13.2: + dependencies: + '@huggingface/jinja': 0.1.3 + onnxruntime-web: 1.14.0 + sharp: 0.32.6 + optionalDependencies: + onnxruntime-node: 1.14.0 + transitivePeerDependencies: + - bare-buffer + + chromadb@1.9.2(@google/generative-ai@0.21.0)(cohere-ai@7.14.0)(openai@4.79.1(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)): + dependencies: + cliui: 8.0.1 + isomorphic-fetch: 3.0.0 + optionalDependencies: + '@google/generative-ai': 0.21.0 + cohere-ai: 7.14.0 + openai: 4.79.1(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + transitivePeerDependencies: + - encoding + chrome-trace-event@1.0.4: {} ci-info@3.9.0: {} @@ -5074,6 +8504,24 @@ snapshots: estree-walker: 3.0.3 periscopic: 3.1.0 + cohere-ai@7.14.0: + dependencies: + '@aws-sdk/client-sagemaker': 3.731.1 + '@aws-sdk/credential-providers': 3.731.1 + '@aws-sdk/protocol-http': 3.374.0 + '@aws-sdk/signature-v4': 3.374.0 + form-data: 4.0.0 + form-data-encoder: 4.0.2 + formdata-node: 6.0.3 + js-base64: 3.7.2 + node-fetch: 2.7.0 + qs: 6.11.2 + readable-stream: 4.7.0 + url-join: 4.0.1 + transitivePeerDependencies: + - aws-crt + - encoding + collect-v8-coverage@1.0.2: {} color-convert@1.9.3: @@ -5093,11 +8541,19 @@ snapshots: color-name: 1.1.4 simple-swizzle: 0.2.2 + color-support@1.1.3: + optional: true + color@3.2.1: dependencies: color-convert: 1.9.3 color-string: 1.9.1 + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + colors@1.4.0: {} colorspace@1.1.4: @@ -5123,8 +8579,13 @@ snapshots: consola@3.2.3: {} + console-control-strings@1.1.0: + optional: true + convert-source-map@2.0.0: {} + core-util-is@1.0.3: {} + create-jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@swc/core@1.7.10(@swc/helpers@0.5.12))(@types/node@20.14.2)(typescript@5.4.5)): dependencies: '@jest/types': 29.6.3 @@ -5142,6 +8603,12 @@ snapshots: create-require@1.1.1: {} + cross-fetch@3.2.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -5161,14 +8628,29 @@ snapshots: csstype@3.1.3: {} + csv-parse@5.6.0: {} + + dayjs@1.11.13: {} + debug@4.3.5: dependencies: ms: 2.1.2 decamelize@1.2.0: {} + decompress-response@4.2.1: + dependencies: + mimic-response: 2.1.0 + optional: true + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + dedent@1.5.3: {} + deep-extend@0.6.0: {} + deep-is@0.1.4: {} deepmerge@4.3.1: {} @@ -5179,10 +8661,15 @@ snapshots: delayed-stream@1.0.0: {} + delegates@1.0.0: + optional: true + dequal@2.0.3: {} destr@2.0.3: {} + detect-libc@2.0.3: {} + detect-newline@3.1.0: {} diff-match-patch@1.0.5: {} @@ -5191,8 +8678,46 @@ snapshots: diff@4.0.2: {} + dingbat-to-unicode@1.0.1: {} + + discord-api-types@0.37.116: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dotenv@16.4.5: {} + duck@0.1.12: + dependencies: + underscore: 1.13.7 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + ejs@3.1.10: dependencies: jake: 10.9.2 @@ -5203,13 +8728,21 @@ snapshots: emoji-regex@8.0.0: {} + emoji-regex@9.2.2: {} + enabled@2.0.0: {} + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + enhanced-resolve@5.17.0: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 + entities@4.5.0: {} + entities@5.0.0: {} enumify@2.0.0: {} @@ -5218,8 +8751,16 @@ snapshots: dependencies: is-arrayish: 0.2.1 + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + es-module-lexer@1.5.3: {} + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + escalade@3.1.2: {} escape-string-regexp@1.0.5: {} @@ -5345,6 +8886,8 @@ snapshots: exit@0.1.2: {} + expand-template@2.0.3: {} + expect@29.7.0: dependencies: '@jest/expect-utils': 29.7.0 @@ -5353,6 +8896,8 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 + extend@3.0.2: {} + external-editor@3.1.0: dependencies: chardet: 0.7.0 @@ -5361,6 +8906,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-fifo@1.3.2: {} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5373,6 +8920,12 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.0.5: {} + + fast-xml-parser@4.4.1: + dependencies: + strnum: 1.0.5 + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -5383,6 +8936,16 @@ snapshots: fecha@4.2.3: {} + fetch-h2@3.0.2: + dependencies: + '@types/tough-cookie': 4.0.5 + already: 2.2.1 + callguard: 2.0.0 + get-stream: 6.0.1 + through2: 4.0.2 + to-arraybuffer: 1.0.1 + tough-cookie: 4.1.4 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -5410,14 +8973,23 @@ snapshots: flatted: 3.3.2 keyv: 4.5.4 + flatbuffers@1.12.0: {} + flatted@3.3.2: {} fn.name@1.1.0: {} follow-redirects@1.15.6: {} + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + form-data-encoder@1.7.2: {} + form-data-encoder@4.0.2: {} + form-data@4.0.0: dependencies: asynckit: 0.4.0 @@ -5429,16 +9001,32 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 4.0.0-beta.3 + formdata-node@6.0.3: {} + + fs-constants@1.0.0: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 + fs-extra@2.1.2: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 2.4.0 + fs-minipass@2.1.0: dependencies: minipass: 3.3.6 + fs-promise@2.0.3: + dependencies: + any-promise: 1.3.0 + fs-extra: 2.1.2 + mz: 2.7.0 + thenify-all: 1.6.0 + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -5446,12 +9034,64 @@ snapshots: function-bind@1.1.2: {} + gauge@3.0.2: + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + optional: true + + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@6.1.0: + dependencies: + gaxios: 6.7.1 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + generic-pool@3.9.0: {} + gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} + get-intrinsic@1.2.7: + dependencies: + call-bind-apply-helpers: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + get-package-type@0.1.0: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + get-stream@6.0.1: {} get-stream@8.0.1: {} @@ -5467,6 +9107,8 @@ snapshots: pathe: 1.1.2 tar: 6.2.1 + github-from-package@0.0.0: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -5477,6 +9119,15 @@ snapshots: glob-to-regexp@0.4.1: {} + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.4 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -5500,10 +9151,58 @@ snapshots: globals@15.13.0: {} + google-auth-library@9.15.0: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.0 + gtoken: 7.1.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + gopd@1.2.0: {} + + gpt-tokenizer@2.8.1: {} + graceful-fs@4.2.11: {} graphemer@1.4.0: {} + graphql-request@6.1.0(graphql@16.10.0): + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + cross-fetch: 3.2.0 + graphql: 16.10.0 + transitivePeerDependencies: + - encoding + + graphql@16.10.0: {} + + groq-sdk@0.8.0: + dependencies: + '@types/node': 18.19.34 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + guid-typescript@1.0.9: {} + handlebars@4.7.8: dependencies: minimist: 1.2.8 @@ -5517,12 +9216,54 @@ snapshots: has-flag@4.0.0: {} + has-symbols@1.1.0: {} + + has-unicode@2.0.1: + optional: true + hasown@2.0.2: dependencies: function-bind: 1.1.2 html-escaper@2.0.2: {} + html-to-text@9.0.5: + dependencies: + '@selderee/plugin-htmlparser2': 0.11.0 + deepmerge: 4.3.1 + dom-serializer: 2.0.0 + htmlparser2: 8.0.2 + selderee: 0.11.0 + + htmlparser2@8.0.2: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.3 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + optional: true + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} human-signals@5.0.0: {} @@ -5535,8 +9276,12 @@ snapshots: dependencies: safer-buffer: 2.1.2 + ieee754@1.2.1: {} + ignore@5.3.2: {} + immediate@3.0.6: {} + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 @@ -5554,8 +9299,14 @@ snapshots: once: 1.4.0 wrappy: 1.0.2 + infobox-parser@3.6.4: + dependencies: + camelcase: 4.1.0 + inherits@2.0.4: {} + ini@1.3.8: {} + inquirer@10.2.2: dependencies: '@inquirer/core': 9.1.0 @@ -5613,8 +9364,17 @@ snapshots: dependencies: is-docker: 2.2.1 + isarray@1.0.0: {} + isexe@2.0.0: {} + isomorphic-fetch@3.0.0: + dependencies: + node-fetch: 2.7.0 + whatwg-fetch: 3.6.20 + transitivePeerDependencies: + - encoding + istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@5.2.1: @@ -5656,6 +9416,12 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jake@10.9.2: dependencies: async: 3.2.5 @@ -5991,10 +9757,16 @@ snapshots: jiti@1.21.6: {} + js-base64@3.7.2: {} + js-tiktoken@1.0.12: dependencies: base64-js: 1.5.1 + js-tiktoken@1.0.16: + dependencies: + base64-js: 1.5.1 + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -6006,14 +9778,22 @@ snapshots: dependencies: argparse: 2.0.1 + jsbi@4.3.0: {} + jsesc@2.5.2: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.1.2 + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} json-stable-stringify-without-jsonify@1.0.1: {} @@ -6028,6 +9808,10 @@ snapshots: chalk: 5.3.0 diff-match-patch: 1.0.5 + jsonfile@2.4.0: + optionalDependencies: + graceful-fs: 4.2.11 + jsonfile@6.1.0: dependencies: universalify: 2.0.1 @@ -6036,6 +9820,48 @@ snapshots: jsonpointer@5.0.1: {} + jsonwebtoken@9.0.2: + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.6.3 + + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + + jwa@1.4.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jwa@2.0.0: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@3.2.2: + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + + jws@4.0.0: + dependencies: + jwa: 2.0.0 + safe-buffer: 5.2.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -6095,6 +9921,8 @@ snapshots: langchain: 0.2.13(axios@1.7.2)(handlebars@4.7.8)(ignore@5.3.2)(openai@4.51.0)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)) openai: 4.55.1(zod@3.23.8) + leac@0.6.0: {} + leven@3.1.0: {} levn@0.4.1: @@ -6102,8 +9930,89 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lie@3.3.0: + dependencies: + immediate: 3.0.6 + lines-and-columns@1.2.4: {} + llamaindex@0.8.31(@aws-sdk/credential-providers@3.731.1)(@huggingface/transformers@3.3.1)(bufferutil@4.0.8)(tree-sitter@0.22.4)(typescript@5.4.5)(utf-8-validate@6.0.4)(web-tree-sitter@0.24.7)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)): + dependencies: + '@anthropic-ai/sdk': 0.32.1 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.731.1 + '@azure/cosmos': 4.2.0 + '@azure/identity': 4.6.0 + '@azure/search-documents': 12.1.0 + '@datastax/astra-db-ts': 1.5.0 + '@discoveryjs/json-ext': 0.6.3 + '@google-cloud/vertexai': 1.9.0 + '@google/generative-ai': 0.21.0 + '@grpc/grpc-js': 1.12.5 + '@llamaindex/anthropic': 0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/clip': 0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + '@llamaindex/cloud': 2.0.21(@llamaindex/core@0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(@llamaindex/env@0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)) + '@llamaindex/core': 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/deepinfra': 0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + '@llamaindex/env': 0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/groq': 0.0.44(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + '@llamaindex/huggingface': 0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + '@llamaindex/node-parser': 0.0.21(@llamaindex/core@0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(@llamaindex/env@0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(tree-sitter@0.22.4)(web-tree-sitter@0.24.7) + '@llamaindex/ollama': 0.0.36(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/openai': 0.1.45(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + '@llamaindex/portkey-ai': 0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/readers': 1.0.22(@aws-sdk/credential-providers@3.731.1)(@llamaindex/core@0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(@llamaindex/env@0.1.25(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2))(bufferutil@4.0.8)(utf-8-validate@6.0.4) + '@llamaindex/replicate': 0.0.29(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) + '@llamaindex/vllm': 0.0.15(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + '@mistralai/mistralai': 1.3.6(zod@3.23.8) + '@mixedbread-ai/sdk': 2.2.11 + '@pinecone-database/pinecone': 4.1.0 + '@qdrant/js-client-rest': 1.13.0(typescript@5.4.5) + '@types/lodash': 4.17.14 + '@types/node': 22.10.7 + '@types/pg': 8.11.10 + '@upstash/vector': 1.2.0 + '@zilliz/milvus2-sdk-node': 2.5.4 + ajv: 8.17.1 + assemblyai: 4.8.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + chromadb: 1.9.2(@google/generative-ai@0.21.0)(cohere-ai@7.14.0)(openai@4.79.1(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8)) + chromadb-default-embed: 2.13.2 + cohere-ai: 7.14.0 + gpt-tokenizer: 2.8.1 + groq-sdk: 0.8.0 + js-tiktoken: 1.0.16 + lodash: 4.17.21 + magic-bytes.js: 1.10.0 + mongodb: 6.12.0(@aws-sdk/credential-providers@3.731.1) + openai: 4.79.1(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8) + pathe: 1.1.2 + rake-modified: 1.0.8 + weaviate-client: 3.3.4 + wikipedia: 2.1.2 + wink-nlp: 2.3.2 + zod: 3.23.8 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@huggingface/transformers' + - '@mongodb-js/zstd' + - aws-crt + - bare-buffer + - bufferutil + - debug + - encoding + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + - supports-color + - tiktoken + - tree-sitter + - typescript + - utf-8-validate + - web-tree-sitter + - ws + loader-runner@4.3.0: {} locate-character@3.0.0: {} @@ -6116,10 +10025,28 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.camelcase@4.3.0: {} + + lodash.includes@4.3.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + lodash.memoize@4.1.2: {} lodash.merge@4.6.2: {} + lodash.once@4.1.1: {} + + lodash@4.17.21: {} + logform@2.6.1: dependencies: '@colors/colors': 1.6.0 @@ -6129,20 +10056,41 @@ snapshots: safe-stable-stringify: 2.4.3 triple-beam: 1.4.1 + long@4.0.0: {} + + long@5.2.4: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 + lop@0.4.2: + dependencies: + duck: 0.1.12 + option: 0.2.4 + underscore: 1.13.7 + + lru-cache@10.4.3: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 + lru-cache@9.1.2: {} + lunr@2.3.9: {} + magic-bytes.js@1.10.0: {} + magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + optional: true + make-dir@4.0.0: dependencies: semver: 7.6.3 @@ -6153,10 +10101,29 @@ snapshots: dependencies: tmpl: 1.0.5 + mammoth@1.9.0: + dependencies: + '@xmldom/xmldom': 0.8.10 + argparse: 1.0.10 + base64-js: 1.5.1 + bluebird: 3.4.7 + dingbat-to-unicode: 1.0.1 + jszip: 3.10.1 + lop: 0.4.2 + path-is-absolute: 1.0.1 + underscore: 1.13.7 + xmlbuilder: 10.1.1 + marked@4.3.0: {} + math-intrinsics@1.1.0: {} + + md-utils-ts@2.0.0: {} + mdn-data@2.0.30: {} + memory-pager@1.5.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -6176,6 +10143,11 @@ snapshots: mimic-fn@4.0.0: {} + mimic-response@2.1.0: + optional: true + + mimic-response@3.1.0: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -6196,13 +10168,24 @@ snapshots: minipass@5.0.0: {} + minipass@7.1.2: {} + minizlib@2.1.2: dependencies: minipass: 3.3.6 yallist: 4.0.0 + minizlib@3.0.1: + dependencies: + minipass: 7.1.2 + rimraf: 5.0.10 + + mkdirp-classic@0.5.3: {} + mkdirp@1.0.4: {} + mkdirp@3.0.1: {} + mlly@1.7.1: dependencies: acorn: 8.11.3 @@ -6210,21 +10193,68 @@ snapshots: pkg-types: 1.1.1 ufo: 1.5.3 + mongodb-connection-string-url@3.0.2: + dependencies: + '@types/whatwg-url': 11.0.5 + whatwg-url: 14.1.0 + + mongodb@6.12.0(@aws-sdk/credential-providers@3.731.1): + dependencies: + '@mongodb-js/saslprep': 1.1.9 + bson: 6.10.1 + mongodb-connection-string-url: 3.0.2 + optionalDependencies: + '@aws-sdk/credential-providers': 3.731.1 + ms@2.1.2: {} ms@2.1.3: {} mustache@4.2.0: {} - mute-stream@1.0.0: {} + mute-stream@1.0.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nan@2.22.0: + optional: true + + nanoid@3.3.6: {} + + nanoid@3.3.7: {} + + napi-build-utils@1.0.2: {} + + natural-compare@1.4.0: {} + + neo-async@2.6.2: {} + + nice-grpc-client-middleware-retry@3.1.9: + dependencies: + abort-controller-x: 0.4.3 + nice-grpc-common: 2.0.2 + + nice-grpc-common@2.0.2: + dependencies: + ts-error: 1.0.6 - nanoid@3.3.6: {} + nice-grpc@2.1.10: + dependencies: + '@grpc/grpc-js': 1.12.5 + abort-controller-x: 0.4.3 + nice-grpc-common: 2.0.2 - nanoid@3.3.7: {} + node-abi@3.73.0: + dependencies: + semver: 7.6.3 - natural-compare@1.4.0: {} + node-addon-api@6.1.0: {} - neo-async@2.6.2: {} + node-addon-api@8.3.0: {} node-domexception@1.0.0: {} @@ -6237,12 +10267,26 @@ snapshots: node-gyp-build@4.8.1: optional: true + node-gyp-build@4.8.4: {} + node-int64@0.4.0: {} node-releases@2.0.14: {} + nopt@5.0.0: + dependencies: + abbrev: 1.1.1 + optional: true + normalize-path@3.0.0: {} + notion-md-crawler@1.0.0: + dependencies: + '@notionhq/client': 2.2.15 + md-utils-ts: 2.0.0 + transitivePeerDependencies: + - encoding + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 @@ -6251,6 +10295,14 @@ snapshots: dependencies: path-key: 4.0.0 + npmlog@5.0.1: + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + optional: true + nypm@0.3.8: dependencies: citty: 0.1.6 @@ -6259,8 +10311,18 @@ snapshots: pathe: 1.1.2 ufo: 1.5.3 + object-assign@4.1.1: {} + + object-inspect@1.13.3: {} + + obuf@1.1.2: {} + ohash@1.1.3: {} + ollama@0.5.12: + dependencies: + whatwg-fetch: 3.6.20 + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -6277,6 +10339,44 @@ snapshots: dependencies: mimic-fn: 4.0.0 + onnx-proto@4.0.4: + dependencies: + protobufjs: 6.11.4 + + onnxruntime-common@1.14.0: {} + + onnxruntime-common@1.20.1: {} + + onnxruntime-common@1.21.0-dev.20241212-1f88284f96: {} + + onnxruntime-node@1.14.0: + dependencies: + onnxruntime-common: 1.14.0 + optional: true + + onnxruntime-node@1.20.1: + dependencies: + onnxruntime-common: 1.20.1 + tar: 7.4.3 + + onnxruntime-web@1.14.0: + dependencies: + flatbuffers: 1.12.0 + guid-typescript: 1.0.9 + long: 4.0.0 + onnx-proto: 4.0.4 + onnxruntime-common: 1.14.0 + platform: 1.3.6 + + onnxruntime-web@1.21.0-dev.20250114-228dd16893: + dependencies: + flatbuffers: 1.12.0 + guid-typescript: 1.0.9 + long: 5.2.4 + onnxruntime-common: 1.21.0-dev.20241212-1f88284f96 + platform: 1.3.6 + protobufjs: 7.4.0 + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -6295,6 +10395,7 @@ snapshots: web-streams-polyfill: 3.3.3 transitivePeerDependencies: - encoding + optional: true openai@4.55.1(zod@3.23.8): dependencies: @@ -6310,8 +10411,25 @@ snapshots: transitivePeerDependencies: - encoding + openai@4.79.1(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))(zod@3.23.8): + dependencies: + '@types/node': 18.19.34 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + optionalDependencies: + ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + zod: 3.23.8 + transitivePeerDependencies: + - encoding + openapi-types@12.1.3: {} + option@0.2.4: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -6357,6 +10475,12 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + + pako@1.0.11: {} + + papaparse@5.5.1: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -6368,6 +10492,11 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parseley@0.12.1: + dependencies: + leac: 0.6.0 + peberminta: 0.9.0 + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -6384,8 +10513,15 @@ snapshots: dependencies: path-root-regex: 0.1.2 + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + pathe@1.1.2: {} + peberminta@0.9.0: {} + perfect-debounce@1.0.0: {} periscopic@3.1.0: @@ -6394,6 +10530,22 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.2 + pg-int8@1.0.1: {} + + pg-numeric@1.0.2: {} + + pg-protocol@1.7.0: {} + + pg-types@4.0.2: + dependencies: + pg-int8: 1.0.1 + pg-numeric: 1.0.2 + postgres-array: 3.0.2 + postgres-bytea: 3.0.0 + postgres-date: 2.1.0 + postgres-interval: 3.0.0 + postgres-range: 1.1.4 + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -6412,12 +10564,45 @@ snapshots: mlly: 1.7.1 pathe: 1.1.2 + platform@1.3.6: {} + + portkey-ai@0.1.16: + dependencies: + agentkeepalive: 4.5.0 + postcss@8.4.41: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 source-map-js: 1.2.0 + postgres-array@3.0.2: {} + + postgres-bytea@3.0.0: + dependencies: + obuf: 1.1.2 + + postgres-date@2.1.0: {} + + postgres-interval@3.0.0: {} + + postgres-range@1.1.4: {} + + prebuild-install@7.1.2: + dependencies: + detect-libc: 2.0.3 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.73.0 + pump: 3.0.2 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.2 + tunnel-agent: 0.6.0 + prelude-ls@1.2.1: {} prettier-plugin-organize-imports@4.1.0(prettier@3.4.2)(typescript@5.4.5): @@ -6433,13 +10618,59 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + priorityqueuejs@2.0.0: {} + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + prompts@2.4.2: dependencies: kleur: 3.0.3 sisteransi: 1.0.5 + protobufjs@6.11.4: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.2 + '@types/node': 20.14.2 + long: 4.0.0 + + protobufjs@7.4.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.14.2 + long: 5.2.4 + proxy-from-env@1.1.0: {} + psl@1.15.0: + dependencies: + punycode: 2.3.1 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + punycode@2.3.1: {} pure-rand@6.1.0: {} @@ -6448,8 +10679,21 @@ snapshots: dependencies: tweetnacl: 1.0.3 + qs@6.11.2: + dependencies: + side-channel: 1.1.0 + + querystringify@2.2.0: {} + queue-microtask@1.2.3: {} + queue-tick@1.0.1: {} + + rake-modified@1.0.8: + dependencies: + fs-promise: 2.0.3 + lodash: 4.17.21 + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 @@ -6459,26 +10703,63 @@ snapshots: defu: 6.1.4 destr: 2.0.3 + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + react-is@18.3.1: {} react@18.3.1: dependencies: loose-envify: 1.4.0 + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 regenerator-runtime@0.14.1: {} + remeda@2.19.2: + dependencies: + type-fest: 4.32.0 + + replicate@1.0.1: + optionalDependencies: + readable-stream: 4.7.0 + require-directory@2.1.1: {} + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -6503,6 +10784,15 @@ snapshots: reusify@1.0.4: {} + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + optional: true + + rimraf@5.0.10: + dependencies: + glob: 10.4.5 + rollup-plugin-dts@6.1.1(rollup@4.28.1)(typescript@5.4.5): dependencies: magic-string: 0.30.11 @@ -6565,6 +10855,8 @@ snapshots: dependencies: tslib: 2.6.3 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safe-stable-stringify@2.4.3: {} @@ -6579,6 +10871,12 @@ snapshots: secure-json-parse@2.7.0: {} + selderee@0.11.0: + dependencies: + parseley: 0.12.1 + + semaphore@1.1.0: {} + semver@6.3.1: {} semver@7.6.2: {} @@ -6593,6 +10891,50 @@ snapshots: dependencies: randombytes: 2.1.0 + set-blocking@2.0.0: + optional: true + + setimmediate@1.0.5: {} + + sharp@0.32.6: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + node-addon-api: 6.1.0 + prebuild-install: 7.1.2 + semver: 7.6.3 + simple-get: 4.0.1 + tar-fs: 3.0.8 + tunnel-agent: 0.6.0 + transitivePeerDependencies: + - bare-buffer + + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -6606,10 +10948,53 @@ snapshots: vscode-oniguruma: 1.7.0 vscode-textmate: 8.0.0 + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.3 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + object-inspect: 1.13.3 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + object-inspect: 1.13.3 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.3 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + signal-exit@3.0.7: {} signal-exit@4.1.0: {} + simple-concat@1.0.1: {} + + simple-get@3.1.1: + dependencies: + decompress-response: 4.2.1 + once: 1.4.0 + simple-concat: 1.0.1 + optional: true + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 @@ -6634,6 +11019,10 @@ snapshots: source-map@0.7.4: {} + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + sprintf-js@1.0.3: {} sswr@2.1.0(svelte@4.2.18): @@ -6647,6 +11036,16 @@ snapshots: dependencies: escape-string-regexp: 2.0.0 + stoppable@1.1.0: {} + + streamx@2.21.1: + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + text-decoder: 1.2.3 + optionalDependencies: + bare-events: 2.5.4 + string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -6658,6 +11057,16 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -6666,14 +11075,22 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + strip-bom@4.0.0: {} strip-final-newline@2.0.0: {} strip-final-newline@3.0.0: {} + strip-json-comments@2.0.1: {} + strip-json-comments@3.1.1: {} + strnum@1.0.5: {} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -6719,6 +11136,37 @@ snapshots: tapable@2.2.1: {} + tar-fs@2.1.2: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.2 + tar-stream: 2.2.0 + + tar-fs@3.0.8: + dependencies: + pump: 3.0.2 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 4.0.1 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-buffer + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar-stream@3.1.7: + dependencies: + b4a: 1.6.7 + fast-fifo: 1.3.2 + streamx: 2.21.1 + tar@6.2.1: dependencies: chownr: 2.0.0 @@ -6728,6 +11176,15 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 + tar@7.4.3: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.1 + mkdirp: 3.0.1 + yallist: 5.0.0 + terser-webpack-plugin@5.3.10(@swc/core@1.7.10(@swc/helpers@0.5.12))(webpack@5.92.0(@swc/core@1.7.10(@swc/helpers@0.5.12))): dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -6752,28 +11209,64 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 + text-decoder@1.2.3: + dependencies: + b4a: 1.6.7 + text-hex@1.0.0: {} + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 tmpl@1.0.5: {} + to-arraybuffer@1.0.1: {} + to-fast-properties@2.0.0: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + tr46@0.0.3: {} + tr46@5.0.0: + dependencies: + punycode: 2.3.1 + + tree-sitter@0.22.4: + dependencies: + node-addon-api: 8.3.0 + node-gyp-build: 4.8.4 + triple-beam@1.4.1: {} ts-api-utils@1.4.3(typescript@5.4.5): dependencies: typescript: 5.4.5 + ts-error@1.0.6: {} + ts-jest@29.2.4(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@swc/core@1.7.10(@swc/helpers@0.5.12))(@types/node@20.14.2)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 @@ -6823,8 +11316,14 @@ snapshots: optionalDependencies: '@swc/core': 1.7.10(@swc/helpers@0.5.12) + tslib@1.14.1: {} + tslib@2.6.3: {} + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + tweetnacl@1.0.3: {} type-check@0.4.0: @@ -6835,6 +11334,12 @@ snapshots: type-fest@0.21.3: {} + type-fest@4.32.0: {} + + typed-emitter@2.1.0: + optionalDependencies: + rxjs: 7.8.1 + typedoc@0.25.13(typescript@5.4.5): dependencies: lunr: 2.3.9 @@ -6861,12 +11366,31 @@ snapshots: uglify-js@3.18.0: optional: true + underscore@1.13.7: {} + undici-types@5.26.5: {} undici-types@6.19.8: {} + undici-types@6.20.0: {} + + undici@5.28.5: + dependencies: + '@fastify/busboy': 2.1.1 + + undici@6.19.8: {} + + universalify@0.2.0: {} + universalify@2.0.1: {} + unpdf@0.12.1: + optionalDependencies: + canvas: 2.11.2 + transitivePeerDependencies: + - encoding + - supports-color + update-browserslist-db@1.0.16(browserslist@4.23.1): dependencies: browserslist: 4.23.1 @@ -6877,6 +11401,13 @@ snapshots: dependencies: punycode: 2.3.1 + url-join@4.0.1: {} + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + use-sync-external-store@1.2.2(react@18.3.1): dependencies: react: 18.3.1 @@ -6890,8 +11421,12 @@ snapshots: uuid@10.0.0: {} + uuid@8.3.2: {} + uuid@9.0.1: {} + uuidv7@0.6.3: {} + v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.3.0: @@ -6923,12 +11458,30 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 - web-streams-polyfill@3.3.3: {} + weaviate-client@3.3.4: + dependencies: + abort-controller-x: 0.4.3 + graphql: 16.10.0 + graphql-request: 6.1.0(graphql@16.10.0) + long: 5.2.4 + nice-grpc: 2.1.10 + nice-grpc-client-middleware-retry: 3.1.9 + nice-grpc-common: 2.0.2 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + + web-streams-polyfill@3.3.3: + optional: true web-streams-polyfill@4.0.0-beta.3: {} + web-tree-sitter@0.24.7: {} + webidl-conversions@3.0.1: {} + webidl-conversions@7.0.0: {} + webpack-sources@3.2.3: {} webpack@5.92.0(@swc/core@1.7.10(@swc/helpers@0.5.12)): @@ -6962,6 +11515,13 @@ snapshots: - esbuild - uglify-js + whatwg-fetch@3.6.20: {} + + whatwg-url@14.1.0: + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -6971,6 +11531,20 @@ snapshots: dependencies: isexe: 2.0.0 + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + optional: true + + wikipedia@2.1.2: + dependencies: + axios: 1.7.2 + infobox-parser: 3.6.4 + transitivePeerDependencies: + - debug + + wink-nlp@2.3.2: {} + winston-transport@4.7.1: dependencies: logform: 2.6.1 @@ -7007,6 +11581,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} write-file-atomic@4.0.2: @@ -7018,7 +11598,8 @@ snapshots: optionalDependencies: bufferutil: 4.0.8 utf-8-validate: 6.0.4 - optional: true + + xmlbuilder@10.1.1: {} y18n@5.0.8: {} @@ -7026,6 +11607,8 @@ snapshots: yallist@4.0.0: {} + yallist@5.0.0: {} + yaml@2.4.5: {} yargs-parser@21.1.1: {} @@ -7054,4 +11637,8 @@ snapshots: dependencies: zod: 3.23.8 + zod-to-json-schema@3.24.1(zod@3.23.8): + dependencies: + zod: 3.23.8 + zod@3.23.8: {} From 3a8fb8e6475400bbc67ef414d04f2d7401327741 Mon Sep 17 00:00:00 2001 From: Abhishek Patil <83769052+abhishekpatil4@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:06:21 +0530 Subject: [PATCH 08/34] Feat/docs monitor logs (#1172) --- docs/mint.json | 1 + docs/monitoring-logs.mdx | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 docs/monitoring-logs.mdx diff --git a/docs/mint.json b/docs/mint.json index 9807b7bb187..f236f3cbbd1 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -192,6 +192,7 @@ "faq/api_key/cli", "faq/integrations_and_connections/list_of_tools", "faq/supported_llms/supported_llm", + "monitoring-docs", "changelog" ] }, diff --git a/docs/monitoring-logs.mdx b/docs/monitoring-logs.mdx new file mode 100644 index 00000000000..47182912abf --- /dev/null +++ b/docs/monitoring-logs.mdx @@ -0,0 +1,17 @@ +--- +title: "Monitoring Logs" +sidebarTitle: "Monitoring Logs" +description: "How to monitor logs & troubleshoot errors" +--- + +#### Monitoring Action Execution & Triggers Logs + + +You can monitor the action execution & triggers logs by clicking on [Action Logs](https://app.composio.dev/logs) and [Triggers Logs](https://app.composio.dev/trigger_logs) under **Logs** on the dashboard. + + + +Click on any log to view detais like log id, provider name, action name, request & response body. Similarly in triggers logs, you can view the trigger name, trigger ID & payload + + + From 8e6f898f177994f904dcf55ccc5a159b60e459c1 Mon Sep 17 00:00:00 2001 From: Prathit <67639393+Prat011@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:14:31 +0530 Subject: [PATCH 09/34] fix: trend finder agent added and existing python examples were fixed (#1173) --- .../AI_PM_agent/crewai/main.py | 24 +++---- .../AI_PM_agent/crewai/setup.sh | 10 +-- .../AI_PM_agent/llamaindex/main.py | 34 ++++------ .../AI_PM_agent/llamaindex/setup.sh | 9 ++- .../Second_brain_Agent/crewai/setup.sh | 2 +- .../Second_brain_Agent/llamaindex/setup.sh | 2 +- .../content_writing_agent/llamaindex/main.py | 2 +- .../content_writing_agent/llamaindex/setup.sh | 3 +- .../content_writing_agent/phidata/main.py | 6 +- .../content_writing_agent/phidata/setup.sh | 1 - .../crewai/main.py | 12 ++-- .../crewai/setup.sh | 12 ++-- .../llamaindex/main.py | 6 +- .../llamaindex/setup.sh | 12 ++-- .../image_search/image_search_autogen/main.py | 2 +- .../image_search/image_search_crewai/main.py | 2 +- .../indie_hacker_agent/langgraph/main.py | 4 +- .../indie_hacker_agent/langgraph/readme.md | 2 +- .../langgraph/requirements.txt | 2 + .../indie_hacker_agent/langgraph/setup.sh | 12 +--- .../indie_hacker_agent/letta/.env.example | 4 -- .../indie_hacker_agent/letta/main.py | 38 ----------- .../indie_hacker_agent/letta/readme.md | 30 --------- .../indie_hacker_agent/letta/requirements.txt | 3 - .../lead_generator_agent/main.py | 2 +- .../lead_generator_agent/setup.sh | 3 + .../lead_outreach_agent/crewai/main.py | 21 +++--- .../lead_outreach_agent/llamaindex/main.py | 60 ++++------------- .../llamaindex/requirements.txt | 3 +- .../lead_outreach_agent/llamaindex/setup.sh | 1 + .../newsletter_summarizer_autogen/README.md | 2 +- .../newsletter_summarizer_autogen/main.py | 2 - .../newsletter_summarizer_autogen/setup.sh | 1 + .../newsletter_summarizer_crewai/README.md | 2 +- .../newsletter_summarizer_crewai/main.py | 11 ++-- .../newsletter_summarizer_crewai/setup.sh | 1 + .../newsletter_summarizer_llamaindex/main.py | 2 +- .../newsletter_summarizer_llamaindex/setup.sh | 1 + .../pr_agent/pr_agent_autogen/main.py | 8 +-- .../pr_agent/pr_agent_autogen/setup.sh | 9 +-- .../pr_agent/pr_agent_crewai/main.py | 15 +++-- .../pr_agent/pr_agent_crewai/setup.sh | 6 +- .../pr_agent/pr_agent_langchain/main.py | 6 +- .../pr_agent/pr_agent_langchain/setup.sh | 8 +-- .../pr_agent/pr_agent_llama_index/main.py | 10 +-- .../pr_agent_llama_index/requirements.txt | 3 +- .../pr_agent/pr_agent_llama_index/setup.sh | 9 +-- .../pr_agent/pr_agent_openai/main.py | 10 +-- .../pr_agent/pr_agent_openai/requirements.txt | 1 + .../pr_agent/pr_agent_openai/setup.sh | 8 +-- .../advanced_agents/recruiter_agent/main.py | 6 +- .../recruiter_agent/requirements.txt | 4 ++ .../advanced_agents/recruiter_agent/setup.sh | 2 + .../scheduler_agent_autogen/main.py | 26 ++------ .../scheduler_agent_autogen/readme.md | 2 +- .../scheduler_agent_autogen/requirements.txt | 3 +- .../scheduler_agent_autogen/setup.sh | 2 +- .../scheduler_agent_crewai/main.py | 27 ++------ .../scheduler_agent_crewai/readme.md | 2 +- .../scheduler_agent_crewai/requirements.txt | 3 +- .../scheduler_agent_crewai/setup.sh | 2 +- .../scheduler_agent_langchain/main.py | 6 +- .../scheduler_agent_langchain/readme.md | 2 +- .../requirements.txt | 4 +- .../scheduler_agent_langchain/setup.sh | 1 - .../scheduler_agent_langgraph/main.py | 17 ++--- .../scheduler_agent_langgraph/readme.md | 4 +- .../scheduler_agent_langgraph/setup.sh | 1 - .../scheduler_agent_llamaindex/main.py | 24 ++----- .../scheduler_agent_llamaindex/readme.md | 2 +- .../requirements.txt | 2 + .../scheduler_agent_llamaindex/setup.sh | 1 - .../scheduler_agent_phidata/main.py | 17 ++--- .../scheduler_agent_phidata/readme.md | 2 +- .../scheduler_agent_phidata/setup.sh | 1 - .../slack_agent_autogen/readme.md | 2 +- .../slack_agent_autogen/setup.sh | 12 ++-- .../slack_agent_autogen.py | 9 +-- .../slack_agent_crewai/readme.md | 2 +- .../slack_agent_crewai/setup.sh | 12 ++-- .../slack_agent_crewai/slack_agent_crewai.py | 11 ++-- .../slack_agent_langchain/readme.md | 2 +- .../slack_agent_langchain/setup.sh | 12 ++-- .../slack_agent_langchain.py | 6 +- .../slack_agent_llamaindex/readme.md | 2 +- .../slack_agent_llamaindex/setup.sh | 11 ++-- .../slack_agent_llamaindex.py | 8 +-- .../slack_agent_ollama/main.py | 10 +-- .../slack_agent_ollama/readme.md | 2 +- .../slack_agent_ollama/requirements.txt | 1 + .../slack_agent_ollama/setup.sh | 11 ++-- .../slack_agent_openai/readme.md | 2 +- .../slack_agent_openai/setup.sh | 11 ++-- .../slack_agent_openai/slack_agent_openai.py | 7 +- .../miscellaneous/news_summary/setup.sh | 2 +- .../Notion_todo_list_agent/crewai/setup.sh | 2 + .../llamaindex/setup.sh | 3 + .../calendar_agent/crewai/README.md | 2 +- .../calendar_agent/langgraph/README.md | 2 +- .../calendar_agent/langgraph/main.py | 2 +- .../calendar_agent/llamaindex/README.md | 2 +- .../calendar_agent/llamaindex/main.py | 2 +- .../quickstarters/code-analysis/README.md | 2 +- .../code_execution_agent/README.md | 2 +- .../code_execution_agent/crewai_ci_chart.py | 5 +- .../code_execution_agent/main.py | 9 +-- .../code_execution_agent/requirements.txt | 2 - .../customer_support/swarm/readme.md | 2 +- .../presentation_agent/crewai/main.py | 6 +- .../presentation_agent/crewai/setup.sh | 1 + .../presentation_agent/langgraph/main.py | 2 +- .../presentation_agent/langgraph/setup.sh | 1 + .../presentation_agent/llama_index/main.py | 2 +- .../presentation_agent/llama_index/setup.sh | 1 + .../research_assistant_camelai/setup.sh | 2 +- .../research_assistant_crewai/setup.sh | 2 +- .../research_assistant_praisonai/setup.sh | 2 +- .../quickstarters/solana-agent/main.py | 12 ++-- .../quickstarters/solana-agent/readme.md | 6 +- .../startup_trend_generator/.env.example | 2 + .../startup_trend_generator/main.py | 34 ++++++++++ .../startup_trend_generator/readme.md | 30 +++++++++ .../startup_trend_generator/requirements.txt | 2 + .../startup_trend_generator}/setup.sh | 15 +---- .../quickstarters/trend_finder/.env.example | 2 + .../quickstarters/trend_finder/main.py | 64 +++++++++++++++++++ .../quickstarters/trend_finder/readme.md | 30 +++++++++ .../trend_finder/requirements.txt | 2 + .../quickstarters/trend_finder/setup.sh | 31 +++++++++ 129 files changed, 512 insertions(+), 511 deletions(-) delete mode 100644 python/examples/advanced_agents/indie_hacker_agent/letta/.env.example delete mode 100644 python/examples/advanced_agents/indie_hacker_agent/letta/main.py delete mode 100644 python/examples/advanced_agents/indie_hacker_agent/letta/readme.md delete mode 100644 python/examples/advanced_agents/indie_hacker_agent/letta/requirements.txt create mode 100644 python/examples/quickstarters/startup_trend_generator/.env.example create mode 100644 python/examples/quickstarters/startup_trend_generator/main.py create mode 100644 python/examples/quickstarters/startup_trend_generator/readme.md create mode 100644 python/examples/quickstarters/startup_trend_generator/requirements.txt rename python/examples/{advanced_agents/indie_hacker_agent/letta => quickstarters/startup_trend_generator}/setup.sh (70%) create mode 100644 python/examples/quickstarters/trend_finder/.env.example create mode 100644 python/examples/quickstarters/trend_finder/main.py create mode 100644 python/examples/quickstarters/trend_finder/readme.md create mode 100644 python/examples/quickstarters/trend_finder/requirements.txt create mode 100644 python/examples/quickstarters/trend_finder/setup.sh diff --git a/python/examples/advanced_agents/AI_PM_agent/crewai/main.py b/python/examples/advanced_agents/AI_PM_agent/crewai/main.py index 2eb6e96ac33..4c69140f81f 100644 --- a/python/examples/advanced_agents/AI_PM_agent/crewai/main.py +++ b/python/examples/advanced_agents/AI_PM_agent/crewai/main.py @@ -19,8 +19,8 @@ RESPOND_ONLY_IF_TAGGED = ( True # Set to True to have the bot respond only when tagged in a message ) -import agentops -agentops.init(os.environ["AGENTOPS_API_KEY"]) +# import agentops +# agentops.init(os.environ["AGENTOPS_API_KEY"]) #from langchain_cerebras import ChatCerebras @@ -46,7 +46,7 @@ def proc(mail_message, sender_mail): "text": f"Are you sure you want to post message:{mail_message} from sender email:{sender_mail}. If yes, tag test_app and tell it the project id and team id.", }, ) - slack_listener.listen() + slack_listener.wait_forever() @@ -55,20 +55,20 @@ def proc(mail_message, sender_mail): goal="You are an agent that creates issues in Linear based on customer feedback emails", backstory="You are an expert in using Linear and creating issues on it.", llm=llm, - tools=composio_tools, + tools=composio_tools, # type: ignore ) # Callback function for handling new messages in a Slack channel @slack_listener.callback(filters={"trigger_name": "slackbot_receive_message"}) -def callback_new_message(event: TriggerEventData) -> None: +def callback_slack_new_message(event: TriggerEventData) -> None: print("Recieved new messsage") payload = event.payload user_id = payload.get("user", "") # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") @@ -77,7 +77,7 @@ def callback_new_message(event: TriggerEventData) -> None: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") return ( f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" - ) + ) # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -98,14 +98,14 @@ def callback_new_message(event: TriggerEventData) -> None: ), expected_output="issue was created", agent=issue_creator_agent, - tools=composio_tools + tools=composio_tools # type: ignore ) crew = Crew( agents=[issue_creator_agent], tasks=[issue_task], process=Process.sequential, - tools = composio_tools + tools = composio_tools # type: ignore ) result = crew.kickoff() @@ -120,7 +120,7 @@ def callback_new_message(event: TriggerEventData) -> None: @gmail_listener.callback(filters={"trigger_name": "gmail_new_gmail_message"}) -def callback_new_message(event: TriggerEventData) -> None: +def callback_gmail_new_message(event: TriggerEventData) -> None: print("MESSAGE RECEIVED") print("here in the function") payload = event.payload @@ -140,12 +140,12 @@ def callback_new_message(event: TriggerEventData) -> None: "pre": { Action.LINEAR_CREATE_LINEAR_ISSUE: proc(mail_message, sender_mail) }, - } + } # type: ignore ) print("GMAIL LISTENING") -gmail_listener.listen() +gmail_listener.wait_forever() diff --git a/python/examples/advanced_agents/AI_PM_agent/crewai/setup.sh b/python/examples/advanced_agents/AI_PM_agent/crewai/setup.sh index a39a3aa6497..260a3de0d66 100644 --- a/python/examples/advanced_agents/AI_PM_agent/crewai/setup.sh +++ b/python/examples/advanced_agents/AI_PM_agent/crewai/setup.sh @@ -16,15 +16,15 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot +echo "Add slack tool. Finish the flow" +composio add slack composio add gmail +composio add linear echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply composio triggers enable new_gmail_message # Copy env backup to .env file diff --git a/python/examples/advanced_agents/AI_PM_agent/llamaindex/main.py b/python/examples/advanced_agents/AI_PM_agent/llamaindex/main.py index 789959efbb1..49efe811256 100644 --- a/python/examples/advanced_agents/AI_PM_agent/llamaindex/main.py +++ b/python/examples/advanced_agents/AI_PM_agent/llamaindex/main.py @@ -20,8 +20,8 @@ RESPOND_ONLY_IF_TAGGED = ( True # Set to True to have the bot respond only when tagged in a message ) -import agentops -agentops.init(os.environ["AGENTOPS_API_KEY"]) +# import agentops +# agentops.init(os.environ["AGENTOPS_API_KEY"]) llm = OpenAI(model="gpt-4o") @@ -44,7 +44,7 @@ def proc(): "text": f"Are you sure you want to post message:{mail_message} from sender email:{sender_mail}. If yes, tag test_app and tell it the project id and team id.", }, ) - slack_listener.listen() + slack_listener.wait_forever() @@ -60,7 +60,7 @@ def proc(): ] agent = FunctionCallingAgentWorker( - tools=composio_tools, + tools=composio_tools, # type: ignore llm=llm, prefix_messages=prefix_messages, max_function_calls=10, @@ -71,14 +71,14 @@ def proc(): # Callback function for handling new messages in a Slack channel @slack_listener.callback(filters={"trigger_name": "slackbot_receive_message"}) -def callback_new_message(event: TriggerEventData) -> None: +def callback_slack_new_message(event: TriggerEventData) -> None: print("Recieved new messsage") payload = event.payload user_id = payload.get("user", "") # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") @@ -86,8 +86,8 @@ def callback_new_message(event: TriggerEventData) -> None: if RESPOND_ONLY_IF_TAGGED and f"<@{BOT_USER_ID}>" not in message: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") return ( - f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" - ) + f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" # type: ignore + ) # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -105,16 +105,16 @@ def callback_new_message(event: TriggerEventData) -> None: ), ) ] - tools = composio_toolset.get_tools(apps=[App.LINEAR]) + tools = composio_toolset.get_tools(apps=[App.LINEAR]) # type: ignore # Process the message and post the response in the same channel or thread check_agent = FunctionCallingAgentWorker( - tools=tools, + tools=tools, # type: ignore llm=llm, prefix_messages=YES_OR_NO_prefix_messages, max_function_calls=10, allow_parallel_tool_calls=False, verbose=True, - ).as_agent() + ).as_agent() # type: ignore query_task = f""" 2. If you decide to create an issue, Create it on Linear. 3. If you decide to create an issue it should be a summary of the email content. @@ -125,7 +125,7 @@ def callback_new_message(event: TriggerEventData) -> None: 6. If the user does not give project_id or team_id find them out by using Linear Tool's actions. """ result = check_agent.chat(query_task) - print(result) + print(result) # type: ignore composio_toolset.execute_action( action=Action.SLACKBOT_CHAT_POST_MESSAGE, params={ @@ -152,16 +152,10 @@ def callback_new_message(event: TriggerEventData) -> None: return print(sender_mail) print("WAITING FOR SLACK CONFIRMATION") - composio_toolset_1 = ComposioToolSet( - processors={ - "pre": { - Action.LINEAR_CREATE_LINEAR_ISSUE: proc() - }, - } - ) + proc() print("GMAIL LISTENING") -gmail_listener.listen() +gmail_listener.wait_forever() diff --git a/python/examples/advanced_agents/AI_PM_agent/llamaindex/setup.sh b/python/examples/advanced_agents/AI_PM_agent/llamaindex/setup.sh index a39a3aa6497..cfee14aa6c7 100644 --- a/python/examples/advanced_agents/AI_PM_agent/llamaindex/setup.sh +++ b/python/examples/advanced_agents/AI_PM_agent/llamaindex/setup.sh @@ -16,15 +16,14 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool - echo "Add slackbot tool. Finish the flow" -composio add slackbot +composio add slack composio add gmail +composio add linear echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply composio triggers enable new_gmail_message # Copy env backup to .env file diff --git a/python/examples/advanced_agents/Second_brain_Agent/crewai/setup.sh b/python/examples/advanced_agents/Second_brain_Agent/crewai/setup.sh index ef049fa3357..8b81564ec38 100644 --- a/python/examples/advanced_agents/Second_brain_Agent/crewai/setup.sh +++ b/python/examples/advanced_agents/Second_brain_Agent/crewai/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add tool. Finish the flow" composio add serpapi diff --git a/python/examples/advanced_agents/Second_brain_Agent/llamaindex/setup.sh b/python/examples/advanced_agents/Second_brain_Agent/llamaindex/setup.sh index ef049fa3357..8b81564ec38 100644 --- a/python/examples/advanced_agents/Second_brain_Agent/llamaindex/setup.sh +++ b/python/examples/advanced_agents/Second_brain_Agent/llamaindex/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add tool. Finish the flow" composio add serpapi diff --git a/python/examples/advanced_agents/content_writing_agent/llamaindex/main.py b/python/examples/advanced_agents/content_writing_agent/llamaindex/main.py index 996a72c8b0f..69bfe0d83d1 100644 --- a/python/examples/advanced_agents/content_writing_agent/llamaindex/main.py +++ b/python/examples/advanced_agents/content_writing_agent/llamaindex/main.py @@ -50,7 +50,7 @@ def create_prefix_message(): # Initialize the agent agent = FunctionCallingAgentWorker( - tools=tools, + tools=tools, # type: ignore llm=llm, prefix_messages=prefix_messages, max_function_calls=10, diff --git a/python/examples/advanced_agents/content_writing_agent/llamaindex/setup.sh b/python/examples/advanced_agents/content_writing_agent/llamaindex/setup.sh index 0ff8854e651..0c0c6ef99e9 100644 --- a/python/examples/advanced_agents/content_writing_agent/llamaindex/setup.sh +++ b/python/examples/advanced_agents/content_writing_agent/llamaindex/setup.sh @@ -16,13 +16,14 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add slackbot tool. Finish the flow" composio add twitter composio add linkedin composio add firecrawl composio add tavily +composio add googlesheets # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/advanced_agents/content_writing_agent/phidata/main.py b/python/examples/advanced_agents/content_writing_agent/phidata/main.py index 438f5242537..5534a4a6d7a 100644 --- a/python/examples/advanced_agents/content_writing_agent/phidata/main.py +++ b/python/examples/advanced_agents/content_writing_agent/phidata/main.py @@ -1,5 +1,5 @@ -from phi.agent import Agent -from phi.model.openai import OpenAIChat +from phi.agent.agent import Agent +from phi.model.openai.chat import OpenAIChat from composio_phidata import ComposioToolSet, App, Action from dotenv import load_dotenv import json @@ -12,7 +12,7 @@ description="you help the user plan their weekends", name="AI Writer", add_chat_history_to_messages=True, - model=OpenAIChat(id="gpt-4o"), + model=OpenAIChat(id="gpt-4o"), # type: ignore instructions=[ """ You are a creative content automation agent. Your tasks are: diff --git a/python/examples/advanced_agents/content_writing_agent/phidata/setup.sh b/python/examples/advanced_agents/content_writing_agent/phidata/setup.sh index 0ff8854e651..35b7e0b0083 100644 --- a/python/examples/advanced_agents/content_writing_agent/phidata/setup.sh +++ b/python/examples/advanced_agents/content_writing_agent/phidata/setup.sh @@ -16,7 +16,6 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool echo "Add slackbot tool. Finish the flow" composio add twitter diff --git a/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/main.py b/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/main.py index 9e8630fecc5..24bd0d860c5 100644 --- a/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/main.py +++ b/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/main.py @@ -35,7 +35,7 @@ slack_tools = composio_toolset.get_tools( actions=[ - Action.SLACKBOT_CHAT_POST_MESSAGE, + Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, ] ) @@ -54,7 +54,7 @@ def proc() -> None: }, ) print("Message sent to Slack channel. Waiting for user response...") - slack_listener.listen() + slack_listener.wait_forever() # Listens to user response on Slack @slack_listener.callback(filters={"trigger_name": "slackbot_receive_message"}) @@ -93,7 +93,7 @@ def callback_new_message(event: TriggerEventData) -> None: You should also draft an email in response to the sender of the previous email """, verbose=True, - tools=schedule_tool, + tools=schedule_tool, # type: ignore llm=llm ) @@ -117,7 +117,7 @@ def callback_new_message(event: TriggerEventData) -> None: """, expected_output="Event was scheduler and a reply was drafted", agent=scheduler_agent, - tools = schedule_tool + tools = schedule_tool # type: ignore ) crew = Crew( @@ -129,7 +129,7 @@ def callback_new_message(event: TriggerEventData) -> None: response = crew.kickoff() print("Response from agent received:") print(response) - return response.raw + return response.raw # type: ignore # Gmail listener Function # We initialize mail content variable mail_message and sender mail here @@ -156,4 +156,4 @@ def callback_gmail_message(event: TriggerEventData) -> None: print(f"Error in callback_gmail_message: {e}") print("GMAIL LISTENING... Waiting for new messages.") -gmail_listener.listen() \ No newline at end of file +gmail_listener.wait_forever() \ No newline at end of file diff --git a/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/setup.sh b/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/setup.sh index 701a490f51e..2d3ce1775d4 100644 --- a/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/setup.sh +++ b/python/examples/advanced_agents/human_in_the_loop_scheduler/crewai/setup.sh @@ -16,14 +16,14 @@ pip install -r requirements.txt || { echo "Failed to install libraries"; exit 1; echo "Login to your Composio account" composio login || { echo "Failed to login to Composio"; exit 1; } -# Add slackbot tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot || { echo "Failed to add slackbot"; exit 1; } +# Add slack tool +echo "Add slack tool. Finish the flow" +composio add slack || { echo "Failed to add slack"; exit 1; } composio add gmail || { echo "Failed to add gmail"; exit 1; } -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message || { echo "Failed to enable slackbot_receive_message trigger"; exit 1; } -composio triggers enable slackbot_receive_thread_reply || { echo "Failed to enable slackbot_receive_thread_reply trigger"; exit 1; } +echo "Enable slack triggers" +composio triggers enable slack_receive_message || { echo "Failed to enable slack_receive_message trigger"; exit 1; } +composio triggers enable slack_receive_thread_reply || { echo "Failed to enable slack_receive_thread_reply trigger"; exit 1; } composio triggers enable new_gmail_message || { echo "Failed to enable new_gmail_message trigger"; exit 1; } # Copy env backup to .env file diff --git a/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/main.py b/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/main.py index 9c2ce17fa0d..a139ace2afe 100644 --- a/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/main.py +++ b/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/main.py @@ -56,7 +56,7 @@ def proc() -> None: }, ) print("Message sent to Slack channel. Waiting for user response...") - slack_listener.listen() + slack_listener.wait_forever() # Listens to user response on Slack @slack_listener.callback(filters={"trigger_name": "slackbot_receive_message"}) @@ -101,7 +101,7 @@ def callback_new_message(event: TriggerEventData) -> None: print("Creating agent for analyzing email...") agent = FunctionCallingAgentWorker( - tools=schedule_tool, # Tools available for the agent to use + tools=schedule_tool, # Tools available for the agent to use # type: ignore llm=llm, # Language model for processing requests prefix_messages=prefix_messages, # Initial system messages for context max_function_calls=10, # Maximum number of function calls allowed @@ -160,4 +160,4 @@ def callback_gmail_message(event: TriggerEventData) -> None: print(f"Error in callback_gmail_message: {e}") print("GMAIL LISTENING... Waiting for new messages.") -gmail_listener.listen() \ No newline at end of file +gmail_listener.wait_forever() \ No newline at end of file diff --git a/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/setup.sh b/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/setup.sh index 701a490f51e..2d3ce1775d4 100644 --- a/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/setup.sh +++ b/python/examples/advanced_agents/human_in_the_loop_scheduler/llamaindex/setup.sh @@ -16,14 +16,14 @@ pip install -r requirements.txt || { echo "Failed to install libraries"; exit 1; echo "Login to your Composio account" composio login || { echo "Failed to login to Composio"; exit 1; } -# Add slackbot tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot || { echo "Failed to add slackbot"; exit 1; } +# Add slack tool +echo "Add slack tool. Finish the flow" +composio add slack || { echo "Failed to add slack"; exit 1; } composio add gmail || { echo "Failed to add gmail"; exit 1; } -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message || { echo "Failed to enable slackbot_receive_message trigger"; exit 1; } -composio triggers enable slackbot_receive_thread_reply || { echo "Failed to enable slackbot_receive_thread_reply trigger"; exit 1; } +echo "Enable slack triggers" +composio triggers enable slack_receive_message || { echo "Failed to enable slack_receive_message trigger"; exit 1; } +composio triggers enable slack_receive_thread_reply || { echo "Failed to enable slack_receive_thread_reply trigger"; exit 1; } composio triggers enable new_gmail_message || { echo "Failed to enable new_gmail_message trigger"; exit 1; } # Copy env backup to .env file diff --git a/python/examples/advanced_agents/image_search/image_search_autogen/main.py b/python/examples/advanced_agents/image_search/image_search_autogen/main.py index 7c92aa62e62..e4a8e5be9ca 100644 --- a/python/examples/advanced_agents/image_search/image_search_autogen/main.py +++ b/python/examples/advanced_agents/image_search/image_search_autogen/main.py @@ -46,7 +46,7 @@ # Register tools with the ComposioToolSet, specifying the caller (chatbot) and executor (user_proxy) composio_toolset.register_tools( - tools=[App.EMBED_TOOL], # Tools to be registered + apps=[App.EMBED_TOOL], # Tools to be registered caller=chatbot, # The chatbot that calls the tools executor=user_proxy, # The user proxy that executes the tools ) diff --git a/python/examples/advanced_agents/image_search/image_search_crewai/main.py b/python/examples/advanced_agents/image_search/image_search_crewai/main.py index 44dfdd665f8..3406d64b4dc 100644 --- a/python/examples/advanced_agents/image_search/image_search_crewai/main.py +++ b/python/examples/advanced_agents/image_search/image_search_crewai/main.py @@ -34,7 +34,7 @@ role="Image Search Agent", goal=("Search and retrieve images based on specific queries."), verbose=True, # Enable verbose output - memory=True, # Enable memory for the agent + memory=True, # Enable memory for the agent # type: ignore backstory=( "You are an image search expert, skilled in finding and retrieving relevant images from the web. " "Your keen eye for detail ensures that the images you find are accurate and high quality." diff --git a/python/examples/advanced_agents/indie_hacker_agent/langgraph/main.py b/python/examples/advanced_agents/indie_hacker_agent/langgraph/main.py index f52e348ce7e..9e54892cd4f 100644 --- a/python/examples/advanced_agents/indie_hacker_agent/langgraph/main.py +++ b/python/examples/advanced_agents/indie_hacker_agent/langgraph/main.py @@ -53,7 +53,7 @@ def chatbot(state: State): Also print the link to the original idea on hackernews.""") # The config is the **second positional argument** to stream() or invoke()! events = graph.stream( - {"messages": [("user", user_input)]}, config, stream_mode="values" + {"messages": [("user", user_input)]}, config, stream_mode="values" # type: ignore ) for event in events: event["messages"][-1].pretty_print() @@ -68,7 +68,7 @@ def chatbot(state: State): ) ] }, - config, + config, # type: ignore stream_mode="values", ) for event in events: diff --git a/python/examples/advanced_agents/indie_hacker_agent/langgraph/readme.md b/python/examples/advanced_agents/indie_hacker_agent/langgraph/readme.md index 0de4fba1d6f..d8f0e165280 100644 --- a/python/examples/advanced_agents/indie_hacker_agent/langgraph/readme.md +++ b/python/examples/advanced_agents/indie_hacker_agent/langgraph/readme.md @@ -1,6 +1,6 @@ # Indie Hacker Agent Guide -This guide provides detailed steps to create an Indie Hacker Agent that leverages Composio, agentic frameworks such as Letta and OpenAI to create a complete content writing and posting pipeline. Ensure you have Python 3.8 or higher installed. +This guide provides detailed steps to create an Indie Hacker Agent that leverages Composio, agentic frameworks such as Langgraph and OpenAI to create a complete content writing and posting pipeline. Ensure you have Python 3.8 or higher installed. ## Steps to Run diff --git a/python/examples/advanced_agents/indie_hacker_agent/langgraph/requirements.txt b/python/examples/advanced_agents/indie_hacker_agent/langgraph/requirements.txt index e02185993df..0aa2f4289b0 100644 --- a/python/examples/advanced_agents/indie_hacker_agent/langgraph/requirements.txt +++ b/python/examples/advanced_agents/indie_hacker_agent/langgraph/requirements.txt @@ -1,3 +1,5 @@ composio-langgraph langgraph +langchain-groq +langchain-openai python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/indie_hacker_agent/langgraph/setup.sh b/python/examples/advanced_agents/indie_hacker_agent/langgraph/setup.sh index 0ff8854e651..abf39f58f9d 100644 --- a/python/examples/advanced_agents/indie_hacker_agent/langgraph/setup.sh +++ b/python/examples/advanced_agents/indie_hacker_agent/langgraph/setup.sh @@ -2,11 +2,11 @@ # Create a virtual environment echo "Creating virtual environment..." -python3 -m venv ~/.venvs/content_writing +python3 -m venv ~/.venvs/indie_hacker # Activate the virtual environment echo "Activating virtual environment..." -source ~/.venvs/content_writing/bin/activate +source ~/.venvs/indie_hacker/bin/activate # Install libraries from requirements.txt echo "Installing libraries from requirements.txt..." @@ -16,14 +16,6 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool - -echo "Add slackbot tool. Finish the flow" -composio add twitter -composio add linkedin -composio add firecrawl -composio add tavily - # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/advanced_agents/indie_hacker_agent/letta/.env.example b/python/examples/advanced_agents/indie_hacker_agent/letta/.env.example deleted file mode 100644 index 39bc53f1c30..00000000000 --- a/python/examples/advanced_agents/indie_hacker_agent/letta/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -OPENAI_API_KEY=YOUR_OPENAI_API_KEY -COMPOSIO_API_KEY=YOUR_COMPOSIO_API_KEY -GROQ_API_KEY=YOUR_GROQ_API_KEY -CEREBRAS_API_KEY=YOUR_CEREBRAS_API_KEY \ No newline at end of file diff --git a/python/examples/advanced_agents/indie_hacker_agent/letta/main.py b/python/examples/advanced_agents/indie_hacker_agent/letta/main.py deleted file mode 100644 index 09c8974ca4d..00000000000 --- a/python/examples/advanced_agents/indie_hacker_agent/letta/main.py +++ /dev/null @@ -1,38 +0,0 @@ -import dotenv -from composio_langchain import Action, ComposioToolSet -from letta import create_client, LLMConfig -from letta.schemas.tool import Tool - -# Load environment variables from .env -# Set your OpenAI API Key in a .env file -dotenv.load_dotenv() - - -toolset = ComposioToolSet() -tools = toolset.get_tools(actions=[ -Action.CODEINTERPRETER_EXECUTE_CODE, -Action.CODEINTERPRETER_GET_FILE_CMD, -Action.CODEINTERPRETER_RUN_TERMINAL_CMD, -Action.HACKERNEWS_GET_TODAYS_POSTS, -Action.HACKERNEWS_GET_FRONTPAGE, -Action.HACKERNEWS_GET_LATEST_POSTS, -Action.HACKERNEWS_GET_ITEM_WITH_ID, -]) -task = ( -"""You are an Indie Hacker Agent, you are supposed to research hackernews. -Find a latest post to implement, brainstorm creative ideas and implement an MVP Version of it. -The idea implementation should then be executed and shown to the user. - Also print the link to the original idea on hackernews. Please execute the code on the code interpreter.""" -) - -client = create_client() - -agent_state = client.create_agent( - name="Indie Hacker Agent", -) - -client.add_tool(tools) - -response = client.send_message(agent_id=agent_state.id, role="user", message=task) -print("Usage:", response.usage) -print("Agent messages:", response.messages) diff --git a/python/examples/advanced_agents/indie_hacker_agent/letta/readme.md b/python/examples/advanced_agents/indie_hacker_agent/letta/readme.md deleted file mode 100644 index 4b335d9909b..00000000000 --- a/python/examples/advanced_agents/indie_hacker_agent/letta/readme.md +++ /dev/null @@ -1,30 +0,0 @@ -# Indie Hacker Agent Guide - -This guide provides detailed steps to create an Indie Hacker Agent that leverages Composio, agentic frameworks such as LangGraph and Groq to create a complete content writing and posting pipeline. Ensure you have Python 3.8 or higher installed. - - -## Steps to Run - -**Navigate to the Project Directory:** -Change to the directory where the `setup.sh`, `main.py`, `requirements.txt`, and `README.md` files are located. For example: -```sh -cd path/to/project/directory -``` - -### 1. Run the Setup File -Make the setup.sh Script Executable (if necessary): -On Linux or macOS, you might need to make the setup.sh script executable: -```shell -chmod +x setup.sh -``` -Execute the setup.sh script to set up the environment and install dependencies: -```shell -./setup.sh -``` -Now, fill in the `.env` file with your secrets. - -### 2. Run the Python Script -```shell -python cookbook/python-examples/advanced_agents/indie_hacker_agent/langgraph/main.py -``` - diff --git a/python/examples/advanced_agents/indie_hacker_agent/letta/requirements.txt b/python/examples/advanced_agents/indie_hacker_agent/letta/requirements.txt deleted file mode 100644 index 2870f4d54b3..00000000000 --- a/python/examples/advanced_agents/indie_hacker_agent/letta/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -composio-letta -letta -python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/lead_generator_agent/main.py b/python/examples/advanced_agents/lead_generator_agent/main.py index a2a5326ea3a..af2b63c1eb2 100644 --- a/python/examples/advanced_agents/lead_generator_agent/main.py +++ b/python/examples/advanced_agents/lead_generator_agent/main.py @@ -25,7 +25,7 @@ ] agent = FunctionCallingAgentWorker( - tools=tools, + tools=tools, # type: ignore llm=llm, prefix_messages=prefix_messages, max_function_calls=10, diff --git a/python/examples/advanced_agents/lead_generator_agent/setup.sh b/python/examples/advanced_agents/lead_generator_agent/setup.sh index 3d42b30af2f..49e9fc941a6 100644 --- a/python/examples/advanced_agents/lead_generator_agent/setup.sh +++ b/python/examples/advanced_agents/lead_generator_agent/setup.sh @@ -21,6 +21,9 @@ else touch .env fi +echo "Authenticating with Composio..." +composio add peopledatalabs +composio add googlesheets # Prompt the user to enter the OPENAI_API_KEY read -p "Enter your OPENAI_API_KEY: " OPENAI_API_KEY diff --git a/python/examples/advanced_agents/lead_outreach_agent/crewai/main.py b/python/examples/advanced_agents/lead_outreach_agent/crewai/main.py index 32c3ff4de17..269f77c866f 100644 --- a/python/examples/advanced_agents/lead_outreach_agent/crewai/main.py +++ b/python/examples/advanced_agents/lead_outreach_agent/crewai/main.py @@ -14,18 +14,15 @@ role="Lead Outreach Agent", goal="Given the information, draft the perfect lead outreach email. You are ", verbose=True, - memory=True, backstory="You are an expert in crafting perfect lead outreach emails.", - allow_delegation=False, - tools=tools, + tools=tools, # type: ignore ) execute_code_task = Task( description=f"Use Hubspot, Read the names in the CRM by using listing contacts actions using every Hubspot action necessary and draft the perfect lead outreach email. Please pass in the correct params for the action", expected_output="Draft of a lead outreach email was created and also mention the email id of the lead", - tools=tools, + tools=tools, # type: ignore agent=python_executor_agent, - allow_delegation=False, ) crew = Crew( @@ -37,29 +34,29 @@ class LeadOutreach(Flow): model='gpt-4o' @start() - def draft(self): - result = crew.kickoff() + async def draft(self): + result = await crew.kickoff_async() return result.raw @listen(draft) - def create_gmail_draft(self, message): + async def create_gmail_draft(self, message): print("Creating draft") res = toolset.execute_action( Action.GMAIL_CREATE_EMAIL_DRAFT, params={}, - text= message - ) + text=message + ) # type: ignore return res @listen(and_(draft, create_gmail_draft)) - def done(self): + async def done(self): print('done') return "Action Done" async def main(): flow = LeadOutreach() flow.plot('my_flow_plot') - await flow.kickoff() + return await flow.kickoff_async() if __name__ == "__main__": asyncio.run(main()) \ No newline at end of file diff --git a/python/examples/advanced_agents/lead_outreach_agent/llamaindex/main.py b/python/examples/advanced_agents/lead_outreach_agent/llamaindex/main.py index e76f1dfc2ec..7000f831e81 100644 --- a/python/examples/advanced_agents/lead_outreach_agent/llamaindex/main.py +++ b/python/examples/advanced_agents/lead_outreach_agent/llamaindex/main.py @@ -1,74 +1,36 @@ -import gradio as gr from composio_llamaindex import ComposioToolSet, App, Action from llama_index.core.agent import FunctionCallingAgentWorker from llama_index.core.llms import ChatMessage from llama_index.llms.openai import OpenAI from dotenv import load_dotenv -# Load environment variables load_dotenv() +toolset = ComposioToolSet(api_key="") +tools = toolset.get_tools(actions=[Action.HUBSPOT_LIST_CONTACTS_PAGE, Action.GMAIL_CREATE_EMAIL_DRAFT]) -# Initialize tools and language model -toolset = ComposioToolSet() -tools = toolset.get_tools(apps=[App.WEBTOOL, App.EXA]) llm = OpenAI(model="gpt-4o") + prefix_messages = [ ChatMessage( role="system", content=( - "You are a Lead Outreach Agent that is equipped with great tools for research " + f""" + "You are a Lead Outreach Agent that is has access to the CRM through HubSpot." "and is an expert writer. Your job is to first research some info about the lead " "given to you and then draft a perfect ideal email for whatever input task is given to you. " - "Always write the subject, content of the email and nothing else." - ) + """ + ), ) ] agent = FunctionCallingAgentWorker( - tools=tools, + tools=tools, # type: ignore llm=llm, prefix_messages=prefix_messages, max_function_calls=10, allow_parallel_tool_calls=False, - verbose=True + verbose=True, ).as_agent() -# Function to generate email -def generate_email(lead, email_id, purpose): - response = agent.chat(f"These are the lead details that we know {lead}. This is the purpose to write the email: {purpose}. Write a well written email for the purpose to the lead.") - - # Collecting final response - final_response = response.response - - return final_response - -def send_email(email_content, email_id): - t = email_content+"This is the email id:"+email_id - from composio import ComposioToolSet - composio_toolset = ComposioToolSet() - composio_toolset.execute_action( - "gmail_send_email", - params={}, - text=str(t), - ) - return "Email sent" -# Setting up Gradio interface -with gr.Blocks() as demo: - gr.Markdown("### Lead Outreach Email Generator") - - lead_input = gr.Textbox(label="Lead Details", placeholder="Enter lead details here...") - email_input = gr.Textbox(label="Email ID", placeholder="Enter recipient's email here...") - purpose_input = gr.Textbox(label="Purpose and your details", placeholder="Enter purpose of the email, dont forget to mention your name in it...") - - submit_button = gr.Button("Generate Email") - send_button = gr.Button("Send Email") - output_message = gr.Textbox(label="Was the email sent?", placeholder="not sent") - - output_email = gr.Textbox(label="Generated Email", interactive=False) - - submit_button.click(generate_email, inputs=[lead_input, email_input, purpose_input], outputs=output_email) - send_button.click(send_email, inputs = [output_email, email_input], outputs= output_message) - - -# Launching the Gradio app -demo.launch() \ No newline at end of file +user_input = f"Draft an email for each lead in my Hubspot contacts page introducing yourself and asking them if they're interested in integrating AI Agents in their workflow." +response = agent.chat(user_input) \ No newline at end of file diff --git a/python/examples/advanced_agents/lead_outreach_agent/llamaindex/requirements.txt b/python/examples/advanced_agents/lead_outreach_agent/llamaindex/requirements.txt index e034e97f91a..a6f7c578a77 100644 --- a/python/examples/advanced_agents/lead_outreach_agent/llamaindex/requirements.txt +++ b/python/examples/advanced_agents/lead_outreach_agent/llamaindex/requirements.txt @@ -1,2 +1,3 @@ composio-llamaindex -gradio \ No newline at end of file +gradio +python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/lead_outreach_agent/llamaindex/setup.sh b/python/examples/advanced_agents/lead_outreach_agent/llamaindex/setup.sh index 242ffa197dd..ccf7dea4ff5 100644 --- a/python/examples/advanced_agents/lead_outreach_agent/llamaindex/setup.sh +++ b/python/examples/advanced_agents/lead_outreach_agent/llamaindex/setup.sh @@ -21,6 +21,7 @@ else touch .env fi +composio add exa # Prompt the user to enter the OPENAI_API_KEY read -p "Enter your OPENAI_API_KEY: " OPENAI_API_KEY diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/README.md b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/README.md index bd8f6266a2f..2ce439ef9ca 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/README.md +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/README.md @@ -24,5 +24,5 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/main.py +python cookbook/python-examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/main.py ``` diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/main.py b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/main.py index 24e28a3145f..0a0d1a8ece4 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/main.py +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/main.py @@ -8,8 +8,6 @@ from composio_autogen import Action, App, ComposioToolSet from datetime import datetime -from python.composio.cli import apps - # Load environment variables from a .env file dotenv.load_dotenv() diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/setup.sh b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/setup.sh index df31419c00f..a4bdd339a27 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/setup.sh +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_autogen/setup.sh @@ -12,6 +12,7 @@ source newsletter_summarizer/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add gmail # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/README.md b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/README.md index ad3a222908d..4adc4a58a18 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/README.md +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/README.md @@ -24,5 +24,5 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/main.py +python cookbook/python-examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/main.py ``` diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/main.py b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/main.py index 574e32c9632..5b902220a43 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/main.py +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/main.py @@ -27,11 +27,10 @@ role="Email Fetcher Agent", goal="Fetch recent newsletter emails from the inbox. Please look for labels 'newsletter' only for last 7 days. Don't add any other unnecessary filters.", verbose=True, - memory=True, backstory=f"You are an expert in retrieving and organizing email content, with a keen eye for identifying relevant newsletters. Today's date is {datetime.now().strftime('%B %d, %Y')}. You are writing an email to a reader who is interested in the stock market and trading.", llm=llm, allow_delegation=False, - tools=gmail_tools, + tools=gmail_tools, # type: ignore ) # Define the Summarizer Agent @@ -39,7 +38,6 @@ role="Summarizer Agent", goal="Summarize the content of newsletter emails, highlighting key information and trends", verbose=True, - memory=True, backstory=f"You are an expert in analyzing and summarizing complex information, with a talent for distilling essential points from various sources. Today's date is {datetime.now().strftime('%B %d, %Y')}. You are writing an email to a reader who is interested in the stock market and trading. You are writing an email to a reader who is interested in the stock market and trading.", llm=llm, allow_delegation=False, @@ -51,11 +49,10 @@ role="Email Sender Agent", goal="Send the summarized newsletter content via email to investtradegame@gmail.com with a professional and engaging format", verbose=True, - memory=True, backstory=f"You are an expert in composing and sending emails with well-formatted, visually appealing content. You have a knack for creating engaging subject lines and structuring information for easy readability. Today's date is {datetime.now().strftime('%B %d, %Y')}. You are writing an email to a reader who is interested in the stock market and trading.", llm=llm, allow_delegation=False, - tools=gmail_tools, + tools=gmail_tools, # type: ignore ) # Define the task for fetching emails @@ -67,7 +64,7 @@ "Pay special attention to newsletters from reputable sources and industry leaders." ), expected_output="A detailed list of recent newsletter emails with their content, including any relevant links or attachments", - tools=gmail_tools, + tools=gmail_tools, # type: ignore agent=email_fetcher_agent, ) @@ -113,7 +110,7 @@ "Important: Ensure all HTML tags are properly closed and nested correctly." ), expected_output="Confirmation that the well-formatted, detailed summary email with important links has been sent to investtradegame@gmail.com", - tools=gmail_tools, + tools=gmail_tools, # type: ignore agent=email_sender_agent, context=[summarize_emails_task], ) diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/setup.sh b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/setup.sh index 822920414b1..bd5145db1c1 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/setup.sh +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_crewai/setup.sh @@ -12,6 +12,7 @@ source newsletter_summarizer/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add gmail # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/main.py b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/main.py index 7f3f51513b5..20771b12f88 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/main.py +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/main.py @@ -40,7 +40,7 @@ ] agent = FunctionCallingAgentWorker( - tools=gmail_tools, # Tools available for the agent to use + tools=gmail_tools, # Tools available for the agent to use # type: ignore llm=llm, # Language model for processing requests prefix_messages=prefix_messages, # Initial system messages for context max_function_calls=10, # Maximum number of function calls allowed diff --git a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/setup.sh b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/setup.sh index 822920414b1..bd5145db1c1 100644 --- a/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/setup.sh +++ b/python/examples/advanced_agents/newsletter_summarizer/newsletter_summarizer_llamaindex/setup.sh @@ -12,6 +12,7 @@ source newsletter_summarizer/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add gmail # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_autogen/main.py b/python/examples/advanced_agents/pr_agent/pr_agent_autogen/main.py index 917976a1d8d..61a20ec7190 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_autogen/main.py +++ b/python/examples/advanced_agents/pr_agent/pr_agent_autogen/main.py @@ -51,12 +51,12 @@ # Creating a ComposioToolSet instance for handling actions composio_toolset = ComposioToolSet() -composio_toolset.register_actions( +composio_toolset.register_tools( actions=[ - Action.GITHUB_GET_CODE_CHANGES_IN_PR, - Action.GITHUB_PULLS_CREATE_REVIEW_COMMENT, + Action.GITHUB_GET_A_PULL_REQUEST, + Action.GITHUB_CREATE_A_REVIEW_FOR_A_PULL_REQUEST, Action.GITHUB_CREATE_AN_ISSUE, - Action.SLACKBOT_CHAT_POST_MESSAGE, + Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, ], caller=chatbot, executor=user_proxy, diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_autogen/setup.sh b/python/examples/advanced_agents/pr_agent/pr_agent_autogen/setup.sh index bbbeb250d61..519d42c8606 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_autogen/setup.sh +++ b/python/examples/advanced_agents/pr_agent/pr_agent_autogen/setup.sh @@ -16,15 +16,12 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add github tool. Finish the flow" composio add github -echo "Add slackbot tool. Finish the flow" -composio add slackbot - -echo "Updating apps" -composio apps update +echo "Add slack tool. Finish the flow" +composio add slack echo "Enable trigger for github" composio triggers enable github_pull_request_event diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_crewai/main.py b/python/examples/advanced_agents/pr_agent/pr_agent_crewai/main.py index bd6e69552a5..dfb82047415 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_crewai/main.py +++ b/python/examples/advanced_agents/pr_agent/pr_agent_crewai/main.py @@ -14,12 +14,12 @@ # Define the tools -pr_agent_tools = composio_toolset.get_actions( +pr_agent_tools = composio_toolset.get_tools( actions=[ - Action.GITHUB_GET_CODE_CHANGES_IN_PR, - Action.GITHUB_PULLS_CREATE_REVIEW_COMMENT, - Action.GITHUB_ISSUES_CREATE, - Action.SLACKBOT_CHAT_POST_MESSAGE, + Action.GITHUB_GET_A_PULL_REQUEST, + Action.GITHUB_CREATE_A_REVIEW_FOR_A_PULL_REQUEST, + Action.GITHUB_CREATE_AN_ISSUE, + Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, ] ) @@ -65,13 +65,14 @@ def review_code_task(code_to_review): return Task( description=f"Review the following code changes and provide feedback: {code_to_review}", + expected_output="A detailed review of the code changes, including any issues, suggestions, and a summary of the changes.", agent=code_reviewer, ) # Create the crew code_review_crew = Crew( - agents=[code_reviewer], tasks=[], verbose=2, process=Process.sequential + agents=[code_reviewer], tasks=[], verbose=True, process=Process.sequential ) print("Assistant is ready") @@ -97,4 +98,4 @@ def review_new_pr(event: TriggerEventData) -> None: print("Listener started!") print("Create a pr to get the review") -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_crewai/setup.sh b/python/examples/advanced_agents/pr_agent/pr_agent_crewai/setup.sh index bbbeb250d61..620d7bc0baa 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_crewai/setup.sh +++ b/python/examples/advanced_agents/pr_agent/pr_agent_crewai/setup.sh @@ -16,12 +16,12 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add github tool. Finish the flow" composio add github -echo "Add slackbot tool. Finish the flow" -composio add slackbot +echo "Add slack tool. Finish the flow" +composio add slack echo "Updating apps" composio apps update diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_langchain/main.py b/python/examples/advanced_agents/pr_agent/pr_agent_langchain/main.py index 24788b325db..f99a6270312 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_langchain/main.py +++ b/python/examples/advanced_agents/pr_agent/pr_agent_langchain/main.py @@ -36,10 +36,10 @@ # Define the tools pr_agent_tools = composio_toolset.get_tools( actions=[ - Action.GITHUB_GET_CODE_CHANGES_IN_PR, - Action.GITHUB_PULLS_CREATE_REVIEW_COMMENT, + Action.GITHUB_GET_A_PULL_REQUEST, + Action.GITHUB_CREATE_A_REVIEW_FOR_A_PULL_REQUEST, Action.GITHUB_CREATE_AN_ISSUE, - Action.SLACKBOT_CHAT_POST_MESSAGE, + Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, ] ) diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_langchain/setup.sh b/python/examples/advanced_agents/pr_agent/pr_agent_langchain/setup.sh index bbbeb250d61..e63fd5f062c 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_langchain/setup.sh +++ b/python/examples/advanced_agents/pr_agent/pr_agent_langchain/setup.sh @@ -16,15 +16,13 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add github tool. Finish the flow" composio add github -echo "Add slackbot tool. Finish the flow" -composio add slackbot +echo "Add slack tool. Finish the flow" +composio add slack -echo "Updating apps" -composio apps update echo "Enable trigger for github" composio triggers enable github_pull_request_event diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/main.py b/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/main.py index 26485f66371..6ebdd87c3ac 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/main.py +++ b/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/main.py @@ -61,7 +61,7 @@ # Initialize a FunctionCallingAgentWorker with the tools, LLM, and system messages agent = FunctionCallingAgentWorker( - tools=tools, # Tools available for the agent to use + tools=tools, # Tools available for the agent to use # type: ignore llm=llm, # Language model for processing requests prefix_messages=prefix_messages, # Initial system messages for context max_function_calls=10, # Maximum number of function calls allowed @@ -73,10 +73,10 @@ # Define the tools pr_agent_tools = composio_toolset.get_tools( actions=[ - Action.GITHUB_GET_CODE_CHANGES_IN_PR, - Action.GITHUB_PULLS_CREATE_REVIEW_COMMENT, + Action.GITHUB_GET_A_PULL_REQUEST, + Action.GITHUB_CREATE_A_REVIEW_FOR_A_PULL_REQUEST, Action.GITHUB_CREATE_AN_ISSUE, - Action.SLACKBOT_CHAT_POST_MESSAGE, + Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, ] ) @@ -94,4 +94,4 @@ def review_new_pr(event: TriggerEventData) -> None: print("Listener started!") print("Create a pr to get the review") -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/requirements.txt b/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/requirements.txt index 0b0cc89f78c..8bbca3e841e 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/requirements.txt +++ b/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/requirements.txt @@ -1,2 +1,3 @@ composio-llamaindex -llama-index \ No newline at end of file +llama-index +python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/setup.sh b/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/setup.sh index bbbeb250d61..519d42c8606 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/setup.sh +++ b/python/examples/advanced_agents/pr_agent/pr_agent_llama_index/setup.sh @@ -16,15 +16,12 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add github tool. Finish the flow" composio add github -echo "Add slackbot tool. Finish the flow" -composio add slackbot - -echo "Updating apps" -composio apps update +echo "Add slack tool. Finish the flow" +composio add slack echo "Enable trigger for github" composio triggers enable github_pull_request_event diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_openai/main.py b/python/examples/advanced_agents/pr_agent/pr_agent_openai/main.py index 6e1e8b6d9ad..116331c272a 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_openai/main.py +++ b/python/examples/advanced_agents/pr_agent/pr_agent_openai/main.py @@ -32,10 +32,10 @@ composio_toolset = ComposioToolSet() pr_agent_tools = composio_toolset.get_tools( actions=[ - Action.GITHUB_GET_CODE_CHANGES_IN_PR, # For a given PR it get's all the changes - Action.GITHUB_PULLS_CREATE_REVIEW_COMMENT, # For a given PR it creates a comment - Action.GITHUB_CREATE_AN_ISSUE, # If required, allows you to create issues on github - Action.SLACKBOT_CHAT_POST_MESSAGE, # Send a message to slack using app + Action.GITHUB_GET_A_PULL_REQUEST, + Action.GITHUB_CREATE_A_REVIEW_FOR_A_PULL_REQUEST, + Action.GITHUB_CREATE_AN_ISSUE, + Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, ] ) @@ -82,4 +82,4 @@ def review_new_pr(event: TriggerEventData) -> None: print("Listener started!") print("Create a pr to get the review") -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_openai/requirements.txt b/python/examples/advanced_agents/pr_agent/pr_agent_openai/requirements.txt index 10869f76803..dfa0dbef75f 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_openai/requirements.txt +++ b/python/examples/advanced_agents/pr_agent/pr_agent_openai/requirements.txt @@ -1,2 +1,3 @@ composio-openai openai +python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/pr_agent/pr_agent_openai/setup.sh b/python/examples/advanced_agents/pr_agent/pr_agent_openai/setup.sh index 9db0efc04e2..a7be3760214 100644 --- a/python/examples/advanced_agents/pr_agent/pr_agent_openai/setup.sh +++ b/python/examples/advanced_agents/pr_agent/pr_agent_openai/setup.sh @@ -16,15 +16,11 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool echo "Add github tool. Finish the flow" composio add github -echo "Updating apps" -composio apps update - -echo "Add slackbot tool. Finish the flow" -composio add slackbot +echo "Add slack tool. Finish the flow" +composio add slack echo "Enable trigger for github" composio triggers enable github_pull_request_event diff --git a/python/examples/advanced_agents/recruiter_agent/main.py b/python/examples/advanced_agents/recruiter_agent/main.py index 81fb377f027..543599bcfa2 100644 --- a/python/examples/advanced_agents/recruiter_agent/main.py +++ b/python/examples/advanced_agents/recruiter_agent/main.py @@ -8,8 +8,8 @@ load_dotenv() -import agentops -agentops.init(os.getenv("AGENTOPS_API_KEY")) +# import agentops +# agentops.init(os.getenv("AGENTOPS_API_KEY")) toolset = ComposioToolSet(api_key=os.getenv("COMPOSIO_API_KEY")) @@ -33,7 +33,7 @@ ] agent = FunctionCallingAgentWorker( - tools=tools, + tools=tools, # type: ignore llm=llm, prefix_messages=prefix_messages, max_function_calls=10, diff --git a/python/examples/advanced_agents/recruiter_agent/requirements.txt b/python/examples/advanced_agents/recruiter_agent/requirements.txt index e034e97f91a..7d37729dec9 100644 --- a/python/examples/advanced_agents/recruiter_agent/requirements.txt +++ b/python/examples/advanced_agents/recruiter_agent/requirements.txt @@ -1,2 +1,6 @@ composio-llamaindex +agentops +llama-index-llms-groq +llama-index-llms-openai +python-dotenv gradio \ No newline at end of file diff --git a/python/examples/advanced_agents/recruiter_agent/setup.sh b/python/examples/advanced_agents/recruiter_agent/setup.sh index 0a7625f08b8..8e09596a89c 100644 --- a/python/examples/advanced_agents/recruiter_agent/setup.sh +++ b/python/examples/advanced_agents/recruiter_agent/setup.sh @@ -12,6 +12,8 @@ source recruiter/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add peopledatalabs +composio add googlesheets # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/main.py b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/main.py index 7caa7a0e023..0a0f9745646 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/main.py +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/main.py @@ -3,7 +3,7 @@ import re from dotenv import load_dotenv from autogen.agentchat import AssistantAgent, UserProxyAgent -from composio_autogen import Action, App, ComposioToolSet +from composio_autogen import Action, App, ComposioToolSet, Trigger from composio.client.collections import TriggerEventData from datetime import datetime from typing import Optional, Any @@ -38,25 +38,11 @@ human_input_mode="NEVER", code_execution_config={"use_docker": False}, ) -def extract_sender_email(payload): - delivered_to_header_found = False - for header in payload["headers"]: - if header.get("name", "") == "Delivered-To" and header.get("value", "") != "": - delivered_to_header_found = True - print("delivered_to_header_found: ", delivered_to_header_found) - if not delivered_to_header_found: - return None - for header in payload["headers"]: - if header["name"] == "From": - # Regular expression to extract email from the 'From' header value - match = re.search(r"[\w\.-]+@[\w\.-]+", header["value"]) - if match: - return match.group(0) - return None - # Creating a ComposioToolSet instance for handling actions composio_toolset = ComposioToolSet() -schedule_tool = composio_toolset.register_actions( +schedule_tool = composio_toolset.register_tools( + caller=chatbot, + executor=user_proxy, actions=[ Action.GOOGLECALENDAR_FIND_FREE_SLOTS, Action.GOOGLECALENDAR_CREATE_EVENT, @@ -70,7 +56,7 @@ def extract_sender_email(payload): listener = composio_toolset.create_trigger_listener() -@listener.callback(filters={"trigger_name": "gmail_new_gmail_message"}) +@listener.callback(filters={"trigger_name": Trigger.GMAIL_NEW_GMAIL_MESSAGE}) def callback_new_message(event: TriggerEventData) -> None: print("here in the function") payload = event.payload @@ -101,4 +87,4 @@ def callback_new_message(event: TriggerEventData) -> None: print("Subscription created!") -listener.listen() +listener.wait_forever() \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/readme.md b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/readme.md index 3420359103e..d700f91b674 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/readme.md +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/readme.md @@ -24,5 +24,5 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/scheduler_agent/main.py +python python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/main.py ``` \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/requirements.txt b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/requirements.txt index eb1fd5854bb..48d96e78f14 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/requirements.txt +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/requirements.txt @@ -1,3 +1,4 @@ composio-autogen autogen -langchain-openai \ No newline at end of file +langchain-openai +python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/setup.sh b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/setup.sh index b58a330bb53..4a1c1b2bfa5 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/setup.sh +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_autogen/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add google calendar and gmail tool. Finish the flow" composio add googlecalendar composio add gmail diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/main.py b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/main.py index 1a7f9e4c6f0..91126573341 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/main.py +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/main.py @@ -32,28 +32,11 @@ Pass empty config ("config": {{}}) for the function calls, if you get an error about not passing config.""", verbose=True, llm=llm, - tools=schedule_tool, + tools=schedule_tool, # type: ignore allow_delegation=False, ) -def extract_sender_email(payload): - delivered_to_header_found = False - for header in payload["headers"]: - if header.get("name", "") == "Delivered-To" and header.get("value", "") != "": - delivered_to_header_found = True - print("delivered_to_header_found: ", delivered_to_header_found) - if not delivered_to_header_found: - return None - for header in payload["headers"]: - if header["name"] == "From": - # Regular expression to extract email from the 'From' header value - match = re.search(r"[\w\.-]+@[\w\.-]+", header["value"]) - if match: - return match.group(0) - return None - - listener = composio_toolset.create_trigger_listener() @@ -90,19 +73,19 @@ def callback_new_message(event: TriggerEventData) -> None: should describe what the meeting is about""", expected_output="emails was drafted", agent=email_assistant, - tools=[email_tool], + tools=email_tool, # type: ignore context=[analyze_email_task], ) email_processing_crew = Crew( agents=[email_assistant], tasks=[analyze_email_task, draft_email_task], - verbose=1, + verbose=True, process=Process.sequential, ) result = email_processing_crew.kickoff() - return result + return result.raw # type: ignore print("Subscription created!") -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/readme.md b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/readme.md index c067fb7e591..31500b2bea8 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/readme.md +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/readme.md @@ -24,7 +24,7 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/scheduler_agent/main.py +python python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/main.py ``` diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/requirements.txt b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/requirements.txt index 1b3712748e4..2e57d9def27 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/requirements.txt +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/requirements.txt @@ -1,3 +1,4 @@ composio-crewai crewai -langchain-openai \ No newline at end of file +langchain-openai +python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/setup.sh b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/setup.sh index b58a330bb53..4a1c1b2bfa5 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/setup.sh +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_crewai/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool + echo "Add google calendar and gmail tool. Finish the flow" composio add googlecalendar composio add gmail diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/main.py b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/main.py index 253592c23b5..76e80777826 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/main.py +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/main.py @@ -18,14 +18,14 @@ composio_toolset = ComposioToolSet() -schedule_tool = composio_toolset.get_actions( +schedule_tool = composio_toolset.get_tools( actions=[ Action.GOOGLECALENDAR_FIND_FREE_SLOTS, Action.GOOGLECALENDAR_CREATE_EVENT, Action.GMAIL_CREATE_EMAIL_DRAFT, ] ) -email_tool = composio_toolset.get_actions(actions=[Action.GMAIL_CREATE_EMAIL_DRAFT]) +email_tool = composio_toolset.get_tools(actions=[Action.GMAIL_CREATE_EMAIL_DRAFT]) date_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") timezone = datetime.now().astimezone().tzinfo @@ -85,4 +85,4 @@ def callback_new_message(event: TriggerEventData) -> None: print("Subscription created!") -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/readme.md b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/readme.md index c067fb7e591..3cedc8cfc47 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/readme.md +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/readme.md @@ -24,7 +24,7 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/scheduler_agent/main.py +python python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/main.py ``` diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/requirements.txt b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/requirements.txt index 4c742351d33..cd5930b50ec 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/requirements.txt +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/requirements.txt @@ -1,3 +1,5 @@ composio-langchain langchain -langchain-openai \ No newline at end of file +langchain-openai +python-dotenv +agentops \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/setup.sh b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/setup.sh index b58a330bb53..c0ee4ca8c49 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/setup.sh +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langchain/setup.sh @@ -16,7 +16,6 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool echo "Add google calendar and gmail tool. Finish the flow" composio add googlecalendar composio add gmail diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/main.py b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/main.py index 4e048847965..aaed267afe3 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/main.py +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/main.py @@ -27,13 +27,13 @@ llm = ChatOpenAI(model="gpt-4-turbo") composio_toolset = ComposioToolSet() -schedule_tools = composio_toolset.get_actions( +schedule_tools = composio_toolset.get_tools( actions=[ Action.GOOGLECALENDAR_FIND_FREE_SLOTS, Action.GOOGLECALENDAR_CREATE_EVENT, ] ) -email_tools = composio_toolset.get_actions(actions=[Action.GMAIL_CREATE_EMAIL_DRAFT]) +email_tools = composio_toolset.get_tools(actions=[Action.GMAIL_CREATE_EMAIL_DRAFT]) tools = [*schedule_tools, *email_tools] tool_node = ToolNode(tools) @@ -129,16 +129,6 @@ def router(state) -> Literal["call_tool", "__end__", "continue"]: app = workflow.compile() -def extract_sender_email(payload): - if not any(header.get("name") == "Delivered-To" and header.get("value") for header in payload["headers"]): - return None - - for header in payload["headers"]: - if header["name"] == "From": - match = re.search(r"[\w\.-]+@[\w\.-]+", header["value"]) - return match.group(0) if match else None - return None - def process_email(email_sender, email_content, thread_id): final_state = app.invoke({ "messages": [ @@ -171,4 +161,5 @@ def callback_new_message(event: TriggerEventData) -> None: output = process_email(email_sender, email_content, thread_id) print("Final output:", output) -listener.listen() \ No newline at end of file +print("Starting listener") +listener.wait_forever() \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/readme.md b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/readme.md index 0f4456f3ef0..56ae16225e4 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/readme.md +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/readme.md @@ -27,5 +27,5 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/scheduler_agent/scheduler_agent_langgraph/main.py -``` \ No newline at end of file +python python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/main.py +``` diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/setup.sh b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/setup.sh index b58a330bb53..c0ee4ca8c49 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/setup.sh +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_langgraph/setup.sh @@ -16,7 +16,6 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool echo "Add google calendar and gmail tool. Finish the flow" composio add googlecalendar composio add gmail diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/main.py b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/main.py index d62e84fc26e..1349b88983b 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/main.py +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/main.py @@ -5,7 +5,7 @@ # Import modules from Composio and LlamaIndex import re from datetime import datetime -from composio_llamaindex import App, ComposioToolSet, Action +from composio_llamaindex import App, ComposioToolSet, Action, Trigger from llama_index.core.agent import FunctionCallingAgentWorker from llama_index.core.llms import ChatMessage from llama_index.llms.openai import OpenAI @@ -34,25 +34,9 @@ date_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") timezone = datetime.now().astimezone().tzinfo -def extract_sender_email(payload): - delivered_to_header_found = False - for header in payload["headers"]: - if header.get("name", "") == "Delivered-To" and header.get("value", "") != "": - delivered_to_header_found = True - print("delivered_to_header_found: ", delivered_to_header_found) - if not delivered_to_header_found: - return None - for header in payload["headers"]: - if header["name"] == "From": - # Regular expression to extract email from the 'From' header value - match = re.search(r"[\w\.-]+@[\w\.-]+", header["value"]) - if match: - return match.group(0) - return None - # Create a trigger listener listener = composio_toolset.create_trigger_listener() -@listener.callback(filters={"trigger_name": "GMAIL_NEW_GMAIL_MESSAGE"}) +@listener.callback(filters={"trigger_name": Trigger.GMAIL_NEW_GMAIL_MESSAGE}) def callback_new_message(event: TriggerEventData) -> None: # Using the information from Trigger, execute the agent print("here in the function") @@ -81,7 +65,7 @@ def callback_new_message(event: TriggerEventData) -> None: ) ] agent = FunctionCallingAgentWorker( - tools=schedule_tool, # Tools available for the agent to use + tools=schedule_tool, # Tools available for the agent to use # type: ignore llm=llm, # Language model for processing requests prefix_messages=prefix_messages, # Initial system messages for context max_function_calls=10, # Maximum number of function calls allowed @@ -107,4 +91,4 @@ def callback_new_message(event: TriggerEventData) -> None: print("Listener started!") print("Waiting for email") -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/readme.md b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/readme.md index e047a68b153..bd76b37a3bc 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/readme.md +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/readme.md @@ -24,7 +24,7 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/scheduler_agent/main.py +python python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/main.py ``` diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/requirements.txt b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/requirements.txt index f91f9a662e0..68360a929f5 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/requirements.txt +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/requirements.txt @@ -2,3 +2,5 @@ composio-llamaindex python-dotenv llama-index-llms-openai llama-index +agentops +llama-index-llms-groq \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/setup.sh b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/setup.sh index b58a330bb53..c0ee4ca8c49 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/setup.sh +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_llamaindex/setup.sh @@ -16,7 +16,6 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool echo "Add google calendar and gmail tool. Finish the flow" composio add googlecalendar composio add gmail diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/main.py b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/main.py index f28ea7b7896..336d47d6ce2 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/main.py +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/main.py @@ -9,13 +9,13 @@ # Initialize Composio tools composio_toolset = ComposioToolSet() -schedule_tool = composio_toolset.get_actions( +schedule_tool = composio_toolset.get_tools( actions=[ Action.GOOGLECALENDAR_FIND_FREE_SLOTS, Action.GOOGLECALENDAR_CREATE_EVENT, ] ) -email_tool = composio_toolset.get_actions(actions=[Action.GMAIL_CREATE_EMAIL_DRAFT]) +email_tool = composio_toolset.get_tools(actions=[Action.GMAIL_CREATE_EMAIL_DRAFT]) date_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") timezone = datetime.now().astimezone().tzinfo @@ -29,18 +29,9 @@ Current DateTime: {date_time}. All the conversations happen in {timezone} timezone. Pass empty config ("config": {{}}) for the function calls, if you get an error about not passing config.""", run_id="", - tools=schedule_tool + tools=schedule_tool # type: ignore ) -def extract_sender_email(payload): - for header in payload["payload"]["headers"]: - if header["name"] == "From": - match = re.search(r"[\w\.-]+@[\w\.-]+", header["value"]) - if match: - return match.group(0) - return None - - listener = composio_toolset.create_trigger_listener() @listener.callback(filters={"trigger_name": "gmail_new_gmail_message"}) @@ -72,4 +63,4 @@ def callback_new_message(event: TriggerEventData) -> None: if __name__ == "__main__": print("Subscription created!") - listener.listen() \ No newline at end of file + listener.wait_forever() \ No newline at end of file diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/readme.md b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/readme.md index 9172e4c668b..81a80c7d71d 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/readme.md +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/readme.md @@ -24,7 +24,7 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/scheduler_agent/main.py +python python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/main.py ``` diff --git a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/setup.sh b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/setup.sh index b58a330bb53..c0ee4ca8c49 100644 --- a/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/setup.sh +++ b/python/examples/advanced_agents/scheduler_agent/scheduler_agent_phidata/setup.sh @@ -16,7 +16,6 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool echo "Add google calendar and gmail tool. Finish the flow" composio add googlecalendar composio add gmail diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/readme.md b/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/readme.md index f7dbab2a07a..9bec3c4e877 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/readme.md +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/readme.md @@ -38,6 +38,6 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/slack_agent_autogen/slack_agent_autogen.py +python python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/slack_agent_autogen.py ``` diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/setup.sh b/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/setup.sh index 2458e08c994..db50d3c1ae0 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/setup.sh +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/setup.sh @@ -16,14 +16,14 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +echo "Add slack tool. Finish the flow" +composio add slack + +echo "Enable Slack triggers" +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/slack_agent_autogen.py b/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/slack_agent_autogen.py index 054b0dcefb3..be49eff2237 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/slack_agent_autogen.py +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_autogen/slack_agent_autogen.py @@ -1,4 +1,5 @@ # Import necessary libraries +import json import os from dotenv import load_dotenv from autogen.agentchat import AssistantAgent, UserProxyAgent @@ -50,7 +51,7 @@ composio_toolset = ComposioToolSet() composio_toolset.register_tools( - tools=[App.CODEINTERPRETER, App.EXA, App.FIRECRAWL, App.TAVILY], + apps=[App.CODEINTERPRETER, App.EXA, App.FIRECRAWL, App.TAVILY], caller=chatbot, executor=user_proxy, ) @@ -68,7 +69,7 @@ def callback_new_message(event: TriggerEventData) -> None: # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") @@ -77,7 +78,7 @@ def callback_new_message(event: TriggerEventData) -> None: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") return ( f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" - ) + ) # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -98,4 +99,4 @@ def callback_new_message(event: TriggerEventData) -> None: ) -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/readme.md b/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/readme.md index aeec90ed972..cc4d54782dc 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/readme.md +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/readme.md @@ -38,6 +38,6 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/slack_agent_crewai/slack_agent_crewai.py +python python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/slack_agent_crewai.py ``` diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/setup.sh b/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/setup.sh index 2458e08c994..db50d3c1ae0 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/setup.sh +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/setup.sh @@ -16,14 +16,14 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +echo "Add slack tool. Finish the flow" +composio add slack + +echo "Enable Slack triggers" +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/slack_agent_crewai.py b/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/slack_agent_crewai.py index a5bfb92b008..4beb4da2ebe 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/slack_agent_crewai.py +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_crewai/slack_agent_crewai.py @@ -1,5 +1,6 @@ # Import necessary libraries import os +from re import T from dotenv import load_dotenv from composio_crewai import Action, App, ComposioToolSet from crewai import Agent, Crew, Task @@ -41,7 +42,7 @@ goal="Assist users by answering questions and performing tasks using integrated tools", backstory=("As an AI assistant, I am equipped with a suite of tools to help users"), verbose=True, - tools=composio_tools, + tools=composio_tools, # type: ignore llm=llm, ) @@ -51,7 +52,7 @@ expected_output="Confirmation of the completed action or a well-informed response", ) -crew = Crew(agents=[crewai_agent], tasks=[task], verbose=2) +crew = Crew(agents=[crewai_agent], tasks=[task], verbose=True) # Callback function for handling new messages in a Slack channel @@ -63,7 +64,7 @@ def callback_new_message(event: TriggerEventData) -> None: # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") @@ -72,7 +73,7 @@ def callback_new_message(event: TriggerEventData) -> None: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") return ( f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" - ) + ) # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -91,4 +92,4 @@ def callback_new_message(event: TriggerEventData) -> None: ) -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/readme.md b/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/readme.md index f397fceb053..7cc8364bc15 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/readme.md +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/readme.md @@ -38,6 +38,6 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/slack_agent_langchain/slack_agent_langchain.py +python python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/slack_agent_langchain.py ``` diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/setup.sh b/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/setup.sh index 2458e08c994..db50d3c1ae0 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/setup.sh +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/setup.sh @@ -16,14 +16,14 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +echo "Add slack tool. Finish the flow" +composio add slack + +echo "Enable Slack triggers" +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/slack_agent_langchain.py b/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/slack_agent_langchain.py index 07cb497538e..8704e8548e5 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/slack_agent_langchain.py +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_langchain/slack_agent_langchain.py @@ -48,7 +48,7 @@ def callback_new_message(event: TriggerEventData) -> None: # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") @@ -57,7 +57,7 @@ def callback_new_message(event: TriggerEventData) -> None: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") return ( f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" - ) + ) # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -84,4 +84,4 @@ def callback_new_message(event: TriggerEventData) -> None: return result["output"] -listener.listen() +listener.wait_forever() diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/readme.md b/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/readme.md index 250ad2e5d1a..2788f268463 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/readme.md +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/readme.md @@ -38,6 +38,6 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/slack_agent_llamaindex/slack_agent_llamaindex.py +python python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/slack_agent_llamaindex.py ``` diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/setup.sh b/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/setup.sh index 2458e08c994..8a13e8d59d6 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/setup.sh +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/setup.sh @@ -16,14 +16,13 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot +echo "Add slack tool. Finish the flow" +composio add slack -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +echo "Enable Slack triggers" +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/slack_agent_llamaindex.py b/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/slack_agent_llamaindex.py index 5f87fd403bb..dd1d121fcda 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/slack_agent_llamaindex.py +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_llamaindex/slack_agent_llamaindex.py @@ -46,7 +46,7 @@ ] agent = FunctionCallingAgentWorker( - tools=composio_tools, + tools=list(composio_tools), # type: ignore llm=llm, prefix_messages=prefix_messages, max_function_calls=10, @@ -64,7 +64,7 @@ def callback_new_message(event: TriggerEventData) -> None: # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") @@ -73,7 +73,7 @@ def callback_new_message(event: TriggerEventData) -> None: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") return ( f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" - ) + ) # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -92,4 +92,4 @@ def callback_new_message(event: TriggerEventData) -> None: ) -listener.listen() +listener.wait_forever() \ No newline at end of file diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/main.py b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/main.py index ca70f8c3ac6..f65abcb9219 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/main.py +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/main.py @@ -1,15 +1,15 @@ # Import necessary libraries +import json import os from dotenv import load_dotenv from composio_langchain import Action, App, ComposioToolSet from langchain import hub from langchain.agents import AgentExecutor, create_openai_functions_agent from langchain_openai import ChatOpenAI +from langchain_ollama import ChatOllama from composio.client.collections import TriggerEventData load_dotenv() -# LangChain supports many other chat models. Here, we're using Ollama -from langchain.chat_models import ChatOllama llm = ChatOllama(model="mistral") bot_id = os.getenv("SLACK_BOT_ID", "") @@ -50,14 +50,14 @@ def callback_new_message(event: TriggerEventData) -> None: # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") # Respond only if the bot is tagged in the message, if configured to do so if RESPOND_ONLY_IF_TAGGED and f"<@{BOT_USER_ID}>" not in message: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") - return f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" + return f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -82,6 +82,6 @@ def callback_new_message(event: TriggerEventData) -> None: if __name__ == "__main__": inputs = { - "entityId": "hellll", + "entityId": "default", } main(inputs) diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/readme.md b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/readme.md index 249cd07de58..d50255cdddc 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/readme.md +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/readme.md @@ -52,6 +52,6 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/slack_agent_langchain/slack_agent_langchain.py +python python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/main.py ``` diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/requirements.txt b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/requirements.txt index f017ab67987..77cbf9d6281 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/requirements.txt +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/requirements.txt @@ -1,4 +1,5 @@ langchain langchain-openai +langchain-ollama composio-langchain python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/setup.sh b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/setup.sh index 2458e08c994..8a13e8d59d6 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/setup.sh +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_ollama/setup.sh @@ -16,14 +16,13 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot +echo "Add slack tool. Finish the flow" +composio add slack -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +echo "Enable Slack triggers" +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/readme.md b/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/readme.md index 532cd17b6ac..9f0a7fcae68 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/readme.md +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/readme.md @@ -38,6 +38,6 @@ Now, fill in the `.env` file with your secrets. ### 2. Run the Python Script ```shell -python cookbook/examples/slack_agent_openai/slack_agent_openai.py +python python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/slack_agent_openai.py ``` diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/setup.sh b/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/setup.sh index 2458e08c994..8a13e8d59d6 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/setup.sh +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/setup.sh @@ -16,14 +16,13 @@ pip install -r requirements.txt echo "Login to your Composio acount" composio login -# Add trello tool -echo "Add slackbot tool. Finish the flow" -composio add slackbot +echo "Add slack tool. Finish the flow" +composio add slack -echo "Enable Slackbot triggers" -composio triggers enable slackbot_receive_message -composio triggers enable slackbot_receive_thread_reply +echo "Enable Slack triggers" +composio triggers enable slack_receive_message +composio triggers enable slack_receive_thread_reply # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/slack_agent_openai.py b/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/slack_agent_openai.py index 3d44abe4655..2090927b64a 100644 --- a/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/slack_agent_openai.py +++ b/python/examples/advanced_agents/slack_bot_agent/slack_agent_openai/slack_agent_openai.py @@ -1,4 +1,5 @@ # Step 1: Import necessary libraries +import json import os from dotenv import load_dotenv from typing import Dict @@ -90,7 +91,7 @@ def process_message(event: TriggerEventData, is_new_message: bool) -> None: # Ignore messages from the bot itself to prevent self-responses if user_id == BOT_USER_ID: - return "Bot ignored" + return "Bot ignored" # type: ignore message = payload.get("text", "") @@ -99,7 +100,7 @@ def process_message(event: TriggerEventData, is_new_message: bool) -> None: print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") return ( f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" - ) + ) # type: ignore # Extract channel and timestamp information from the event payload channel_id = payload.get("channel", "") @@ -186,7 +187,7 @@ def run_openai_thread(thread_id: str, message: str) -> str: if messages.data: for message_response in messages.data: for content in message_response.content: - openai_response = content.text.value + openai_response = content.text.value # type: ignore break if openai_response != "No response generated": break diff --git a/python/examples/miscellaneous/news_summary/setup.sh b/python/examples/miscellaneous/news_summary/setup.sh index a21d7aba199..770ddaed46d 100644 --- a/python/examples/miscellaneous/news_summary/setup.sh +++ b/python/examples/miscellaneous/news_summary/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio account" composio login -# Add trello tool + echo "Add serpapi tool. Finish the flow" composio add serpapi diff --git a/python/examples/quickstarters/Notion_todo_list_agent/crewai/setup.sh b/python/examples/quickstarters/Notion_todo_list_agent/crewai/setup.sh index 1d8a85d0669..7d247a446df 100644 --- a/python/examples/quickstarters/Notion_todo_list_agent/crewai/setup.sh +++ b/python/examples/quickstarters/Notion_todo_list_agent/crewai/setup.sh @@ -11,6 +11,8 @@ source ./venv/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add notion +composio add slack # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/quickstarters/Notion_todo_list_agent/llamaindex/setup.sh b/python/examples/quickstarters/Notion_todo_list_agent/llamaindex/setup.sh index 1d8a85d0669..78d3f07a842 100644 --- a/python/examples/quickstarters/Notion_todo_list_agent/llamaindex/setup.sh +++ b/python/examples/quickstarters/Notion_todo_list_agent/llamaindex/setup.sh @@ -11,6 +11,9 @@ source ./venv/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add notion +composio add slack + # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/quickstarters/calendar_agent/crewai/README.md b/python/examples/quickstarters/calendar_agent/crewai/README.md index b1b5413b550..dc717718203 100644 --- a/python/examples/quickstarters/calendar_agent/crewai/README.md +++ b/python/examples/quickstarters/calendar_agent/crewai/README.md @@ -39,6 +39,6 @@ Now, Fill in the .env file with your secrets. ### 2. Run the python script ```shell -python cookbook/examples/calendar_agent/main.py +python python/examples/quickstarters/calendar_agent/main.py ``` A new event has been added to our Google calendar! diff --git a/python/examples/quickstarters/calendar_agent/langgraph/README.md b/python/examples/quickstarters/calendar_agent/langgraph/README.md index b1b5413b550..dc717718203 100644 --- a/python/examples/quickstarters/calendar_agent/langgraph/README.md +++ b/python/examples/quickstarters/calendar_agent/langgraph/README.md @@ -39,6 +39,6 @@ Now, Fill in the .env file with your secrets. ### 2. Run the python script ```shell -python cookbook/examples/calendar_agent/main.py +python python/examples/quickstarters/calendar_agent/main.py ``` A new event has been added to our Google calendar! diff --git a/python/examples/quickstarters/calendar_agent/langgraph/main.py b/python/examples/quickstarters/calendar_agent/langgraph/main.py index 1363ce22bd0..b8b491111a7 100644 --- a/python/examples/quickstarters/calendar_agent/langgraph/main.py +++ b/python/examples/quickstarters/calendar_agent/langgraph/main.py @@ -27,7 +27,7 @@ def call_model(state: MessagesState): def should_continue(state: MessagesState) -> Literal["tools", "__end__"]: messages = state["messages"] last_message = messages[-1] - if last_message.tool_calls: + if last_message.tool_calls: # type: ignore return "tools" return "__end__" diff --git a/python/examples/quickstarters/calendar_agent/llamaindex/README.md b/python/examples/quickstarters/calendar_agent/llamaindex/README.md index b1b5413b550..1f6b0b1e1fa 100644 --- a/python/examples/quickstarters/calendar_agent/llamaindex/README.md +++ b/python/examples/quickstarters/calendar_agent/llamaindex/README.md @@ -39,6 +39,6 @@ Now, Fill in the .env file with your secrets. ### 2. Run the python script ```shell -python cookbook/examples/calendar_agent/main.py +python python/examples/quickstarters/calendar_agent/llamaindex/main.py ``` A new event has been added to our Google calendar! diff --git a/python/examples/quickstarters/calendar_agent/llamaindex/main.py b/python/examples/quickstarters/calendar_agent/llamaindex/main.py index 6be414cc187..9c6b83faaa8 100644 --- a/python/examples/quickstarters/calendar_agent/llamaindex/main.py +++ b/python/examples/quickstarters/calendar_agent/llamaindex/main.py @@ -50,7 +50,7 @@ # Initialize a FunctionCallingAgentWorker with the tools, LLM, and system messages agent = FunctionCallingAgentWorker( - tools=tools, # Tools available for the agent to use + tools=tools, # Tools available for the agent to use # type: ignore llm=llm, # Language model for processing requests prefix_messages=prefix_messages, # Initial system messages for context max_function_calls=10, # Maximum number of function calls allowed diff --git a/python/examples/quickstarters/code-analysis/README.md b/python/examples/quickstarters/code-analysis/README.md index 4f521bcdd6c..0239c6bb730 100644 --- a/python/examples/quickstarters/code-analysis/README.md +++ b/python/examples/quickstarters/code-analysis/README.md @@ -27,5 +27,5 @@ Now, Fill in the `.env` file with your secrets. ### 2. Run the python script ```shell -python cookbook/examples/code-analysis/main.py +python python/examples/quickstarters/code-analysis/main.py ``` diff --git a/python/examples/quickstarters/code_execution_agent/README.md b/python/examples/quickstarters/code_execution_agent/README.md index 970537acc32..3c36056e960 100644 --- a/python/examples/quickstarters/code_execution_agent/README.md +++ b/python/examples/quickstarters/code_execution_agent/README.md @@ -27,5 +27,5 @@ Now, Fill in the `.env` file with your secrets. ### 2. Run the python script ```shell -python cookbook/examples/code_execution_agent/main.py +python python/examples/quickstarters/code_execution_agent/main.py ``` diff --git a/python/examples/quickstarters/code_execution_agent/crewai_ci_chart.py b/python/examples/quickstarters/code_execution_agent/crewai_ci_chart.py index aee062204ed..3cfe7e3a000 100644 --- a/python/examples/quickstarters/code_execution_agent/crewai_ci_chart.py +++ b/python/examples/quickstarters/code_execution_agent/crewai_ci_chart.py @@ -10,16 +10,15 @@ if main_task.lower() == "exit": break - code_interpreter_tools = ComposioToolSet().get_tools([App.CODEINTERPRETER]) + code_interpreter_tools = ComposioToolSet().get_tools(apps=[App.CODEINTERPRETER]) code_interpreter_agent = Agent( role="Python Code Interpreter Agent", goal=f"""Run I a code to get achieve a task given by the user""", backstory="""You are an agent that helps users run Python code.""", verbose=True, - tools=code_interpreter_tools, + tools=list(code_interpreter_tools), # type: ignore llm=llm, - memory=True, ) code_interpreter_task = Task( diff --git a/python/examples/quickstarters/code_execution_agent/main.py b/python/examples/quickstarters/code_execution_agent/main.py index 6eec30b0c2f..d3b85460e43 100644 --- a/python/examples/quickstarters/code_execution_agent/main.py +++ b/python/examples/quickstarters/code_execution_agent/main.py @@ -9,10 +9,8 @@ role="Python Code Executor", goal="Execute Python code in a Jupyter notebook cell and return the results.", verbose=True, - memory=True, backstory="You are an expert in executing Python code and interpreting results in a sandbox environment.", - allow_delegation=False, - tools=tools, + tools=list(tools), ) python_code = """ @@ -35,12 +33,9 @@ def factorial(n): execute_code_task = Task( - description="Execute the following Python code and return the results:\n\n" - + python_code, + description="Execute the following Python code and return the results:\n\n"+ python_code, expected_output="Execution of Python code returned the results.", - tools=tools, agent=python_executor_agent, - allow_delegation=False, ) crew = Crew( diff --git a/python/examples/quickstarters/code_execution_agent/requirements.txt b/python/examples/quickstarters/code_execution_agent/requirements.txt index 5c6fa05928a..9b3171746e0 100644 --- a/python/examples/quickstarters/code_execution_agent/requirements.txt +++ b/python/examples/quickstarters/code_execution_agent/requirements.txt @@ -1,6 +1,4 @@ crewai -crewai[tools] python-dotenv -composio_core composio-crewai langchain_openai \ No newline at end of file diff --git a/python/examples/quickstarters/customer_support/swarm/readme.md b/python/examples/quickstarters/customer_support/swarm/readme.md index cf316abddc8..6028fb1ab2e 100644 --- a/python/examples/quickstarters/customer_support/swarm/readme.md +++ b/python/examples/quickstarters/customer_support/swarm/readme.md @@ -29,5 +29,5 @@ Now, Fill in the `.env` file with your secrets. ### 2. Run the python script ```shell -python cookbook/examples/quickstarters/customer_support/swarm/main.py +python python/examples/quickstarters/customer_support/swarm/main.py ``` diff --git a/python/examples/quickstarters/presentation_agent/crewai/main.py b/python/examples/quickstarters/presentation_agent/crewai/main.py index 616029784b0..cf9f6447a8c 100644 --- a/python/examples/quickstarters/presentation_agent/crewai/main.py +++ b/python/examples/quickstarters/presentation_agent/crewai/main.py @@ -7,9 +7,9 @@ from pathlib import Path import os load_dotenv() -import agentops -AGENTOPS_API_KEY = os.environ["AGENTOPS_API_KEY"] -agentops.init(AGENTOPS_API_KEY) +# import agentops +# AGENTOPS_API_KEY = os.environ["AGENTOPS_API_KEY"] +# agentops.init(AGENTOPS_API_KEY) llm = ChatOpenAI(model='gpt-4o') #Settings.llm = Groq(model="llama3-groq-70b-8192-tool-use-preview") diff --git a/python/examples/quickstarters/presentation_agent/crewai/setup.sh b/python/examples/quickstarters/presentation_agent/crewai/setup.sh index 275e594167e..4c4a1da2dee 100644 --- a/python/examples/quickstarters/presentation_agent/crewai/setup.sh +++ b/python/examples/quickstarters/presentation_agent/crewai/setup.sh @@ -12,6 +12,7 @@ source ~/.venvs/presentation_agent/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add googlesheets # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/quickstarters/presentation_agent/langgraph/main.py b/python/examples/quickstarters/presentation_agent/langgraph/main.py index 3f54f5bdb25..1c385b1a0ee 100644 --- a/python/examples/quickstarters/presentation_agent/langgraph/main.py +++ b/python/examples/quickstarters/presentation_agent/langgraph/main.py @@ -33,7 +33,7 @@ def call_model(state: MessagesState): def should_continue(state: MessagesState) -> Literal["tools", "__end__"]: messages = state["messages"] last_message = messages[-1] - if last_message.tool_calls: + if last_message.tool_calls: # type: ignore return "tools" return "__end__" diff --git a/python/examples/quickstarters/presentation_agent/langgraph/setup.sh b/python/examples/quickstarters/presentation_agent/langgraph/setup.sh index 6a5cd07f886..3560c5fc752 100644 --- a/python/examples/quickstarters/presentation_agent/langgraph/setup.sh +++ b/python/examples/quickstarters/presentation_agent/langgraph/setup.sh @@ -12,6 +12,7 @@ source ~/.venvs/presentation_agent/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add googlesheets # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/quickstarters/presentation_agent/llama_index/main.py b/python/examples/quickstarters/presentation_agent/llama_index/main.py index bfe4cd58b81..5f8ae831188 100644 --- a/python/examples/quickstarters/presentation_agent/llama_index/main.py +++ b/python/examples/quickstarters/presentation_agent/llama_index/main.py @@ -43,7 +43,7 @@ agent = FunctionCallingAgentWorker( - tools=tools, # Tools available for the agent to use + tools=tools, # Tools available for the agent to use # type: ignore llm=llm, # Language model for processing requests prefix_messages=prefix_messages, # Initial system messages for context max_function_calls=10, # Maximum number of function calls allowed diff --git a/python/examples/quickstarters/presentation_agent/llama_index/setup.sh b/python/examples/quickstarters/presentation_agent/llama_index/setup.sh index 275e594167e..4c4a1da2dee 100644 --- a/python/examples/quickstarters/presentation_agent/llama_index/setup.sh +++ b/python/examples/quickstarters/presentation_agent/llama_index/setup.sh @@ -12,6 +12,7 @@ source ~/.venvs/presentation_agent/bin/activate echo "Installing libraries from requirements.txt..." pip install -r requirements.txt +composio add googlesheets # Copy env backup to .env file if [ -f ".env.example" ]; then echo "Copying .env.example to .env..." diff --git a/python/examples/quickstarters/research_assistant/research_assistant_camelai/setup.sh b/python/examples/quickstarters/research_assistant/research_assistant_camelai/setup.sh index 473dfa2b866..5e689aad970 100755 --- a/python/examples/quickstarters/research_assistant/research_assistant_camelai/setup.sh +++ b/python/examples/quickstarters/research_assistant/research_assistant_camelai/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio account" composio login -# Add trello tool + echo "Add serpapi tool. Finish the flow" composio add serpapi diff --git a/python/examples/quickstarters/research_assistant/research_assistant_crewai/setup.sh b/python/examples/quickstarters/research_assistant/research_assistant_crewai/setup.sh index 473dfa2b866..5e689aad970 100755 --- a/python/examples/quickstarters/research_assistant/research_assistant_crewai/setup.sh +++ b/python/examples/quickstarters/research_assistant/research_assistant_crewai/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio account" composio login -# Add trello tool + echo "Add serpapi tool. Finish the flow" composio add serpapi diff --git a/python/examples/quickstarters/research_assistant/research_assistant_praisonai/setup.sh b/python/examples/quickstarters/research_assistant/research_assistant_praisonai/setup.sh index 473dfa2b866..5e689aad970 100755 --- a/python/examples/quickstarters/research_assistant/research_assistant_praisonai/setup.sh +++ b/python/examples/quickstarters/research_assistant/research_assistant_praisonai/setup.sh @@ -16,7 +16,7 @@ pip install -r requirements.txt echo "Login to your Composio account" composio login -# Add trello tool + echo "Add serpapi tool. Finish the flow" composio add serpapi diff --git a/python/examples/quickstarters/solana-agent/main.py b/python/examples/quickstarters/solana-agent/main.py index 36db11c7892..a443174f814 100644 --- a/python/examples/quickstarters/solana-agent/main.py +++ b/python/examples/quickstarters/solana-agent/main.py @@ -11,7 +11,7 @@ # Create an agent with code execution enabled sol_agent = Agent( role="SOL Balance and Price Notifier", - goal="Retrieve SOL balance using get_balance and internet search to get price, then send it to Slack General channel.", + goal="Retrieve SOL balance using get_balance and internet search to get price, then send it to Slack balance_sol channel.", backstory="You are an agent specialized in monitoring SOL balance and price.", ) @@ -33,8 +33,8 @@ # Create a task to send the analyzed price information to Slack send_price_info_task = Task( - description="Send the analyzed real-time price information of Solana to the Slack General channel.", - expected_output='Analyzed price information sent to Slack General channel.', + description="Send the analyzed real-time price information of Solana to the Slack balance_sol channel. Don't say anything in the message other than the data, your insights and recommendation on future investment or sale but make sure its well formatted and nicely written.", + expected_output='Analyzed price information and wrote a detailed analysis on it.', agent=sol_agent, tools=tools # type: ignore ) @@ -48,5 +48,9 @@ # Execute the crew result = analysis_crew.kickoff(inputs={'wallet_address':'BHiAM94bZB9KKZhcVvx8mEVqdnaEANVmZ2XykZMSG8iB'}) - +toolset.execute_action( + action=Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, + params={}, + text=str(result)+'send it on balance_sol channel' +) print(result) diff --git a/python/examples/quickstarters/solana-agent/readme.md b/python/examples/quickstarters/solana-agent/readme.md index 21fc856d8f5..936be567f10 100644 --- a/python/examples/quickstarters/solana-agent/readme.md +++ b/python/examples/quickstarters/solana-agent/readme.md @@ -1,6 +1,6 @@ -# Solana Agent Guide +# Trend Finder Agent Guide -This guide provides detailed steps to create a Solana agent that leverages CrewAI, Composio, and ChatGPT to perform web searches and compile research reports. Ensure you have Python 3.8 or higher installed. +This guide provides detailed steps to create a Trend Finder agent that leverages Composio, ChatGPT to research and find trends in Twitter and Linkedin. Ensure you have Python 3.8 or higher installed. ## Steps to Run **Navigate to the Project Directory:** @@ -23,7 +23,7 @@ add necessary tools: Now, Fill in the .env file with your secrets. ### 2. Run the python script ```shell -python python/examples/quickstarters/solana-agent + python python/examples/quickstarters/trend_finder/main.py ``` diff --git a/python/examples/quickstarters/startup_trend_generator/.env.example b/python/examples/quickstarters/startup_trend_generator/.env.example new file mode 100644 index 00000000000..ff82e07cfb4 --- /dev/null +++ b/python/examples/quickstarters/startup_trend_generator/.env.example @@ -0,0 +1,2 @@ +COMPOSIO_API_KEY=KEY +OPENAI_API_KEY=KEY diff --git a/python/examples/quickstarters/startup_trend_generator/main.py b/python/examples/quickstarters/startup_trend_generator/main.py new file mode 100644 index 00000000000..0ddc1548cd1 --- /dev/null +++ b/python/examples/quickstarters/startup_trend_generator/main.py @@ -0,0 +1,34 @@ +from composio_llamaindex import Action, ComposioToolSet, App +from llama_index.core.llms import ChatMessage +from llama_index.core.agent import FunctionCallingAgentWorker +from dotenv import load_dotenv +from llama_index.llms.openai import OpenAI + +load_dotenv() + +llm = OpenAI(model="gpt-4o") + +toolset = ComposioToolSet() +tools = toolset.get_tools(actions=[Action.FIRECRAWL_SCRAPE_EXTRACT_DATA_LLM]) + + +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a startup idea generator. You are given a list of startups, you need ot analyse the trends and suggest 5 strong ideas on what idea can be used to build a startup." + ), + ) + ] + +agent = FunctionCallingAgentWorker( + tools=tools, # type: ignore + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, + ).as_agent() + +batch_name = input("Enter the batch name: ") +print(agent.chat(f"Go to https://www.ycombinator.com/companies?batch={batch_name} and find the latest startups and analyse the trends and suggest 5 strong ideas on what idea can be used to build a startup.")) \ No newline at end of file diff --git a/python/examples/quickstarters/startup_trend_generator/readme.md b/python/examples/quickstarters/startup_trend_generator/readme.md new file mode 100644 index 00000000000..4ac1c9cd66e --- /dev/null +++ b/python/examples/quickstarters/startup_trend_generator/readme.md @@ -0,0 +1,30 @@ +# Startup Trend Finder Agent Guide + +This guide provides detailed steps to create a Startup Trend Finder agent that leverages Composio, ChatGPT to research and find startup trends. Ensure you have Python 3.8 or higher installed. + +## Steps to Run +**Navigate to the Project Directory:** +Change to the directory where the `setup.sh`, `main.py`, `requirements.txt`, and `README.md` files are located. For example: +```sh +cd path/to/project/directory +``` + +### 1. Run the Setup File +Make the setup.sh Script Executable (if necessary): +On Linux or macOS, you might need to make the setup.sh script executable: +```shell +chmod +x setup.sh +``` +Execute the setup.sh script to set up the environment, install dependencies, login to composio and +add necessary tools: +```shell +./setup.sh +``` +Now, Fill in the .env file with your secrets. +### 2. Run the python script +```shell +python python/examples/quickstarters/trend_finder/main.py +``` + + + diff --git a/python/examples/quickstarters/startup_trend_generator/requirements.txt b/python/examples/quickstarters/startup_trend_generator/requirements.txt new file mode 100644 index 00000000000..2a5db820772 --- /dev/null +++ b/python/examples/quickstarters/startup_trend_generator/requirements.txt @@ -0,0 +1,2 @@ +composio_llamaindex +python-dotenv diff --git a/python/examples/advanced_agents/indie_hacker_agent/letta/setup.sh b/python/examples/quickstarters/startup_trend_generator/setup.sh similarity index 70% rename from python/examples/advanced_agents/indie_hacker_agent/letta/setup.sh rename to python/examples/quickstarters/startup_trend_generator/setup.sh index 0ff8854e651..3cc62929a91 100644 --- a/python/examples/advanced_agents/indie_hacker_agent/letta/setup.sh +++ b/python/examples/quickstarters/startup_trend_generator/setup.sh @@ -2,27 +2,18 @@ # Create a virtual environment echo "Creating virtual environment..." -python3 -m venv ~/.venvs/content_writing +python3 -m venv ~/.venvs/startup_trend_generator # Activate the virtual environment echo "Activating virtual environment..." -source ~/.venvs/content_writing/bin/activate +source ~/.venvs/startup_trend_generator/bin/activate # Install libraries from requirements.txt echo "Installing libraries from requirements.txt..." pip install -r requirements.txt -# Login to your account -echo "Login to your Composio acount" -composio login - -# Add trello tool - -echo "Add slackbot tool. Finish the flow" -composio add twitter -composio add linkedin composio add firecrawl -composio add tavily +composio add slack # Copy env backup to .env file if [ -f ".env.example" ]; then diff --git a/python/examples/quickstarters/trend_finder/.env.example b/python/examples/quickstarters/trend_finder/.env.example new file mode 100644 index 00000000000..ff82e07cfb4 --- /dev/null +++ b/python/examples/quickstarters/trend_finder/.env.example @@ -0,0 +1,2 @@ +COMPOSIO_API_KEY=KEY +OPENAI_API_KEY=KEY diff --git a/python/examples/quickstarters/trend_finder/main.py b/python/examples/quickstarters/trend_finder/main.py new file mode 100644 index 00000000000..96f828b32d2 --- /dev/null +++ b/python/examples/quickstarters/trend_finder/main.py @@ -0,0 +1,64 @@ +from composio_llamaindex import Action, ComposioToolSet, App +from llama_index.core.llms import ChatMessage +from llama_index.core.agent import FunctionCallingAgentWorker +from dotenv import load_dotenv +from llama_index.llms.openai import OpenAI + +load_dotenv() + +llm = OpenAI(model="gpt-4o") + +toolset = ComposioToolSet() +tools = toolset.get_tools(actions=[Action.TWITTER_USER_LOOKUP_BY_USERNAME, Action.TWITTER_BOOKMARKS_BY_USER, Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, Action.TWITTER_RECENT_SEARCH, Action.TAVILY_TAVILY_SEARCH, Action.FIRECRAWL_SCRAPE_EXTRACT_DATA_LLM]) + + +prefix_messages = [ + ChatMessage( + role="system", + content=( + """You are an advanced trend analyzer specializing in AI technology trends. + + Output Format: + :relevant emoji: Trend Title [Trend Score: X/10] [Momentum: ↑↓→] + - Key Insight: One-line summary + - Evidence: Engagement metrics across platforms, do not say based on Tavily Search but suggest what kind of posts are doing well. + - Market Impact: Potential business implications + - Action Items: Specific next steps + + Guidelines: + 1. Cross-validate trends across platforms + 2. Include engagement metrics (views, likes, shares) + 3. Provide sentiment analysis + 4. Compare with historical data + 5. Add expert citations when available + 6. Identify market opportunities + 7. Suggest practical applications + + Search Strategy: + - Use broad keyword clusters for Twitter search + - Leverage Tavily for LinkedIn professional insights + - Analyze bookmark patterns for emerging topics + + Rules: + 1. First fetch id from the username. + 2. Then fetch the bookmarks from the id. + 3. Then based on the keywords, search twitter. + 4. Search for the keywords on tavily and collect all the linkedin related posts that have done well. + 5. Then compile all of this info, write it in the above format and send it on slack channel. + """ + ), + ) + ] + +agent = FunctionCallingAgentWorker( + tools=tools, # type: ignore + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, + ).as_agent() + +id = '@mastmelon82' #your twitter id +channel = 'general' #your slack channel +print(agent.chat(f"What are the latest trends in AI from twitter from my bookmarks, search and linkedin, my id is {id} send it on my slack {channel} channel")) diff --git a/python/examples/quickstarters/trend_finder/readme.md b/python/examples/quickstarters/trend_finder/readme.md new file mode 100644 index 00000000000..9f672fa50c1 --- /dev/null +++ b/python/examples/quickstarters/trend_finder/readme.md @@ -0,0 +1,30 @@ +# Trend Finder Agent Guide + +This guide provides detailed steps to create a Trend Finder agent that leverages Composio, ChatGPT to research and find trends in Twitter and Linkedin. Ensure you have Python 3.8 or higher installed. + +## Steps to Run +**Navigate to the Project Directory:** +Change to the directory where the `setup.sh`, `main.py`, `requirements.txt`, and `README.md` files are located. For example: +```sh +cd path/to/project/directory +``` + +### 1. Run the Setup File +Make the setup.sh Script Executable (if necessary): +On Linux or macOS, you might need to make the setup.sh script executable: +```shell +chmod +x setup.sh +``` +Execute the setup.sh script to set up the environment, install dependencies, login to composio and +add necessary tools: +```shell +./setup.sh +``` +Now, Fill in the .env file with your secrets. +### 2. Run the python script +```shell +python python/examples/quickstarters/trend_finder/main.py +``` + + + diff --git a/python/examples/quickstarters/trend_finder/requirements.txt b/python/examples/quickstarters/trend_finder/requirements.txt new file mode 100644 index 00000000000..2a5db820772 --- /dev/null +++ b/python/examples/quickstarters/trend_finder/requirements.txt @@ -0,0 +1,2 @@ +composio_llamaindex +python-dotenv diff --git a/python/examples/quickstarters/trend_finder/setup.sh b/python/examples/quickstarters/trend_finder/setup.sh new file mode 100644 index 00000000000..90e0ab5e272 --- /dev/null +++ b/python/examples/quickstarters/trend_finder/setup.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Create a virtual environment +echo "Creating virtual environment..." +python3 -m venv ~/.venvs/trend_finder + +# Activate the virtual environment +echo "Activating virtual environment..." +source ~/.venvs/trend_finder/bin/activate + +# Install libraries from requirements.txt +echo "Installing libraries from requirements.txt..." +pip install -r requirements.txt + +composio add twitter +composio add slack +composio add tavily + +# Copy env backup to .env file +if [ -f ".env.example" ]; then + echo "Copying .env.example to .env..." + cp .env.example .env +else + echo "No .env.example file found. Creating a new .env file..." + touch .env +fi + +# Prompt user to fill the .env file +echo "Please fill in the .env file with the necessary environment variables." + +echo "Setup completed successfully!" \ No newline at end of file From 10775fd7ae8f7aef445fa42fa51b4b12524430ec Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Fri, 10 Jan 2025 13:15:36 +0530 Subject: [PATCH 10/34] feat: remove trailing slash (#1176) --- js/src/sdk/client/core/OpenAPI.ts | 2 +- js/src/sdk/models/backendClient.ts | 5 +++-- js/src/sdk/utils/string.ts | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 js/src/sdk/utils/string.ts diff --git a/js/src/sdk/client/core/OpenAPI.ts b/js/src/sdk/client/core/OpenAPI.ts index 3687c05fcdf..e395cb6bad0 100644 --- a/js/src/sdk/client/core/OpenAPI.ts +++ b/js/src/sdk/client/core/OpenAPI.ts @@ -39,7 +39,7 @@ export type OpenAPIConfig = { }; }; -export const COMPOSIO_BASE_URL = "https://backend.composio.dev/"; +export const COMPOSIO_BASE_URL = "https://backend.composio.dev"; export const OpenAPI: OpenAPIConfig = { BASE: COMPOSIO_BASE_URL, diff --git a/js/src/sdk/models/backendClient.ts b/js/src/sdk/models/backendClient.ts index 5f9a0f6387c..764b3b18ae7 100644 --- a/js/src/sdk/models/backendClient.ts +++ b/js/src/sdk/models/backendClient.ts @@ -4,6 +4,7 @@ import { client as axiosClient } from "../client/services.gen"; import { setAxiosClientConfig } from "../utils/config"; import { CEG } from "../utils/error"; import { COMPOSIO_SDK_ERROR_CODES } from "../utils/errors/src/constants"; +import { removeTrailingSlashIfExists } from "../utils/string"; /** * Class representing the details required to initialize and configure the API client. @@ -35,7 +36,7 @@ export class BackendClient { constructor(apiKey: string, baseUrl: string, runtime?: string) { this.runtime = runtime || ""; this.apiKey = apiKey; - this.baseUrl = baseUrl; + this.baseUrl = removeTrailingSlashIfExists(baseUrl); this.instance = axiosClient.instance; if (!apiKey) { @@ -84,7 +85,7 @@ export class BackendClient { */ private initializeApiClient() { axiosClient.setConfig({ - baseURL: this.baseUrl, + baseURL: removeTrailingSlashIfExists(this.baseUrl), headers: { "X-API-KEY": `${this.apiKey}`, "X-SOURCE": "js_sdk", diff --git a/js/src/sdk/utils/string.ts b/js/src/sdk/utils/string.ts new file mode 100644 index 00000000000..e27080f3505 --- /dev/null +++ b/js/src/sdk/utils/string.ts @@ -0,0 +1,2 @@ +export const removeTrailingSlashIfExists = (str: string) => + str.replace(/\/+$/, ""); From 42ff618cbfcefca6310eec31c90306d251ac7960 Mon Sep 17 00:00:00 2001 From: Abhishek Patil <83769052+abhishekpatil4@users.noreply.github.com> Date: Fri, 10 Jan 2025 23:18:26 +0530 Subject: [PATCH 11/34] feat: add docs on how to setup redirect URL (#1177) --- docs/patterns/Auth/Integrations.mdx | 31 ++++++++++++++++++ .../Auth/media/newIntegrationPage.jpg | Bin 0 -> 327196 bytes 2 files changed, 31 insertions(+) create mode 100644 docs/patterns/Auth/media/newIntegrationPage.jpg diff --git a/docs/patterns/Auth/Integrations.mdx b/docs/patterns/Auth/Integrations.mdx index 18710eaa1ae..d5da4c3a8e9 100644 --- a/docs/patterns/Auth/Integrations.mdx +++ b/docs/patterns/Auth/Integrations.mdx @@ -215,3 +215,34 @@ When users connect using this integration, they'll see your app's name and logo + +### Adding custom redirect URL +To use your own domain for OAuth callbacks, set up a 301 redirect from your domain to Composio's default redirect URL +. It would look something like this:
+`yourdomain.com/redirect` → `https://backend.composio.dev/api/v1/auth-apps/add` + + + + + +```bash Redirect URL +https://backend.composio.dev/api/v1/auth-apps/add +``` + + +Head over to your DNS provider and set up a 301 redirect from your domain to Composio's default redirect URL, here are doc references for some of the popular DNS providers: [Cloudflare](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/create-dashboard/), [GoDaddy](https://www.godaddy.com/en-in/help/forward-my-godaddy-domain-12123), [NameCheap](https://www.namecheap.com/support/knowledgebase/article.aspx/385/2237/how-to-set-up-a-url-redirect-for-a-domain/) +Please make sure that you enable the Preserve query string option when setting up the redirect. If you’re using your own custom application code for redirect, please remember to pass the exact query parameters and headers + + +Head over to [dashboard](https://app.composio.dev/), select the app you want to integrate and enable **Use your own Developer App** toggle, enter your OAuth credentials and click on the edit button and add your own redirect URL (yourdomain.com/redirect). Click on **Create Integration** and you're done. + + + diff --git a/docs/patterns/Auth/media/newIntegrationPage.jpg b/docs/patterns/Auth/media/newIntegrationPage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..00748c21283cb39fcda448f1995dba4ce2e389b4 GIT binary patch literal 327196 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 D^x)!! literal 0 HcmV?d00001 From d54518880a03c226fbd274ca1fae054e634f48db Mon Sep 17 00:00:00 2001 From: tushar-composio Date: Mon, 13 Jan 2025 11:37:11 +0530 Subject: [PATCH 12/34] feat: add plugin tests (#1096) --- .github/workflows/common.yml | 4 + .../tools/local/codeanalysis/embedder.py | 4 +- python/tests/test_tools/test_plugins.py | 449 ++++++++++++++++++ python/tox.ini | 37 +- 4 files changed, 483 insertions(+), 11 deletions(-) create mode 100644 python/tests/test_tools/test_plugins.py diff --git a/.github/workflows/common.yml b/.github/workflows/common.yml index 34453ad0daa..438371f55b9 100644 --- a/.github/workflows/common.yml +++ b/.github/workflows/common.yml @@ -102,6 +102,10 @@ jobs: export E2B_API_KEY=${{ secrets.E2B_API_KEY_STAGING }} tox -e test -- -m 'not e2e and not swe' + - name: Plugin tests + if: matrix.python-version == '3.10' + run: | + tox -e plugins - if: matrix.python-version == '3.10' name: Upload test results to Codecov uses: codecov/test-results-action@v1 diff --git a/python/composio/tools/local/codeanalysis/embedder.py b/python/composio/tools/local/codeanalysis/embedder.py index 448967b109d..ce61ca273ba 100644 --- a/python/composio/tools/local/codeanalysis/embedder.py +++ b/python/composio/tools/local/codeanalysis/embedder.py @@ -2,7 +2,6 @@ from typing import Any, Dict, List from deeplake.core.vectorstore.deeplake_vectorstore import DeepLakeVectorStore -from sentence_transformers import SentenceTransformer from composio.tools.local.codeanalysis.constants import ( CODE_MAP_CACHE, @@ -49,6 +48,9 @@ def get_vector_store(repo_name: str, overwrite: bool = True) -> DeepLakeVectorSt class Embedding: def __init__(self): + # pylint: disable=import-outside-toplevel + from sentence_transformers import SentenceTransformer + self.model = SentenceTransformer(EMBEDDER) def compute(self, texts: List[str]) -> List[List[float]]: diff --git a/python/tests/test_tools/test_plugins.py b/python/tests/test_tools/test_plugins.py new file mode 100644 index 00000000000..d7be9ea74ce --- /dev/null +++ b/python/tests/test_tools/test_plugins.py @@ -0,0 +1,449 @@ +import composio_llamaindex +from pydantic import BaseModel + +from composio import action +from composio.client.enums.action import Action + +import composio_crewai +import composio_langchain +import composio_openai + + +class Thread(BaseModel): + id: str + + +@action(toolname="my_tool") +def create_draft( + message_body: str, + thread: Thread | None = None, +) -> dict: + """ + Create a draft reply to a specific Gmail thread + + :param thread: The thread to which the reply is to be drafted + :param message_body: The content of the draft reply + :return draft: The created draft details + """ + _ = message_body, thread + return {} + + +def test_openai_toolset() -> None: + toolset = composio_openai.ComposioToolSet() + + tools = toolset.get_tools(actions=[create_draft]) + assert tools == [ + { + "function": { + "description": "Create a draft reply to a specific Gmail thread", + "name": "MYTOOL_CREATE_DRAFT", + "parameters": { + "properties": { + "message_body": { + "description": "The content of the draft reply. Please provide a " + "value of type string. This parameter is required.", + "title": "Message Body", + "type": "string", + }, + "thread": { + "anyOf": [ + { + "properties": { + "id": { + "title": "Id", + "type": "string", + }, + }, + "required": ["id"], + "title": "Thread", + "type": "object", + }, + {"type": "null"}, + ], + "default": None, + "description": "The thread to which the reply is to be drafted", + "type": "object", + }, + }, + "required": ["message_body"], + "title": "CreateDraftRequest", + "type": "object", + }, + }, + "type": "function", + }, + ] + + tools = toolset.get_tools(actions=[Action.ANTHROPIC_COMPUTER]) + assert tools == [ + { + "function": { + "description": "A Tool That Allows Interaction With The Screen, Keyboard, And " + "Mouse Of The Current Computer. Adapted For Mac Os And Linux.", + "name": "computer", + "parameters": { + "properties": { + "action": { + "description": "The action to perform on the computer. Please provide " + "a value of type string. This parameter is required.", + "enum": [ + "key", + "type", + "mouse_move", + "left_click", + "left_click_drag", + "right_click", + "middle_click", + "double_click", + "screenshot", + "cursor_position", + ], + "title": "ActionType", + "type": "string", + }, + "coordinate": { + "anyOf": [ + { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + {"type": "integer"}, + {"type": "integer"}, + ], + "type": "array", + }, + {"type": "null"}, + ], + "default": None, + "description": "X,Y coordinates for mouse actions", + "title": "Coordinate", + "type": "array", + }, + "text": { + "anyOf": [ + {"type": "string"}, + {"type": "null"}, + ], + "default": None, + "description": "Text to type or key sequence to press. Please provide " + "a value of type string.", + "title": "Text", + "type": "string", + }, + }, + "required": ["action"], + "title": "ComputerRequest", + "type": "object", + }, + }, + "type": "function", + }, + ] + + +def test_crewai_toolset() -> None: + toolset = composio_crewai.ComposioToolSet() + + tools = toolset.get_tools(actions=[create_draft]) + assert len(tools) == 1 + + tool = tools[0] + assert tool.name == "MYTOOL_CREATE_DRAFT" + assert ( + tool.description + # TODO: Thread's properties should be present in the arguments + == "Tool Name: MYTOOL_CREATE_DRAFT\nTool Arguments: {'message_body': {'description': 'The content of the draft reply. Please provide a value of type string. This parameter is required.', 'type': 'str'}, 'thread': {'description': 'The thread to which the reply is to be drafted', 'type': 'dict'}}\nTool Description: Create a draft reply to a specific Gmail thread" + ) + assert tool.args_schema.model_json_schema() == { + "properties": { + "message_body": { + "description": "The content of the draft reply. Please provide a value of type " + "string. This parameter is required.", + "examples": [], + "title": "Message Body", + "type": "string", + }, + "thread": { + "default": None, + "description": "The thread to which the reply is to be drafted", + "examples": [], + "title": "Thread", + # TODO: Thread's properties should be present in the schema + "type": "object", + }, + }, + "required": ["message_body"], + "title": "CreateDraftRequest", + "type": "object", + } + + tools = toolset.get_tools(actions=[Action.ANTHROPIC_COMPUTER]) + assert len(tools) == 1 + + tool = tools[0] + assert ( + tool.description + == "Tool Name: computer\nTool Arguments: {'action': {'description': 'The action to perform on the computer. Please provide a value of type string. This parameter is required. Please provide a value of type string. This parameter is required.', 'type': 'str'}, 'text': {'description': 'Text to type or key sequence to press. Please provide a value of type string. Please provide a value of type string.', 'type': 'str'}, 'coordinate': {'description': 'X,Y coordinates for mouse actions', 'type': 'list'}}\nTool Description: A Tool That Allows Interaction With The Screen, Keyboard, And Mouse Of The Current Computer. Adapted For Mac Os And Linux." + ) + assert tool.args_schema.model_json_schema() == { + "properties": { + "action": { + "description": "The action to perform on the computer. Please provide a value of " + "type string. This parameter is required. Please provide a value " + "of type string. This parameter is required.", + "examples": [], + "title": "Action", + "type": "string", + }, + "coordinate": { + "default": None, + "description": "X,Y coordinates for mouse actions", + "examples": [], + "items": {}, + "title": "Coordinate", + "type": "array", + }, + "text": { + "default": None, + "description": "Text to type or key sequence to press. Please provide a value of " + "type string. Please provide a value of type string.", + "examples": [], + "title": "Text", + "type": "string", + }, + }, + "required": ["action"], + "title": "ComputerRequest", + "type": "object", + } + + +def test_langchain_toolset() -> None: + toolset = composio_langchain.ComposioToolSet() + + tools = toolset.get_tools(actions=[create_draft]) + assert len(tools) == 1 + + tool = tools[0] + assert tool.name == "MYTOOL_CREATE_DRAFT" + # TODO: there's no schema in this description + assert tool.description == "Create a draft reply to a specific Gmail thread" + assert tool.args_schema.model_json_schema() == { + "properties": { + "message_body": { + "description": "The content of the draft reply. Please provide a value of type " + "string. This parameter is required.", + "examples": [], + "title": "Message Body", + "type": "string", + }, + "thread": { + "default": None, + "description": "The thread to which the reply is to be drafted", + "examples": [], + "title": "Thread", + "type": "object", + }, + }, + "required": ["message_body"], + # TODO: title should be MYTOOL_CREATE_DRAFT + "title": "CreateDraftRequest", + "type": "object", + } + + tools = toolset.get_tools(actions=[Action.ANTHROPIC_COMPUTER]) + assert len(tools) == 1 + + tool = tools[0] + assert ( + tool.description + == "A Tool That Allows Interaction With The Screen, Keyboard, And Mouse Of The Current Computer. Adapted For Mac Os And Linux." + ) + assert tool.args_schema.model_json_schema() == { + "properties": { + "action": { + # TODO: "please provide" and "is required" is there 3 times + "description": "The action to perform on the computer. Please provide a value of " + "type string. This parameter is required. Please provide a value " + "of type string. This parameter is required. Please provide a " + "value of type string. This parameter is required.", + "examples": [], + "title": "Action", + "type": "string", + }, + "coordinate": { + "default": None, + "description": "X,Y coordinates for mouse actions", + "examples": [], + "items": {}, + "title": "Coordinate", + "type": "array", + }, + "text": { + "default": None, + # TODO: "please provide" is there 3 times + "description": "Text to type or key sequence to press. Please provide a value of " + "type string. Please provide a value of type string. Please " + "provide a value of type string.", + "examples": [], + "title": "Text", + "type": "string", + }, + }, + "required": ["action"], + # TODO: title should be computer + "title": "ComputerRequest", + "type": "object", + } + + +def test_claude_toolset() -> None: + toolset = composio_crewai.ComposioToolSet() + + tools = toolset.get_tools(actions=[create_draft]) + assert len(tools) == 1 + + tool = tools[0] + assert tool.name == "MYTOOL_CREATE_DRAFT" + assert ( + tool.description + # TODO: Thread's properties should be present in the arguments + == "Tool Name: MYTOOL_CREATE_DRAFT\nTool Arguments: {'message_body': {'description': 'The content of the draft reply. Please provide a value of type string. This parameter is required.', 'type': 'str'}, 'thread': {'description': 'The thread to which the reply is to be drafted', 'type': 'dict'}}\nTool Description: Create a draft reply to a specific Gmail thread" + ) + assert tool.args_schema.model_json_schema() == { + "properties": { + "message_body": { + "description": "The content of the draft reply. Please provide a value of type " + "string. This parameter is required.", + "examples": [], + "title": "Message Body", + "type": "string", + }, + "thread": { + "default": None, + "description": "The thread to which the reply is to be drafted", + "examples": [], + "title": "Thread", + # TODO: Thread's properties should be present in the schema + "type": "object", + }, + }, + "required": ["message_body"], + # TODO: title should be MYTOOL_CREATE_DRAFT + "title": "CreateDraftRequest", + "type": "object", + } + + tools = toolset.get_tools(actions=[Action.ANTHROPIC_COMPUTER]) + assert len(tools) == 1 + + tool = tools[0] + assert ( + tool.description + == "Tool Name: computer\nTool Arguments: {'action': {'description': 'The action to perform on the computer. Please provide a value of type string. This parameter is required. Please provide a value of type string. This parameter is required. Please provide a value of type string. This parameter is required. Please provide a value of type string. This parameter is required.', 'type': 'str'}, 'text': {'description': 'Text to type or key sequence to press. Please provide a value of type string. Please provide a value of type string. Please provide a value of type string. Please provide a value of type string.', 'type': 'str'}, 'coordinate': {'description': 'X,Y coordinates for mouse actions', 'type': 'list'}}\nTool Description: A Tool That Allows Interaction With The Screen, Keyboard, And Mouse Of The Current Computer. Adapted For Mac Os And Linux." + ) + assert tool.args_schema.model_json_schema() == { + "properties": { + "action": { + # TODO: "please provide" and "is required" is there FOUR TIMES + "description": "The action to perform on the computer. Please provide a value of " + "type string. This parameter is required. Please provide a value " + "of type string. This parameter is required. Please provide a " + "value of type string. This parameter is required. Please provide " + "a value of type string. This parameter is required.", + "examples": [], + "title": "Action", + "type": "string", + }, + "coordinate": { + "default": None, + "description": "X,Y coordinates for mouse actions", + "examples": [], + "items": {}, + "title": "Coordinate", + "type": "array", + }, + "text": { + "default": None, + # TODO: "please provide" is there FOUR TIMES + "description": "Text to type or key sequence to press. Please provide a value of " + "type string. Please provide a value of type string. Please " + "provide a value of type string. Please provide a value of type string.", + "examples": [], + "title": "Text", + "type": "string", + }, + }, + "required": ["action"], + # TODO: title should be computer + "title": "ComputerRequest", + "type": "object", + } + + +def test_llamaindex_toolset() -> None: + toolset = composio_llamaindex.ComposioToolSet() + + tools = toolset.get_tools(actions=[create_draft]) + assert len(tools) == 1 + + tool = tools[0] + assert tool.metadata.name == "MYTOOL_CREATE_DRAFT" + assert ( + tool.metadata.description == "Create a draft reply to a specific Gmail thread" + ) + assert tool.metadata.fn_schema is not None + assert tool.metadata.fn_schema.model_json_schema() == { + "properties": { + "message_body": { + # TODO: description missing + "title": "Message Body", + "type": "string", + }, + "thread": { + "default": None, + # TODO: description missing + "title": "Thread", + "type": "object", + }, + }, + "required": ["message_body"], + "title": "MYTOOL_CREATE_DRAFT", + "type": "object", + } + + tools = toolset.get_tools(actions=[Action.ANTHROPIC_COMPUTER]) + assert len(tools) == 1 + + tool = tools[0] + assert ( + tool.metadata.description + == "A Tool That Allows Interaction With The Screen, Keyboard, And Mouse Of The Current Computer. Adapted For Mac Os And Linux." + ) + assert tool.metadata.fn_schema is not None + assert tool.metadata.fn_schema.model_json_schema() == { + "properties": { + "action": { + # TODO: description missing + "title": "Action", + "type": "string", + }, + "coordinate": { + "default": None, + # TODO: description missing + "items": {}, + "title": "Coordinate", + "type": "array", + }, + "text": { + "default": None, + # TODO: description missing + "title": "Text", + "type": "string", + }, + }, + "required": ["action"], + "title": "computer", + "type": "object", + } diff --git a/python/tox.ini b/python/tox.ini index 3edce8485e2..ecc3dc0074f 100644 --- a/python/tox.ini +++ b/python/tox.ini @@ -121,17 +121,32 @@ commands = ; TODO: Extract plugin tests separately ; Installing separately because of the dependency conflicts - uv pip install plugins/langchain --no-deps + uv pip install plugins/langchain - pytest -vvv -rfE --doctest-modules composio/ tests/ swe/tests --junitxml=junit.xml --cov=composio --cov=examples --cov=swe --cov-report=html --cov-report=xml --cov-report=term --cov-report=term-missing --cov-config=.coveragerc {posargs} + pytest -vvv -rfE --doctest-modules composio/ tests/ swe/tests --ignore tests/test_tools/test_plugins.py --junitxml=junit.xml --cov=composio --cov=examples --cov=swe --cov-report=html --cov-report=xml --cov-report=term --cov-report=term-missing --cov-config=.coveragerc {posargs} - ; uv pip install plugins/autogen - ; uv pip install plugins/claude - ; uv pip install plugins/crew_ai - ; uv pip install plugins/griptape - ; uv pip install plugins/julep - ; uv pip install plugins/lyzr - ; uv pip install plugins/openai + +[testenv:plugins] +setenv = + CI={env:CI} + COMPOSIO_API_KEY={env:COMPOSIO_API_KEY} + COMPOSIO_BASE_URL={env:COMPOSIO_BASE_URL} + COMPOSIO_LOGGING_LEVEL="debug" +deps = + . + plugins/autogen + plugins/claude + plugins/crew_ai + plugins/griptape + plugins/julep + plugins/langchain + plugins/langgraph + plugins/llamaindex + plugins/openai + pip + pytest +commands = + pytest -vvv -rfE tests/test_tools/test_plugins.py {posargs} ; Linter config @@ -156,7 +171,9 @@ sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,PLUGINS,PACKAGES,LOCALFOLDER [flake8] max_line_length = 200 exclude= **/build, **/dist -per-file-ignores = __init__.py:F401,W503 +per-file-ignores = + __init__.py:F401,W503 + tests/**:E501 ignore = E231, W291, W503, E704 [mypy] From 3734266cf001e676895a4c3e570d0f0f2ce00452 Mon Sep 17 00:00:00 2001 From: Nicolas Angelo Date: Mon, 13 Jan 2025 01:55:56 -0500 Subject: [PATCH 13/34] feat: support custom actions in vercel toolkit (with type safety improvements) (#1175) Co-authored-by: Himanshu Dixit --- js/src/frameworks/vercel.spec.ts | 51 ++++++++++++++++++++++++++++++++ js/src/frameworks/vercel.ts | 28 ++++++++---------- js/src/sdk/actionRegistry.ts | 28 ++++++++++++++---- js/src/sdk/base.toolset.ts | 16 +++++----- 4 files changed, 94 insertions(+), 29 deletions(-) diff --git a/js/src/frameworks/vercel.spec.ts b/js/src/frameworks/vercel.spec.ts index 560584e6e31..9090e00e2a3 100644 --- a/js/src/frameworks/vercel.spec.ts +++ b/js/src/frameworks/vercel.spec.ts @@ -1,9 +1,12 @@ import { beforeAll, describe, expect, it } from "@jest/globals"; +import { z } from "zod"; import { getTestConfig } from "../../config/getTestConfig"; import { VercelAIToolSet } from "./vercel"; +import type { CreateActionOptions } from "../sdk/actionRegistry"; describe("Apps class tests", () => { let vercelAIToolSet: VercelAIToolSet; + beforeAll(() => { vercelAIToolSet = new VercelAIToolSet({ apiKey: getTestConfig().COMPOSIO_API_KEY, @@ -25,4 +28,52 @@ describe("Apps class tests", () => { }); expect(Object.keys(tools).length).toBe(1); }); + + describe("custom actions", () => { + let customAction: Awaited>; + let tools: Awaited>; + + beforeAll(async () => { + const params = z.object({ + owner: z.string().describe("The owner of the repository"), + repo: z.string().describe("The name of the repository without the `.git` extension."), + }) + + + customAction = await vercelAIToolSet.createAction({ + actionName: "starRepositoryCustomAction", + toolName: "github", + description: "Star A Github Repository For Given `Repo` And `Owner`", + inputParams: params, + callback: async ( + inputParams, + ) => ({ successful: true, data: inputParams }) + }) + + tools = await vercelAIToolSet.getTools({ + actions: ["starRepositoryCustomAction"], + }); + + }); + + it("check if custom actions are coming", async () => { + expect(Object.keys(tools).length).toBe(1); + expect(tools).toHaveProperty(customAction.name, tools[customAction.name]); + }); + + it("check if custom actions are executing", async () => { + const res = await vercelAIToolSet.executeAction({ + action: customAction.name, + params: { + owner: "composioHQ", + repo: "composio" + }, + }) + expect(res.successful).toBe(true); + expect(res.data).toHaveProperty("owner", "composioHQ"); + expect(res.data).toHaveProperty("repo", "composio"); + }); + }) + + }); diff --git a/js/src/frameworks/vercel.ts b/js/src/frameworks/vercel.ts index 75a3b7c9ed2..6236e358bdd 100644 --- a/js/src/frameworks/vercel.ts +++ b/js/src/frameworks/vercel.ts @@ -1,4 +1,4 @@ -import { jsonSchema, tool } from "ai"; +import { jsonSchema, tool, CoreTool } from "ai"; import { z } from "zod"; import { ComposioToolSet as BaseComposioToolSet } from "../sdk/base.toolset"; import { TELEMETRY_LOGGER } from "../sdk/utils/telemetry"; @@ -62,7 +62,7 @@ export class VercelAIToolSet extends BaseComposioToolSet { useCase?: Optional; usecaseLimit?: Optional; filterByAvailableApps?: Optional; - }): Promise<{ [key: string]: RawActionData }> { + }): Promise<{ [key: string]: CoreTool }> { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { method: "getTools", file: this.fileName, @@ -78,21 +78,19 @@ export class VercelAIToolSet extends BaseComposioToolSet { actions, } = ZExecuteToolCallParams.parse(filters); - const actionsList = await this.client.actions.list({ - ...(apps && { apps: apps?.join(",") }), - ...(tags && { tags: tags?.join(",") }), - ...(useCase && { useCase: useCase }), - ...(actions && { actions: actions?.join(",") }), - ...(usecaseLimit && { usecaseLimit: usecaseLimit }), - filterByAvailableApps: filterByAvailableApps ?? undefined, - }); + const actionsList = await this.getToolsSchema({ + apps, + actions, + tags, + useCase, + useCaseLimit: usecaseLimit, + filterByAvailableApps + }) - const tools = {}; - actionsList.items?.forEach((actionSchema) => { - // @ts-ignore + const tools: { [key: string]: CoreTool } = {}; + actionsList.forEach((actionSchema) => { tools[actionSchema.name!] = this.generateVercelTool( - // @ts-ignore - actionSchema as ActionData + actionSchema ); }); diff --git a/js/src/sdk/actionRegistry.ts b/js/src/sdk/actionRegistry.ts index 3d13ab6b537..5eff37e3393 100644 --- a/js/src/sdk/actionRegistry.ts +++ b/js/src/sdk/actionRegistry.ts @@ -18,13 +18,25 @@ type RawExecuteRequestParam = { }; }; -export type CreateActionOptions = { + +type ValidParameters = ZodObject<{ [key: string]: ZodString | ZodOptional }> +export type Parameters = ValidParameters | z.ZodObject<{}> + +type inferParameters = + PARAMETERS extends ValidParameters + ? z.infer + : z.infer> + + +export type CreateActionOptions< + P extends Parameters = z.ZodObject<{}> +> = { actionName?: string; toolName?: string; description?: string; - inputParams: ZodObject<{ [key: string]: ZodString | ZodOptional }>; + inputParams?: P; callback: ( - inputParams: Record, + inputParams: inferParameters

, authCredentials: Record | undefined, executeRequest: ( data: RawExecuteRequestParam @@ -50,7 +62,10 @@ export class ActionRegistry { client: Composio; customActions: Map< string, - { metadata: CreateActionOptions; schema: Record } + { + metadata: CreateActionOptions; + schema: Record + } >; constructor(client: Composio) { @@ -58,7 +73,8 @@ export class ActionRegistry { this.customActions = new Map(); } - async createAction(options: CreateActionOptions): Promise { + + async createAction

>(options: CreateActionOptions

): Promise { const { callback } = options; if (typeof callback !== "function") { throw new Error("Callback must be a function"); @@ -67,7 +83,7 @@ export class ActionRegistry { throw new Error("You must provide actionName for this action"); } if (!options.inputParams) { - options.inputParams = z.object({}); + options.inputParams = z.object({}) as P } const params = options.inputParams; const actionName = options.actionName || callback.name || ""; diff --git a/js/src/sdk/base.toolset.ts b/js/src/sdk/base.toolset.ts index b7740f6e3bd..454f5e7e869 100644 --- a/js/src/sdk/base.toolset.ts +++ b/js/src/sdk/base.toolset.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z, ZodObject } from "zod"; import { Composio } from "../sdk"; import { RawActionData, @@ -10,7 +10,7 @@ import { } from "../types/base_toolset"; import type { Optional, Sequence } from "../types/util"; import { getEnvVariable } from "../utils/shared"; -import { ActionRegistry, CreateActionOptions } from "./actionRegistry"; +import { ActionRegistry, CreateActionOptions, Parameters } from "./actionRegistry"; import { ActionExecutionResDto } from "./client/types.gen"; import { ActionExecuteResponse, Actions } from "./models/actions"; import { ActiveTriggers } from "./models/activeTriggers"; @@ -54,10 +54,10 @@ export class ComposioToolSet { post: TPostProcessor[]; schema: TSchemaProcessor[]; } = { - pre: [fileInputProcessor], - post: [fileResponseProcessor], - schema: [fileSchemaProcessor], - }; + pre: [fileInputProcessor], + post: [fileResponseProcessor], + schema: [fileSchemaProcessor], + }; private userDefinedProcessors: { pre?: TPreProcessor; @@ -172,8 +172,8 @@ export class ComposioToolSet { }); } - async createAction(options: CreateActionOptions) { - return this.userActionRegistry.createAction(options); + async createAction

>(options: CreateActionOptions

) { + return this.userActionRegistry.createAction

(options); } private isCustomAction(action: string) { From 3401f191726b28245771cdb519ec536088c1e40f Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Mon, 13 Jan 2025 12:52:41 +0530 Subject: [PATCH 14/34] feat: prettier and fail test --- js/src/frameworks/vercel.spec.ts | 26 ++++++++++++-------------- js/src/frameworks/vercel.ts | 10 ++++------ js/src/sdk/actionRegistry.ts | 25 ++++++++++++------------- js/src/sdk/base.toolset.spec.ts | 2 +- js/src/sdk/base.toolset.ts | 20 +++++++++++++------- 5 files changed, 42 insertions(+), 41 deletions(-) diff --git a/js/src/frameworks/vercel.spec.ts b/js/src/frameworks/vercel.spec.ts index 9090e00e2a3..3be69b5b6af 100644 --- a/js/src/frameworks/vercel.spec.ts +++ b/js/src/frameworks/vercel.spec.ts @@ -2,7 +2,6 @@ import { beforeAll, describe, expect, it } from "@jest/globals"; import { z } from "zod"; import { getTestConfig } from "../../config/getTestConfig"; import { VercelAIToolSet } from "./vercel"; -import type { CreateActionOptions } from "../sdk/actionRegistry"; describe("Apps class tests", () => { let vercelAIToolSet: VercelAIToolSet; @@ -36,24 +35,25 @@ describe("Apps class tests", () => { beforeAll(async () => { const params = z.object({ owner: z.string().describe("The owner of the repository"), - repo: z.string().describe("The name of the repository without the `.git` extension."), - }) - + repo: z + .string() + .describe("The name of the repository without the `.git` extension."), + }); customAction = await vercelAIToolSet.createAction({ actionName: "starRepositoryCustomAction", toolName: "github", description: "Star A Github Repository For Given `Repo` And `Owner`", inputParams: params, - callback: async ( - inputParams, - ) => ({ successful: true, data: inputParams }) - }) + callback: async (inputParams) => ({ + successful: true, + data: inputParams, + }), + }); tools = await vercelAIToolSet.getTools({ actions: ["starRepositoryCustomAction"], }); - }); it("check if custom actions are coming", async () => { @@ -66,14 +66,12 @@ describe("Apps class tests", () => { action: customAction.name, params: { owner: "composioHQ", - repo: "composio" + repo: "composio", }, - }) + }); expect(res.successful).toBe(true); expect(res.data).toHaveProperty("owner", "composioHQ"); expect(res.data).toHaveProperty("repo", "composio"); }); - }) - - + }); }); diff --git a/js/src/frameworks/vercel.ts b/js/src/frameworks/vercel.ts index 6236e358bdd..a83fd2b0951 100644 --- a/js/src/frameworks/vercel.ts +++ b/js/src/frameworks/vercel.ts @@ -1,4 +1,4 @@ -import { jsonSchema, tool, CoreTool } from "ai"; +import { CoreTool, jsonSchema, tool } from "ai"; import { z } from "zod"; import { ComposioToolSet as BaseComposioToolSet } from "../sdk/base.toolset"; import { TELEMETRY_LOGGER } from "../sdk/utils/telemetry"; @@ -84,14 +84,12 @@ export class VercelAIToolSet extends BaseComposioToolSet { tags, useCase, useCaseLimit: usecaseLimit, - filterByAvailableApps - }) + filterByAvailableApps, + }); const tools: { [key: string]: CoreTool } = {}; actionsList.forEach((actionSchema) => { - tools[actionSchema.name!] = this.generateVercelTool( - actionSchema - ); + tools[actionSchema.name!] = this.generateVercelTool(actionSchema); }); return tools; diff --git a/js/src/sdk/actionRegistry.ts b/js/src/sdk/actionRegistry.ts index 5eff37e3393..62b1da40f5a 100644 --- a/js/src/sdk/actionRegistry.ts +++ b/js/src/sdk/actionRegistry.ts @@ -18,19 +18,17 @@ type RawExecuteRequestParam = { }; }; - -type ValidParameters = ZodObject<{ [key: string]: ZodString | ZodOptional }> -export type Parameters = ValidParameters | z.ZodObject<{}> +type ValidParameters = ZodObject<{ + [key: string]: ZodString | ZodOptional; +}>; +export type Parameters = ValidParameters | z.ZodObject<{}>; type inferParameters = PARAMETERS extends ValidParameters - ? z.infer - : z.infer> - + ? z.infer + : z.infer>; -export type CreateActionOptions< - P extends Parameters = z.ZodObject<{}> -> = { +export type CreateActionOptions

> = { actionName?: string; toolName?: string; description?: string; @@ -64,7 +62,7 @@ export class ActionRegistry { string, { metadata: CreateActionOptions; - schema: Record + schema: Record; } >; @@ -73,8 +71,9 @@ export class ActionRegistry { this.customActions = new Map(); } - - async createAction

>(options: CreateActionOptions

): Promise { + async createAction

>( + options: CreateActionOptions

+ ): Promise { const { callback } = options; if (typeof callback !== "function") { throw new Error("Callback must be a function"); @@ -83,7 +82,7 @@ export class ActionRegistry { throw new Error("You must provide actionName for this action"); } if (!options.inputParams) { - options.inputParams = z.object({}) as P + options.inputParams = z.object({}) as P; } const params = options.inputParams; const actionName = options.actionName || callback.name || ""; diff --git a/js/src/sdk/base.toolset.spec.ts b/js/src/sdk/base.toolset.spec.ts index ad7520ef2db..1d16d95f13d 100644 --- a/js/src/sdk/base.toolset.spec.ts +++ b/js/src/sdk/base.toolset.spec.ts @@ -156,7 +156,7 @@ describe("ComposioToolSet class tests", () => { expect(executionResultAfterRemove.data.title).toBe("Test issue"); }); - it("should execute an file upload", async () => { + it.failing("should execute an file upload", async () => { const ACTION_NAME = "GMAIL_SEND_EMAIL"; const actions = await toolset.getToolsSchema({ actions: [ACTION_NAME] }); diff --git a/js/src/sdk/base.toolset.ts b/js/src/sdk/base.toolset.ts index 454f5e7e869..08b20f4021d 100644 --- a/js/src/sdk/base.toolset.ts +++ b/js/src/sdk/base.toolset.ts @@ -1,4 +1,4 @@ -import { z, ZodObject } from "zod"; +import { z } from "zod"; import { Composio } from "../sdk"; import { RawActionData, @@ -10,7 +10,11 @@ import { } from "../types/base_toolset"; import type { Optional, Sequence } from "../types/util"; import { getEnvVariable } from "../utils/shared"; -import { ActionRegistry, CreateActionOptions, Parameters } from "./actionRegistry"; +import { + ActionRegistry, + CreateActionOptions, + Parameters, +} from "./actionRegistry"; import { ActionExecutionResDto } from "./client/types.gen"; import { ActionExecuteResponse, Actions } from "./models/actions"; import { ActiveTriggers } from "./models/activeTriggers"; @@ -54,10 +58,10 @@ export class ComposioToolSet { post: TPostProcessor[]; schema: TSchemaProcessor[]; } = { - pre: [fileInputProcessor], - post: [fileResponseProcessor], - schema: [fileSchemaProcessor], - }; + pre: [fileInputProcessor], + post: [fileResponseProcessor], + schema: [fileSchemaProcessor], + }; private userDefinedProcessors: { pre?: TPreProcessor; @@ -172,7 +176,9 @@ export class ComposioToolSet { }); } - async createAction

>(options: CreateActionOptions

) { + async createAction

>( + options: CreateActionOptions

+ ) { return this.userActionRegistry.createAction

(options); } From 4b539a38eae4267eabe805362ce9d098b1b66190 Mon Sep 17 00:00:00 2001 From: Viraj <35092918+angrybayblade@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:57:13 +0530 Subject: [PATCH 15/34] fix: use app filter when fetching integrations for `initiate_connection` (#1182) --- python/composio/client/collections.py | 38 ++++++++++++++++++++++++--- python/composio/tools/toolset.py | 10 ++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/python/composio/client/collections.py b/python/composio/client/collections.py index 4792664f2fe..d4403e8744e 100644 --- a/python/composio/client/collections.py +++ b/python/composio/client/collections.py @@ -1491,13 +1491,28 @@ def remove(self, id: str) -> None: self.client.http.delete(url=str(self.endpoint / id)) @t.overload # type: ignore - def get(self) -> t.List[IntegrationModel]: ... + def get( + self, + *, + page_size: t.Optional[int] = None, + page: t.Optional[int] = None, + app_id: t.Optional[str] = None, + app_name: t.Optional[str] = None, + show_disabled: t.Optional[bool] = None, + ) -> t.List[IntegrationModel]: ... @t.overload def get(self, id: t.Optional[str] = None) -> IntegrationModel: ... def get( - self, id: t.Optional[str] = None + self, + id: t.Optional[str] = None, + *, + page_size: t.Optional[int] = None, + page: t.Optional[int] = None, + app_id: t.Optional[str] = None, + app_name: t.Optional[str] = None, + show_disabled: t.Optional[bool] = None, ) -> t.Union[t.List[IntegrationModel], IntegrationModel]: if id is not None: return IntegrationModel( @@ -1505,7 +1520,24 @@ def get( self.client.http.get(url=str(self.endpoint / id)) ).json() ) - return super().get({}) + + quries = {} + if page_size is not None: + quries["pageSize"] = json.dumps(page_size) + + if page is not None: + quries["page"] = json.dumps(page) + + if app_id is not None: + quries["appId"] = app_id + + if app_name is not None: + quries["appName"] = app_name + + if show_disabled is not None: + quries["showDisabled"] = json.dumps(show_disabled) + + return super().get(queries=quries) @te.deprecated("`get_id` is deprecated, use `get(id=id)`") def get_by_id( diff --git a/python/composio/tools/toolset.py b/python/composio/tools/toolset.py index f738d1f80dc..6ed7b1f929d 100644 --- a/python/composio/tools/toolset.py +++ b/python/composio/tools/toolset.py @@ -1341,8 +1341,12 @@ def get_integrations( self, app: t.Optional[AppType] = None, auth_scheme: t.Optional[AuthSchemeType] = None, + fetch_disabled: bool = False, ) -> t.List[IntegrationModel]: - integrations = self.client.integrations.get() + integrations = self.client.integrations.get( + show_disabled=fetch_disabled, + page_size=999, + ) if app is not None: app = str(app).lower() integrations = [i for i in integrations if i.appName.lower() == app] @@ -1350,7 +1354,7 @@ def get_integrations( if auth_scheme is not None: integrations = [i for i in integrations if i.authScheme == auth_scheme] - return integrations + return sorted(integrations, key=lambda x: x.createdAt) def get_connected_account(self, id: str) -> ConnectedAccountModel: return self.client.connected_accounts.get(connection_id=id) @@ -1405,7 +1409,7 @@ def _get_integration_for_app( app: AppType, auth_scheme: t.Optional[str] = None, ) -> IntegrationModel: - for integration in sorted(self.get_integrations(), key=lambda x: x.createdAt): + for integration in reversed(self.get_integrations(app=app)): if integration.appName.lower() == str(app).lower(): if ( auth_scheme is not None From f73d58ed45f3e1e70c8a3e4ee939b00a7054b719 Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Tue, 14 Jan 2025 11:35:17 +0530 Subject: [PATCH 16/34] fix: ENG-3490 (#1186) --- js/src/sdk/utils/errors/index.ts | 3 ++- js/src/utils/external.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/js/src/sdk/utils/errors/index.ts b/js/src/sdk/utils/errors/index.ts index 766c02b5796..6b7514a232d 100644 --- a/js/src/sdk/utils/errors/index.ts +++ b/js/src/sdk/utils/errors/index.ts @@ -1,4 +1,5 @@ import { sendBrowserReq, sendProcessReq } from "../../../utils/external"; +import logger from "../../../utils/logger"; import { getEnvVariable } from "../../../utils/shared"; import ComposioSDKContext from "../composioContext"; import { TELEMETRY_URL } from "../constants"; @@ -39,7 +40,7 @@ export async function logError(payload: ErrorPayload) { } } catch (error) { // eslint-disable-next-line no-console - console.error("Error sending error to telemetry", error); + logger.debug("Error sending error to telemetry", error); // DO NOTHING } } diff --git a/js/src/utils/external.ts b/js/src/utils/external.ts index 13d631ac7fc..4d790a5304c 100644 --- a/js/src/utils/external.ts +++ b/js/src/utils/external.ts @@ -75,7 +75,7 @@ export function sendProcessReq(info: { // // Close the stdin stream child.stdin.end(); } catch (error) { - logger.error("Error sending error to telemetry", error); + logger.debug("Error sending error to telemetry", error); // DO NOTHING } } @@ -120,7 +120,7 @@ export function sendBrowserReq(info: { // Send the reporting payload as a JSON string xhr.send(JSON.stringify(info.data)); } catch (error) { - logger.error("Error sending error to telemetry", error); + logger.debug("Error sending error to telemetry", error); // DO NOTHING } } From 3c8aeb71dac195482aa72caf24053524bacad2ed Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Tue, 14 Jan 2025 12:00:47 +0530 Subject: [PATCH 17/34] fix: langchain and remove failing test check (#1187) --- js/src/frameworks/langchain.ts | 2 +- js/src/sdk/base.toolset.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/frameworks/langchain.ts b/js/src/frameworks/langchain.ts index 3d0eca25609..926177fbba0 100644 --- a/js/src/frameworks/langchain.ts +++ b/js/src/frameworks/langchain.ts @@ -34,7 +34,7 @@ export class LangchainToolSet extends BaseComposioToolSet { super({ apiKey: config.apiKey || null, baseUrl: config.baseUrl || COMPOSIO_BASE_URL, - runtime: config?.runtime || null, + runtime: config?.runtime || LangchainToolSet.FRAMEWORK_NAME, entityId: config.entityId || LangchainToolSet.DEFAULT_ENTITY_ID, }); } diff --git a/js/src/sdk/base.toolset.spec.ts b/js/src/sdk/base.toolset.spec.ts index 1d16d95f13d..ad7520ef2db 100644 --- a/js/src/sdk/base.toolset.spec.ts +++ b/js/src/sdk/base.toolset.spec.ts @@ -156,7 +156,7 @@ describe("ComposioToolSet class tests", () => { expect(executionResultAfterRemove.data.title).toBe("Test issue"); }); - it.failing("should execute an file upload", async () => { + it("should execute an file upload", async () => { const ACTION_NAME = "GMAIL_SEND_EMAIL"; const actions = await toolset.getToolsSchema({ actions: [ACTION_NAME] }); From d562d3f3a7590a285e8109cdb83c55b8d92057cf Mon Sep 17 00:00:00 2001 From: Karan Vaidya Date: Wed, 15 Jan 2025 00:45:29 +0530 Subject: [PATCH 18/34] Add autogen tools new version (#1190) --- python/composio/client/enums/action.pyi | 7 ++ python/composio/client/enums/app.pyi | 1 + python/composio/client/enums/tag.pyi | 2 + python/plugins/autogen/autogen_demo_2.py | 45 +++++++ .../autogen/composio_autogen/toolset.py | 113 +++++++++++++++++- python/plugins/autogen/setup.py | 2 + 6 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 python/plugins/autogen/autogen_demo_2.py diff --git a/python/composio/client/enums/action.pyi b/python/composio/client/enums/action.pyi index fd103d0e883..7a6f983ae38 100644 --- a/python/composio/client/enums/action.pyi +++ b/python/composio/client/enums/action.pyi @@ -1594,6 +1594,7 @@ class Action(Enum[ActionData], metaclass=EnumGenerator): CAL_GET_EVENT_TYPE_BY_TEAM_ID: "Action" CAL_GET_GOOGLE_CALENDAR_OAUTH_AUTHENTICATION_URL: "Action" CAL_GET_OAUTH_CLIENTS_USER: "Action" + CAL_GET_ORGANIZATION_ID: "Action" CAL_GET_ORGANIZATION_SCHEDULES: "Action" CAL_GET_ORGANIZATION_TEAMS_EVENT_TYPES: "Action" CAL_GET_ORGANIZATION_USER_SCHEDULES: "Action" @@ -1921,6 +1922,7 @@ class Action(Enum[ActionData], metaclass=EnumGenerator): CODE_ANALYSIS_TOOL_GET_METHOD_SIGNATURE: "Action" CODE_ANALYSIS_TOOL_GET_RELEVANT_CODE: "Action" CODE_FORMAT_TOOL_FORMAT_AND_LINT_CODEBASE: "Action" + COMPOSIO_ADVANCED_USE_CASE_SEARCH: "Action" COMPOSIO_CHECK_ACTIVE_CONNECTION: "Action" COMPOSIO_ENABLE_TRIGGER: "Action" COMPOSIO_EXECUTE_ACTION: "Action" @@ -8039,6 +8041,11 @@ class Action(Enum[ActionData], metaclass=EnumGenerator): TWITTER_USER_LOOKUP_BY_USERNAME: "Action" TWITTER_USER_LOOKUP_BY_USERNAMES: "Action" TWITTER_USER_LOOKUP_ME: "Action" + TYPEFULLY_CREATE_DRAFT: "Action" + TYPEFULLY_GET_NOTIFICATIONS: "Action" + TYPEFULLY_GET_RECENTLY_PUBLISHED: "Action" + TYPEFULLY_GET_RECENTLY_SCHEDULED: "Action" + TYPEFULLY_MARK_NOTIFICATIONS_READ: "Action" WEATHERMAP_WEATHER: "Action" WEBTOOL_SCRAPE_WEBSITE_CONTENT: "Action" WEBTOOL_SCRAPE_WEBSITE_ELEMENT: "Action" diff --git a/python/composio/client/enums/app.pyi b/python/composio/client/enums/app.pyi index 593a665a785..60450a3f2c4 100644 --- a/python/composio/client/enums/app.pyi +++ b/python/composio/client/enums/app.pyi @@ -261,6 +261,7 @@ class App(Enum[AppData], metaclass=EnumGenerator): TWITCH: "App" TWITTER: "App" TWITTER_MEDIA: "App" + TYPEFULLY: "App" VENLY: "App" VERO: "App" VISME: "App" diff --git a/python/composio/client/enums/tag.pyi b/python/composio/client/enums/tag.pyi index feef75d3766..652033192eb 100644 --- a/python/composio/client/enums/tag.pyi +++ b/python/composio/client/enums/tag.pyi @@ -1123,6 +1123,8 @@ class Tag(Enum[TagData], metaclass=EnumGenerator): TWITTER_TWEETS: "Tag" TWITTER_USAGE: "Tag" TWITTER_USERS: "Tag" + TYPEFULLY_DRAFTS: "Tag" + TYPEFULLY_NOTIFICATIONS: "Tag" WRIKE_ACCOUNTS: "Tag" WRIKE_CONTACTS: "Tag" WRIKE_CUSTOM_FIELDS: "Tag" diff --git a/python/plugins/autogen/autogen_demo_2.py b/python/plugins/autogen/autogen_demo_2.py new file mode 100644 index 00000000000..50c3d4d743c --- /dev/null +++ b/python/plugins/autogen/autogen_demo_2.py @@ -0,0 +1,45 @@ +""" +Autogen demo using get_tools() approach. +""" + +import asyncio +import os + +import dotenv +from autogen_agentchat.agents import AssistantAgent +from autogen_core import CancellationToken +from autogen_ext.models.openai import OpenAIChatCompletionClient + +from composio_autogen import App, ComposioToolSet + + +async def main(): + # Initialize toolset and get tools + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.GITHUB]) + + model_client = OpenAIChatCompletionClient( + model="gpt-4", + api_key=os.environ["OPENAI_API_KEY"], + ) + # Create assistant agent with tools + assistant = AssistantAgent( + name="github_assistant", + system_message=( + "You are an AI assistant that helps with GitHub tasks. " + "Use the provided tools to interact with GitHub." + ), + model_client=model_client, + tools=list(tools), + ) + + # Define task and initiate chat + task = "Star the repository composiohq/composio on GitHub" + result = await assistant.run(task=task, cancellation_token=CancellationToken()) + print(result) + + +if __name__ == "__main__": + # Load environment variables from .env + dotenv.load_dotenv() + asyncio.run(main()) diff --git a/python/plugins/autogen/composio_autogen/toolset.py b/python/plugins/autogen/composio_autogen/toolset.py index c7ddf2243f7..55c11bfe03d 100644 --- a/python/plugins/autogen/composio_autogen/toolset.py +++ b/python/plugins/autogen/composio_autogen/toolset.py @@ -6,9 +6,11 @@ import autogen import typing_extensions as te from autogen.agentchat.conversable_agent import ConversableAgent +from autogen_core.tools import FunctionTool from composio import Action, ActionType, AppType, TagType from composio.tools import ComposioToolSet as BaseComposioToolSet +from composio.tools.toolset import ProcessorsType from composio.utils.shared import get_signature_format_from_schema_params @@ -137,10 +139,14 @@ def execute_action(**kwargs: t.Any) -> t.Dict: ), closure=execute_action.__closure__, ) - function.__signature__ = Signature( # type: ignore - parameters=get_signature_format_from_schema_params( - schema_params=schema["parameters"], - ), + params = get_signature_format_from_schema_params( + schema_params=schema["parameters"], + ) + setattr(function, "__signature__", Signature(parameters=params)) + setattr( + function, + "__annotations__", + {p.name: p.annotation for p in params} | {"return": t.Dict[str, t.Any]}, ) function.__doc__ = ( description if description else f"Action {name} from {appName}" @@ -154,3 +160,102 @@ def execute_action(**kwargs: t.Any) -> t.Dict: ), description=description if description else f"Action {name} from {appName}", ) + + def _wrap_tool( + self, + schema: t.Dict[str, t.Any], + entity_id: t.Optional[str] = None, + ) -> FunctionTool: + """ + Wraps a composio action as an Autogen FunctionTool. + + Args: + schema: The action schema to wrap + entity_id: Optional entity ID for executing function calls + + Returns: + FunctionTool: Wrapped function as an Autogen FunctionTool + """ + name = schema["name"] + description = schema["description"] or f"Action {name} from {schema['appName']}" + + def execute_action(**kwargs: t.Any) -> t.Dict: + """Placeholder function for executing action.""" + return self.execute_action( + action=Action(value=name), + params=kwargs, + entity_id=entity_id or self.entity_id, + _check_requested_actions=True, + ) + + # Create function with proper signature + function = types.FunctionType( + code=execute_action.__code__, + globals=globals(), + name=self._process_function_name_for_registration(input_string=name), + closure=execute_action.__closure__, + ) + + # Set signature and annotations + params = get_signature_format_from_schema_params( + schema_params=schema["parameters"] + ) + setattr(function, "__signature__", Signature(parameters=params)) + setattr( + function, + "__annotations__", + {p.name: p.annotation for p in params} | {"return": t.Dict[str, t.Any]}, + ) + function.__doc__ = description + + return FunctionTool( + func=function, + description=description, + name=self._process_function_name_for_registration(input_string=name), + ) + + def get_tools( + self, + actions: t.Optional[t.Sequence[ActionType]] = None, + apps: t.Optional[t.Sequence[AppType]] = None, + tags: t.Optional[t.List[TagType]] = None, + entity_id: t.Optional[str] = None, + *, + processors: t.Optional[ProcessorsType] = None, + check_connected_accounts: bool = True, + ) -> t.Sequence[FunctionTool]: + """ + Get composio tools as Autogen FunctionTool objects. + + Args: + actions: List of actions to wrap + apps: List of apps to wrap + tags: Filter apps by given tags + entity_id: Entity ID for function wrapper + processors: Optional dict of processors to merge + check_connected_accounts: Whether to check for connected accounts + + Returns: + List of Autogen FunctionTool objects + """ + self.validate_tools(apps=apps, actions=actions, tags=tags) + if processors is not None: + self._merge_processors(processors) + + tools = [ + self._wrap_tool( + schema=tool.model_dump( + exclude_none=True, + ), + entity_id=entity_id or self.entity_id, + ) + for tool in self.get_action_schemas( + actions=actions, + apps=apps, + tags=tags, + check_connected_accounts=check_connected_accounts, + _populate_requested=True, + ) + ] + + return tools diff --git a/python/plugins/autogen/setup.py b/python/plugins/autogen/setup.py index be453caccf6..559486eb9a4 100644 --- a/python/plugins/autogen/setup.py +++ b/python/plugins/autogen/setup.py @@ -26,6 +26,8 @@ "composio_core>=0.6.11,<0.7.0", "pyautogen>=0.2.19", "flaml==2.2.0", + "autogen_core>=0.4.0", + "autogen_agentchat>=0.4.0", ], include_package_data=True, ) From 1c65530edc44ed45a151837244337661298460ed Mon Sep 17 00:00:00 2001 From: Karan Vaidya Date: Wed, 15 Jan 2025 00:48:39 +0530 Subject: [PATCH 19/34] Update release (#1191) --- python/composio/__version__.py | 2 +- python/dockerfiles/Dockerfile | 2 +- python/plugins/autogen/setup.py | 2 +- python/plugins/camel/setup.py | 2 +- python/plugins/claude/setup.py | 2 +- python/plugins/crew_ai/setup.py | 2 +- python/plugins/google/setup.py | 2 +- python/plugins/griptape/setup.py | 2 +- python/plugins/julep/setup.py | 2 +- python/plugins/langchain/setup.py | 2 +- python/plugins/langgraph/setup.py | 2 +- python/plugins/llamaindex/setup.py | 2 +- python/plugins/lyzr/setup.py | 2 +- python/plugins/openai/setup.py | 2 +- python/plugins/phidata/setup.py | 2 +- python/plugins/praisonai/setup.py | 2 +- python/setup.py | 2 +- python/swe/setup.py | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/python/composio/__version__.py b/python/composio/__version__.py index c98d6e334ac..2e77e107345 100644 --- a/python/composio/__version__.py +++ b/python/composio/__version__.py @@ -1 +1 @@ -__version__ = "0.6.13" +__version__ = "0.6.14" diff --git a/python/dockerfiles/Dockerfile b/python/dockerfiles/Dockerfile index da8e6d68cd2..ddb87446110 100644 --- a/python/dockerfiles/Dockerfile +++ b/python/dockerfiles/Dockerfile @@ -19,7 +19,7 @@ RUN /bin/python3 -m venv .composio/venv RUN export PATH=$PATH:$(pwd)/.composio/venv/bin # Install composio -RUN python -m pip install composio-core[all]==0.6.13 fastapi playwright uvicorn +RUN python -m pip install composio-core[all]==0.6.14 fastapi playwright uvicorn # Install playwright deps RUN playwright install-deps diff --git a/python/plugins/autogen/setup.py b/python/plugins/autogen/setup.py index 559486eb9a4..d19b1a5ac2b 100644 --- a/python/plugins/autogen/setup.py +++ b/python/plugins/autogen/setup.py @@ -9,7 +9,7 @@ setup( name="composio_autogen", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Autogen agent.", diff --git a/python/plugins/camel/setup.py b/python/plugins/camel/setup.py index 54647372059..b3c9abca91a 100644 --- a/python/plugins/camel/setup.py +++ b/python/plugins/camel/setup.py @@ -9,7 +9,7 @@ setup( name="composio_camel", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Claude LLMs.", diff --git a/python/plugins/claude/setup.py b/python/plugins/claude/setup.py index a396547d746..7092cca1cce 100644 --- a/python/plugins/claude/setup.py +++ b/python/plugins/claude/setup.py @@ -9,7 +9,7 @@ setup( name="composio_claude", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Claude LLMs.", diff --git a/python/plugins/crew_ai/setup.py b/python/plugins/crew_ai/setup.py index d72912100c8..a50e739d55a 100644 --- a/python/plugins/crew_ai/setup.py +++ b/python/plugins/crew_ai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_crewai", - version="0.6.13", + version="0.6.14", author="Himanshu", author_email="himanshu@composio.dev", description="Use Composio to get an array of tools with your CrewAI agent.", diff --git a/python/plugins/google/setup.py b/python/plugins/google/setup.py index 6b0af19c90a..df6d65904a7 100644 --- a/python/plugins/google/setup.py +++ b/python/plugins/google/setup.py @@ -9,7 +9,7 @@ setup( name="composio_google", - version="0.6.13", + version="0.6.14", author="Assistant", author_email="karan@composio.dev", description="Use Composio to get an array of tools with your Google AI Python Gemini model.", diff --git a/python/plugins/griptape/setup.py b/python/plugins/griptape/setup.py index a1aded401ce..f0f5e04a27c 100644 --- a/python/plugins/griptape/setup.py +++ b/python/plugins/griptape/setup.py @@ -9,7 +9,7 @@ setup( name="composio_griptape", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Griptape workflow.", diff --git a/python/plugins/julep/setup.py b/python/plugins/julep/setup.py index fe10a68d8d3..60c69b99692 100644 --- a/python/plugins/julep/setup.py +++ b/python/plugins/julep/setup.py @@ -9,7 +9,7 @@ setup( name="composio_julep", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Julep workflow.", diff --git a/python/plugins/langchain/setup.py b/python/plugins/langchain/setup.py index 99df877ef41..5900816af11 100644 --- a/python/plugins/langchain/setup.py +++ b/python/plugins/langchain/setup.py @@ -9,7 +9,7 @@ setup( name="composio_langchain", - version="0.6.13", + version="0.6.14", author="Karan", author_email="karan@composio.dev", description="Use Composio to get an array of tools with your LangChain agent.", diff --git a/python/plugins/langgraph/setup.py b/python/plugins/langgraph/setup.py index 121233d6cbf..940b0499581 100644 --- a/python/plugins/langgraph/setup.py +++ b/python/plugins/langgraph/setup.py @@ -9,7 +9,7 @@ setup( name="composio_langgraph", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get array of tools with LangGraph Agent Workflows", diff --git a/python/plugins/llamaindex/setup.py b/python/plugins/llamaindex/setup.py index e61e346db9e..4367cd402b5 100644 --- a/python/plugins/llamaindex/setup.py +++ b/python/plugins/llamaindex/setup.py @@ -9,7 +9,7 @@ setup( name="composio_llamaindex", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your LlamaIndex agent.", diff --git a/python/plugins/lyzr/setup.py b/python/plugins/lyzr/setup.py index ee70e18e5bc..51ed7a21a3e 100644 --- a/python/plugins/lyzr/setup.py +++ b/python/plugins/lyzr/setup.py @@ -9,7 +9,7 @@ setup( name="composio_lyzr", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Lyzr workflow.", diff --git a/python/plugins/openai/setup.py b/python/plugins/openai/setup.py index 504b2a57fcd..fc8fddf2a50 100644 --- a/python/plugins/openai/setup.py +++ b/python/plugins/openai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_openai", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your OpenAI Function Call.", diff --git a/python/plugins/phidata/setup.py b/python/plugins/phidata/setup.py index 64b27d5cd3a..3968d625ad2 100644 --- a/python/plugins/phidata/setup.py +++ b/python/plugins/phidata/setup.py @@ -9,7 +9,7 @@ setup( name="composio_phidata", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Phidata Plugin.", diff --git a/python/plugins/praisonai/setup.py b/python/plugins/praisonai/setup.py index 3833620d473..a69797c871e 100644 --- a/python/plugins/praisonai/setup.py +++ b/python/plugins/praisonai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_praisonai", - version="0.6.13", + version="0.6.14", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio Tools to enhance your PraisonAI agents capabilities.", diff --git a/python/setup.py b/python/setup.py index a805aff4b06..2ab84bf2155 100644 --- a/python/setup.py +++ b/python/setup.py @@ -88,7 +88,7 @@ def scan_for_package_data( setup( name="composio_core", - version="0.6.13", + version="0.6.14", author="Utkarsh", author_email="utkarsh@composio.dev", description="Core package to act as a bridge between composio platform and other services.", diff --git a/python/swe/setup.py b/python/swe/setup.py index d1b898ec25d..69aa8c54d28 100644 --- a/python/swe/setup.py +++ b/python/swe/setup.py @@ -35,7 +35,7 @@ def scan_for_package_data( setup( name="swekit", - version="0.3.14", + version="0.3.15", author="Shubhra", author_email="shubhra@composio.dev", description="Tools for running a SWE agent using Composio platform", From 6905ceb5537244327b4ebd101c445722219014a6 Mon Sep 17 00:00:00 2001 From: Utkarsh Dixit Date: Wed, 15 Jan 2025 11:38:02 +0530 Subject: [PATCH 20/34] feat: add refresh_token in AuthConnectionParamsModel (#1192) Co-authored-by: Viraj <35092918+angrybayblade@users.noreply.github.com> --- python/composio/__version__.py | 2 +- python/composio/client/collections.py | 1 + python/dockerfiles/Dockerfile | 2 +- python/plugins/autogen/setup.py | 2 +- python/plugins/camel/setup.py | 2 +- python/plugins/claude/setup.py | 2 +- python/plugins/crew_ai/setup.py | 2 +- python/plugins/google/setup.py | 2 +- python/plugins/griptape/setup.py | 2 +- python/plugins/julep/setup.py | 2 +- python/plugins/langchain/setup.py | 2 +- python/plugins/langgraph/setup.py | 2 +- python/plugins/llamaindex/setup.py | 2 +- python/plugins/lyzr/setup.py | 2 +- python/plugins/openai/setup.py | 2 +- python/plugins/phidata/setup.py | 2 +- python/plugins/praisonai/setup.py | 2 +- python/setup.py | 2 +- python/swe/setup.py | 2 +- 19 files changed, 19 insertions(+), 18 deletions(-) diff --git a/python/composio/__version__.py b/python/composio/__version__.py index 2e77e107345..c69cd12ff30 100644 --- a/python/composio/__version__.py +++ b/python/composio/__version__.py @@ -1 +1 @@ -__version__ = "0.6.14" +__version__ = "0.6.15" diff --git a/python/composio/client/collections.py b/python/composio/client/collections.py index d4403e8744e..37cab4c7f0e 100644 --- a/python/composio/client/collections.py +++ b/python/composio/client/collections.py @@ -69,6 +69,7 @@ class AuthConnectionParamsModel(BaseModel): client_id: t.Optional[str] = None token_type: t.Optional[str] = None access_token: t.Optional[str] = None + refresh_token: t.Optional[str] = None client_secret: t.Optional[str] = None consumer_id: t.Optional[str] = None consumer_secret: t.Optional[str] = None diff --git a/python/dockerfiles/Dockerfile b/python/dockerfiles/Dockerfile index ddb87446110..edb994dae6d 100644 --- a/python/dockerfiles/Dockerfile +++ b/python/dockerfiles/Dockerfile @@ -19,7 +19,7 @@ RUN /bin/python3 -m venv .composio/venv RUN export PATH=$PATH:$(pwd)/.composio/venv/bin # Install composio -RUN python -m pip install composio-core[all]==0.6.14 fastapi playwright uvicorn +RUN python -m pip install composio-core[all]==0.6.15 fastapi playwright uvicorn # Install playwright deps RUN playwright install-deps diff --git a/python/plugins/autogen/setup.py b/python/plugins/autogen/setup.py index d19b1a5ac2b..0d13867a9fc 100644 --- a/python/plugins/autogen/setup.py +++ b/python/plugins/autogen/setup.py @@ -9,7 +9,7 @@ setup( name="composio_autogen", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Autogen agent.", diff --git a/python/plugins/camel/setup.py b/python/plugins/camel/setup.py index b3c9abca91a..f66cb36c2a7 100644 --- a/python/plugins/camel/setup.py +++ b/python/plugins/camel/setup.py @@ -9,7 +9,7 @@ setup( name="composio_camel", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Claude LLMs.", diff --git a/python/plugins/claude/setup.py b/python/plugins/claude/setup.py index 7092cca1cce..a69eceff19f 100644 --- a/python/plugins/claude/setup.py +++ b/python/plugins/claude/setup.py @@ -9,7 +9,7 @@ setup( name="composio_claude", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Claude LLMs.", diff --git a/python/plugins/crew_ai/setup.py b/python/plugins/crew_ai/setup.py index a50e739d55a..e8ad426c73d 100644 --- a/python/plugins/crew_ai/setup.py +++ b/python/plugins/crew_ai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_crewai", - version="0.6.14", + version="0.6.15", author="Himanshu", author_email="himanshu@composio.dev", description="Use Composio to get an array of tools with your CrewAI agent.", diff --git a/python/plugins/google/setup.py b/python/plugins/google/setup.py index df6d65904a7..07d09aeb77c 100644 --- a/python/plugins/google/setup.py +++ b/python/plugins/google/setup.py @@ -9,7 +9,7 @@ setup( name="composio_google", - version="0.6.14", + version="0.6.15", author="Assistant", author_email="karan@composio.dev", description="Use Composio to get an array of tools with your Google AI Python Gemini model.", diff --git a/python/plugins/griptape/setup.py b/python/plugins/griptape/setup.py index f0f5e04a27c..d3c8738387f 100644 --- a/python/plugins/griptape/setup.py +++ b/python/plugins/griptape/setup.py @@ -9,7 +9,7 @@ setup( name="composio_griptape", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Griptape workflow.", diff --git a/python/plugins/julep/setup.py b/python/plugins/julep/setup.py index 60c69b99692..9e4d75be0e5 100644 --- a/python/plugins/julep/setup.py +++ b/python/plugins/julep/setup.py @@ -9,7 +9,7 @@ setup( name="composio_julep", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Julep workflow.", diff --git a/python/plugins/langchain/setup.py b/python/plugins/langchain/setup.py index 5900816af11..e5db5469a74 100644 --- a/python/plugins/langchain/setup.py +++ b/python/plugins/langchain/setup.py @@ -9,7 +9,7 @@ setup( name="composio_langchain", - version="0.6.14", + version="0.6.15", author="Karan", author_email="karan@composio.dev", description="Use Composio to get an array of tools with your LangChain agent.", diff --git a/python/plugins/langgraph/setup.py b/python/plugins/langgraph/setup.py index 940b0499581..4b3f98ae4c1 100644 --- a/python/plugins/langgraph/setup.py +++ b/python/plugins/langgraph/setup.py @@ -9,7 +9,7 @@ setup( name="composio_langgraph", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get array of tools with LangGraph Agent Workflows", diff --git a/python/plugins/llamaindex/setup.py b/python/plugins/llamaindex/setup.py index 4367cd402b5..9ce3d8b1d32 100644 --- a/python/plugins/llamaindex/setup.py +++ b/python/plugins/llamaindex/setup.py @@ -9,7 +9,7 @@ setup( name="composio_llamaindex", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your LlamaIndex agent.", diff --git a/python/plugins/lyzr/setup.py b/python/plugins/lyzr/setup.py index 51ed7a21a3e..496cbb828d6 100644 --- a/python/plugins/lyzr/setup.py +++ b/python/plugins/lyzr/setup.py @@ -9,7 +9,7 @@ setup( name="composio_lyzr", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Lyzr workflow.", diff --git a/python/plugins/openai/setup.py b/python/plugins/openai/setup.py index fc8fddf2a50..91b1fa60676 100644 --- a/python/plugins/openai/setup.py +++ b/python/plugins/openai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_openai", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your OpenAI Function Call.", diff --git a/python/plugins/phidata/setup.py b/python/plugins/phidata/setup.py index 3968d625ad2..ee0222e6f99 100644 --- a/python/plugins/phidata/setup.py +++ b/python/plugins/phidata/setup.py @@ -9,7 +9,7 @@ setup( name="composio_phidata", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Phidata Plugin.", diff --git a/python/plugins/praisonai/setup.py b/python/plugins/praisonai/setup.py index a69797c871e..a08edf0a69a 100644 --- a/python/plugins/praisonai/setup.py +++ b/python/plugins/praisonai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_praisonai", - version="0.6.14", + version="0.6.15", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio Tools to enhance your PraisonAI agents capabilities.", diff --git a/python/setup.py b/python/setup.py index 2ab84bf2155..0e0eea738cb 100644 --- a/python/setup.py +++ b/python/setup.py @@ -88,7 +88,7 @@ def scan_for_package_data( setup( name="composio_core", - version="0.6.14", + version="0.6.15", author="Utkarsh", author_email="utkarsh@composio.dev", description="Core package to act as a bridge between composio platform and other services.", diff --git a/python/swe/setup.py b/python/swe/setup.py index 69aa8c54d28..d08872a8695 100644 --- a/python/swe/setup.py +++ b/python/swe/setup.py @@ -35,7 +35,7 @@ def scan_for_package_data( setup( name="swekit", - version="0.3.15", + version="0.3.16", author="Shubhra", author_email="shubhra@composio.dev", description="Tools for running a SWE agent using Composio platform", From 54d08cecb7eec1922c9303796078977c722aa96f Mon Sep 17 00:00:00 2001 From: tushar-composio Date: Wed, 15 Jan 2025 16:04:40 +0530 Subject: [PATCH 21/34] fix: Ensure Sentry is initialized for non logged in users too (#1183) --- python/composio/utils/sentry.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/python/composio/utils/sentry.py b/python/composio/utils/sentry.py index 8f18b9f4896..5ec6c1d31d3 100644 --- a/python/composio/utils/sentry.py +++ b/python/composio/utils/sentry.py @@ -6,6 +6,7 @@ import traceback import types import typing as t +from functools import cache from pathlib import Path import requests @@ -22,6 +23,7 @@ import sentry_sdk.types +@cache def fetch_dsn() -> t.Optional[str]: request = requests.get( url="https://backend.composio.dev/api/v1/cli/sentry-dns", @@ -34,6 +36,9 @@ def fetch_dsn() -> t.Optional[str]: def get_sentry_config() -> t.Optional[t.Dict]: user_file = Path.home() / ".composio" / "user_data.json" + if not user_file.exists(): + update_dsn() + if not user_file.exists(): return None @@ -106,18 +111,15 @@ def init(): @atexit.register def update_dsn() -> None: user_file = Path.home() / ".composio" / "user_data.json" - if not user_file.exists(): - return - - try: - data = json.loads(user_file.read_text(encoding="utf-8")) - except json.JSONDecodeError: - return - - if data.get("api_key") is None: - return - - if data.get("sentry") is not None and data.get("sentry").get("dsn") is not None: + if user_file.exists(): + try: + data = json.loads(user_file.read_text(encoding="utf-8")) + except json.JSONDecodeError: + return + else: + data = {} + + if data.get("sentry", {}).get("dsn") is not None: return dsn = fetch_dsn() @@ -125,4 +127,5 @@ def update_dsn() -> None: return data["sentry"] = {"dsn": dsn} + user_file.parent.mkdir(parents=True, exist_ok=True) user_file.write_text(json.dumps(data), encoding="utf-8") From d34e19cbd807cf11e6095564f1b9a2c74c6339c2 Mon Sep 17 00:00:00 2001 From: Abhishek Patil <83769052+abhishekpatil4@users.noreply.github.com> Date: Wed, 15 Jan 2025 16:48:11 +0530 Subject: [PATCH 22/34] feat/update readme (#1188) --- README-CN.md | 378 ++++++++++++++++++++++++------------------------- README-JP.md | 390 +++++++++++++++++++++++++-------------------------- README.md | 378 ++++++++++++++++++++++++------------------------- 3 files changed, 565 insertions(+), 581 deletions(-) diff --git a/README-CN.md b/README-CN.md index b1a7b8283e9..d67cd1593bc 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,143 +1,127 @@

- EN | CN | JP + 英语 | 中国人 | 日本人

- -

- - Composio 标志 - - - Composio 标志 - + + Composio logo + + + Composio Logo +

- - 测试 - - - PyPI - - - 下载量 - -

- -

- 面向 AI 代理的生产就绪型工具集 -

- -

只需一行代码,即可为您的代理配备高质量的工具和集成,无需担心身份验证、准确性和可靠性! -

- - -
-
-

- ✨ 社交媒体 >> - Discord | - Youtube | - Twitter | - LinkedIn -

- ⛏️ 贡献 >> - 报告错误 | - 请求功能 | - 参与贡献 + + PyPI + + + NPM + + + Downloads +

-
+ +

+ 适用于 AI 代理的生产就绪工具集 +

+ +Illustration + +

什么是Composio?

+

Composio 为 AI 代理提供可用于生产的工具集,提供:

+
    +
  • 支持多个类别的 250 多种工具: +
      +
    • GitHub、Notion、Linear、Gmail、Slack、Hubspot、Salesforce 等软件工具 & + + 更多 + +
    • +
    • 操作系统操作, 包括文件工具、shell 工具、代码分析工具 & + + 更多 + +
    • +
    • 通过 Google、Perplexity、Tavily 和 Exa 实现搜索功能 & + + 更多 + +
    • +
    +
  • +
  • 全面的框架支持,包括 OpenAI、 Groq、Claude、LlamaIndex、Langchain、CrewAI、Autogen、Gemini 以及更多
  • +
  • 支持多种协议 (OAuth、API 密钥、Basic JWT) 的托管身份验证
  • +
  • 通过优化设计将工具调用准确率提高高达 40%
  • +
  • 用于后端集成的白标解决方案
  • +
  • 支持自定义工具和扩展的可插拔架构
  • +
## 📋 目录 -- [📋 目录](#-目录) -- [🤔 为什么选择 Composio?](#-为什么选择-composio) -- [🔥 主要特性](#-主要特性) -- [🚀 Python 快速入门](#-python-快速入门) - - [1. 安装](#1-安装) - - [2. Composio 实战测试](#2-composio-实战测试) -- [🚀 Javascript 快速入门](#-javascript-快速入门) - - [1. **安装 Composio SDK**:](#1-安装-composio-sdk) - - [2. **配置 OpenAI 和 Composio 工具集**:](#2-配置-openai-和-composio-工具集) - - [3. **运行您的脚本**:](#3-运行您的脚本) -- [💡 示例](#-示例) - - [Python](#python) - - [Javascript](#javascript) -- [Star 历史](#star-历史) -- [📋 阅读我们的行为准则](#-阅读我们的行为准则) -- [🤗 贡献](#-贡献) -- [🔗 链接](#-链接) -- [🛡️ 许可证](#️-许可证) -- [💪 感谢所有贡献者](#-感谢所有贡献者) - -## 🤔 为什么选择 Composio? - -我们相信基于 AI 的代理/工作流是未来。 -Composio 是将 AI 代理集成到最佳代理工具并用它们完成任务的最佳工具集。 - -插图 - -## 🔥 主要特性 - -- **100+ 工具**:支持各种不同类别 - - **软件**:在 GitHub、Notion、Linear、Gmail、Slack、Hubspot、Salesforce 等 90 多个平台上执行任何操作。 - - **操作系统**:点击任意位置、输入任何内容、复制到剪贴板等。 - - **浏览器**:智能搜索、截图、MultiOn、下载、上传等。 - - **搜索**:Google 搜索、Perplexity 搜索、Tavily、Exa 等。 - - **软件工程**:Ngrok、数据库、Redis、Vercel、Git 等。 - - **RAG**:即时为任何类型的数据提供代理 RAG! - -- **框架**:通过一行代码在 **OpenAI、Claude、LlamaIndex、Langchain、CrewAI、Autogen、Gemini、Julep、Lyzr** 等代理框架中使用工具。 -- **托管授权**:支持六种不同的身份验证协议。将 _Access Token、Refresh Token、OAuth、API Keys、JWT 等_ 抽象出来,让您专注于构建代理。 -- **准确性**:由于更好的工具设计,您的工具调用的 _代理准确性提高了 40%_。 -- **可嵌入**:在应用程序后端进行白标,为所有用户和代理管理身份验证和集成,保持一致的体验。 -- **可插拔**:设计为可轻松扩展其他工具、框架和身份验证协议。 - -## 🚀 Python 快速入门 +- [Python 入门](#开始使用-python) + - [1. 安装](#1-安装) + - [2. 创建代理并执行工具](#2-创建代理并执行工具) +- [JavaScript 入门](#javascript-入门) + - [1. 安装](#1安装) + - [2.创建代理并执行工具](#2-创建代理并执行工具-1) +- [示例](#示例) + - [Python 示例](#python-示例) + - [JavaScript 示例](#javascript-示例) +- [Star 历史](#星号历史) +- [获取帮助](#获取帮助) +- [贡献](#贡献) +- [请求功能](#请求功能) +- [感谢所有贡献者](#感谢所有贡献者) + +## 开始使用 Python ### 1. 安装 -要开始使用,请在终端中键入以下命令。 +首先安装软件包 ```bash pip install composio-core ``` -如果您想安装带有 openai 插件的 'composio' 包:`pip install composio-openai`。 +安装“composio”包及其 openai 插件 `pip install composio-openai`. + +### 2. 创建代理并执行工具 -### 2. Composio 实战测试 +让我们使用 OpenAI 创建 AI 代理,并使用 Composio 的 GitHub 工具为 GitHub 存储库加注星标 -让我们使用 Composio 创建一个可以为 Github 仓库点赞的 AI 代理。 +> [!NOTE] +> 在您的环境变量中设置您的 COMPOSIO_API_KEY 和 OPENAI_API_KEY. +将你的 GitHub 帐户连接到 Composio ```bash -composio add github # 连接您的 Github - 在终端中运行 +composio add github # Run this in terminal ``` ```python + from openai import OpenAI from composio_openai import ComposioToolSet, App, Action -openai_client = OpenAI( - api_key="{{OPENAIKEY}}" -) +openai_client = OpenAI(api_key="{{OPENAIKEY}}") # 初始化 Composio 工具集 composio_tool_set = ComposioToolSet() -# 获取预配置的 GitHub 工具 +# 获取预先配置的 GitHub 工具 actions = composio_tool_set.get_actions( actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER] ) @@ -158,17 +142,15 @@ assistant = openai_client.beta.assistants.create( thread = openai_client.beta.threads.create() message = openai_client.beta.threads.messages.create( - thread_id=thread.id, - role="user", - content=my_task + thread_id=thread.id, role="user", content=my_task ) # 使用集成执行代理 run = openai_client.beta.threads.runs.create( - thread_id=thread.id, - assistant_id=assistant.id + thread_id=thread.id, assistant_id=assistant.id ) + # 执行函数调用 response_after_tool_calls = composio_tool_set.wait_and_handle_assistant_tool_calls( client=openai_client, @@ -179,104 +161,122 @@ response_after_tool_calls = composio_tool_set.wait_and_handle_assistant_tool_cal print(response_after_tool_calls) ``` -## 🚀 Javascript 快速入门 +## JavaScript 入门 -要在 Javascript 中开始使用 Composio SDK,请按照以下步骤操作: +要开始使用 JavaScript 中的 Composio SDK, 请按照以下步骤操作: -### 1. **安装 Composio SDK**: - ```bash - npm install composio-core - ``` - -### 2. **配置 OpenAI 和 Composio 工具集**: - ```javascript - import { OpenAI } from "openai"; - import { OpenAIToolSet } from "composio-core"; - - const toolset = new OpenAIToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, - }); - - async function setupUserConnectionIfNotExists(entityId) { - const entity = await toolset.client.getEntity(entityId); - const connection = await entity.getConnection('github'); - - if (!connection) { - // 如果此实体/用户尚未连接帐户 - const connection = await entity.initiateConnection(appName); - console.log("通过以下方式登录: ", connection.redirectUrl); - return connection.waitUntilActive(60); - } - - return connection; - } - - async function executeAgent(entityName) { - const entity = await toolset.client.getEntity(entityName) - await setupUserConnectionIfNotExists(entity.id); - - const tools = await toolset.get_actions({ actions: ["github_issues_create"] }, entity.id); - const instruction = "Make an issue with sample title in the repo - himanshu-dixit/custom-repo-breaking" - - const client = new OpenAI({ apiKey: process.env.OPEN_AI_API_KEY }) - const response = await client.chat.completions.create({ - model: "gpt-4-turbo", - messages: [{ - role: "user", - content: instruction, - }], - tools: tools, - tool_choice: "auto", - }) - - console.log(response.choices[0].message.tool_calls); - await toolset.handle_tool_call(response, entity.id); - } - - executeAgent("your-entity-name"); - ``` +### 1.安装: +```bash +npm install composio-core +``` -### 3. **运行您的脚本**: - ```bash - node your_script.js - ``` +### 2. 创建代理并执行工具 -这将设置 Composio SDK 并执行一个使用提供的说明创建 GitHub 问题的代理。 +让我们使用 OpenAI 创建一个 AI 代理,并使用 Composio 的 GitHub 工具来加注 GitHub 存储库 -有关更多详细信息,请参阅 [Composio SDK 文档](https://docs.composio.dev/)。 +> [!NOTE] +> 在您的环境变量中设置您的 COMPOSIO_API_KEY 和 OPENAI_API_KEY。 -## 💡 示例 +将你的 GitHub 帐户连接到 Composio +```bash +composio add github # 在终端中运行 +``` -### [Python](https://docs.composio.dev/guides/python/) +```javascript +import { OpenAIToolSet } from "composio-core"; +import OpenAI from "openai"; + +const toolset = new OpenAIToolSet({ apiKey: process.env.COMPOSIO_API_KEY }); +const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); + +const tools = await toolset.getTools({ actions: ["GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER"] }); + +async function createGithubAssistant(openai, tools) { + return await openai.beta.assistants.create({ + name: "Github Assistant", + instructions: "You're a GitHub Assistant, you can do operations on GitHub", + tools: tools, + model: "gpt-4o" + }); +} + +async function executeAssistantTask(openai, toolset, assistant, task) { + const thread = await openai.beta.threads.create(); + const run = await openai.beta.threads.runs.create(thread.id, { + assistant_id: assistant.id, + instructions: task, + tools: tools, + model: "gpt-4o", + stream: false + }); + const call = await toolset.waitAndHandleAssistantToolCalls(openai, run, thread); + console.log(call); +} + +(async () => { + const githubAssistant = await createGithubAssistant(openai, tools); + await executeAssistantTask( + openai, + toolset, + githubAssistant, + "Star the repository 'composiohq/composio'" + ); +})(); +``` -### [Javascript](https://docs.composio.dev/guides/javascript/) +## 示例 -## Star 历史 +### [Python 示例](https://docs.composio.dev/guides/python/) -[![Star History Chart](https://api.star-history.com/svg?repos=composiohq/composio&type=Date)](https://star-history.com/#composiohq/composio&Date) +### [JavaScript 示例](https://docs.composio.dev/guides/javascript/) -## 📋 阅读我们的行为准则 - -作为我们开源社区的一部分,我们要求自己和其他贡献者遵守高标准的沟通。作为本项目的参与者和贡献者,您同意遵守我们的[行为准则](https://github.com/composiodev/composio/blob/master/CODE_OF_CONDUCT.md)。 +## 星号历史 -## 🤗 贡献 +[![Star History +Chart](https://api.star-history.com/svg?repos=composiohq/composio&type=Date)](https://star-history.com/#composiohq/composio&Date) -Composio 是开源的,我们欢迎贡献。请 fork 存储库,为您的功能创建一个新分支,添加您的功能或改进,然后发送拉取请求。 +## 获取帮助 -在开始之前,请先阅读我们的[贡献指南](https://github.com/composiodev/composio/blob/master/CONTRIBUTING.md)和[行为准则](https://github.com/composiodev/composio/blob/master/CODE_OF_CONDUCT.md)。 +- 阅读 docs.composio.dev 上的文档 +- 在 discord 上发布您的问题 -## 🔗 链接 +## 贡献 -- [主页](https://composio.dev?utm_campaign=github-readme) -- [贡献指南](https://github.com/composiodev/composio/blob/master/CONTRIBUTING.md) -- [文档](https://docs.composio.dev/?utm_campaign=github-readme) +我们是一个开源项目,欢迎贡献。请阅读贡献指南了解更多信息,并在开始之前查看我们的行为准则。 -## 🛡️ 许可证 +## 请求功能 -Composio 采用 Elastic 许可证 - 有关详细信息,请参阅 [LICENSE](https://github.com/composiodev/composio/blob/master/LICENSE) 文件。 +- 如果您有功能请求,请打开问题, +发出拉取请求,或在我们的功能请求频道中提交。 +- 如果您有改进想法,也可以在我们的 GitHub 存储库中发起讨论。 -## 💪 感谢所有贡献者 +## 感谢所有贡献者 - 贡献者名单 + 贡献者列表 + +

+ +
+

+ + discord +     + + youtube +     + + x +     + + linkedin + +

+
diff --git a/README-JP.md b/README-JP.md index 683963a560e..6fb53164ebd 100644 --- a/README-JP.md +++ b/README-JP.md @@ -1,151 +1,135 @@

- EN | CN | JP + 英語 | 中国語 | 日本語

-

- - Composio ロゴ - - - Composio ロゴ - + + Composio ロゴ + + + Composio ロゴ +

- - テスト - - - PyPI - - - ダウンロード - -

- -

- AIエージェントのためのプロダクションレディツールセット -

- -

認証、精度、信頼性を心配することなく、エージェントに高品質のツールと統合を1行のコードで装備しましょう! -

- - - -
-
-

- ✨ ソーシャル >> - Discord | - Youtube | - Twitter | - LinkedIn -

- ⛏️ 貢献 >> - バグを報告 | - 機能をリクエスト | - 貢献する + + PyPI + + + NPM + + + ダウンロード +

-
+ +

+ AI エージェント向けの製品版ツールセット +

+ +イラスト + +

Composio?

+

Composio は AI エージェント向けの製品化対応ツールセットを提供します。以下を提供します:

+
    +
  • 複数のカテゴリにわたる 250 以上のツールのサポート: +
      +
    • GitHub、Notion、Linear、Gmail、Slack、Hubspot、Salesforce などのソフトウェア ツール & + + その他 + +
    • +
    • ファイル ツール、シェル ツール、コード分析ツールなどの OS 操作 & + + その他 + +
    • +
    • Google、Perplexity、Tavily、Exa による検索機能 & + + その他 + +
    • +
    +
  • +
  • OpenAI、Groq、 Claude、LlamaIndex、Langchain、CrewAI、Autogen、Gemini、 + および その他
  • +
  • 複数のプロトコル (OAuth、API キー、Basic JWT) をサポートするマネージド認証
  • +
  • 最適化された設計により、ツール呼び出しの精度が最大 40% 向上
  • +
  • バックエンド統合のためのホワイトラベル ソリューション
  • +
  • カスタム ツールと拡張機能をサポートするプラグ可能なアーキテクチャ
  • +
## 📋 目次 -- [📋 目次](#-目次) -- [🤔 なぜComposio?](#-なぜcomposio) -- [🔥 主要機能](#-主要機能) -- [🚀 Pythonでの始め方](#-pythonでの始め方) - - [1. インストール](#1-インストール) - - [2. Composioの実践テスト](#2-composioの実践テスト) -- [🚀 Javascriptでの始め方](#-javascriptでの始め方) - - [1. **Composio SDKのインストール**:](#1-composio-sdkのインストール) - - [2. **OpenAIとComposioツールセットの設定**:](#2-openaiとcomposioツールセットの設定) - - [3. **スクリプトを実行**:](#3-スクリプトを実行) -- [💡 例](#-例) - - [Python](#python) - - [Javascript](#javascript) -- [Star履歴](#star履歴) -- [📋 行動規範を読む](#-行動規範を読む) -- [🤗 貢献](#-貢献) -- [🔗 リンク](#-リンク) -- [🛡️ ライセンス](#️-ライセンス) -- [💪 すべての貢献者に感謝](#-すべての貢献者に感謝) - -## 🤔 なぜComposio? - -私たちはAIベースのエージェント/ワークフローが未来であると信じています。 -Composioは、AIエージェントを最高のエージェントツールに統合し、それらを使用してタスクを完了するための最良のツールセットです。 - -イラスト - -## 🔥 主要機能 - -- **100+ ツール**:さまざまなカテゴリをサポート - - **ソフトウェア**:GitHub、Notion、Linear、Gmail、Slack、Hubspot、Salesforceなど90以上のプラットフォームで何でも実行できます。 - - **OS**:どこでもクリック、何でも入力、クリップボードにコピーなど。 - - **ブラウザ**:スマート検索、スクリーンショット、MultiOn、ダウンロード、アップロードなど。 - - **検索**:Google検索、Perplexity検索、Tavily、Exaなど。 - - **SWE**:Ngrok、データベース、Redis、Vercel、Gitなど。 - - **RAG**:即時に任意のデータタイプに対するエージェントRAG! - -- **フレームワーク**:**OpenAI、Claude、LlamaIndex、Langchain、CrewAI、Autogen、Gemini、Julep、Lyzr**などのエージェントフレームワークでツールを1行のコードで使用できます。 -- **管理された認証**:6つの異なる認証プロトコルをサポート。_アクセストークン、リフレッシュトークン、OAuth、APIキー、JWTなど_を抽象化して、エージェントの構築に集中できます。 -- **精度**:より良いツール設計により、ツール呼び出しのエージェント精度が_最大40%向上_します。 -- **埋め込み可能**:アプリケーションのバックエンドにホワイトラベルを付け、すべてのユーザーとエージェントの認証と統合を管理し、一貫したエクスペリエンスを維持します。 -- **プラグ可能**:追加のツール、フレームワーク、認証プロトコルを簡単に拡張できるように設計されています。 - -## 🚀 Pythonでの始め方 +- [Python の使用開始](#python-を使い始める) + - [1. インストール](#1-インストール) + - [2. エージェントの作成とツールの実行](#2-エージェントの作成とツールの実行) +- [JavaScript の使用開始](#javascript-を使い始める) + - [1. インストール](#1-インストール-1 ) + - [2.エージェントの作成とツールの実行](#2-エージェントの作成とツールの実行-1) +- [例](#例) + - [Python の例](#python-の例) + - [JavaScript の例](#javascript-の例) +- [スター履歴](#星の履歴) +- [ヘルプの取得](#ヘルプの取得) +- [貢献](#貢献) +- [機能のリクエスト](#機能のリクエスト) +- [すべての貢献者に感謝](#すべての貢献者に感謝) + + +## Python を使い始める ### 1. インストール -始めるには、ターミナルに以下のコマンドを入力します。 +まずパッケージをインストールします ```bash pip install composio-core ``` -'composio'パッケージをopenaiプラグインと一緒にインストールしたい場合は:`pip install composio-openai`。 +'composio' パッケージをその openai プラグインとともにインストールする場合は、`pip install composio-openai` を実行します。 -### 2. Composioの実践テスト +### 2. エージェントの作成とツールの実行 -Composioを使用して、GitHubリポジトリにスターを付けるAIエージェントを作成しましょう。 +OpenAI を使用して AI エージェントを作成し、Composio の GitHub ツールを使用して GitHub リポジトリにスターを付けましょう +> [!NOTE] +> 環境変数に COMPOSIO_API_KEY と OPENAI_API_KEY を設定します。 + +GitHubアカウントをComposioに接続する ```bash -composio add github # GitHubを接続 - ターミナルで実行 +composio add github # ターミナルでこれを実行する ``` ```python - from openai import OpenAI from composio_openai import ComposioToolSet, App, Action -openai_client = OpenAI( - api_key="{{OPENAIKEY}}" -) +openai_client = OpenAI(api_key="{{OPENAIKEY}}") -# Composioツールセットを初期化 +# Composioツールセットを初期化する composio_tool_set = ComposioToolSet() -# 事前に設定されたGitHubツールを取得 +# 事前設定されたGitHubツールを入手する actions = composio_tool_set.get_actions( actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER] ) -my_task = "GitHubでcomposiodev/composioリポジトリにスターを付ける" +my_task = "Star a repo composiodev/composio on GitHub" -# openaiアシスタントを設定 -assistant_instruction = "あなたは非常に知的なパーソナルアシスタントです" +# Openaiアシスタントのセットアップ +assistant_instruction = "You are a super intelligent personal assistant" assistant = openai_client.beta.assistants.create( name="Personal Assistant", @@ -154,23 +138,20 @@ assistant = openai_client.beta.assistants.create( tools=actions, ) -# スレッドを作成 +# スレッドを作成する thread = openai_client.beta.threads.create() message = openai_client.beta.threads.messages.create( - thread_id=thread.id, - role="user", - content=my_task + thread_id=thread.id, role="user", content=my_task ) -# 統合でエージェントを実行 +# 統合されたエージェントの実行 run = openai_client.beta.threads.runs.create( - thread_id=thread.id, - assistant_id=assistant.id + thread_id=thread.id, assistant_id=assistant.id ) -# 関数呼び出しを実行 +# 関数呼び出しを実行する response_after_tool_calls = composio_tool_set.wait_and_handle_assistant_tool_calls( client=openai_client, run=run, @@ -180,104 +161,123 @@ response_after_tool_calls = composio_tool_set.wait_and_handle_assistant_tool_cal print(response_after_tool_calls) ``` -## 🚀 Javascriptでの始め方 - -JavascriptでComposio SDKを使用するには、以下の手順に従ってください: - -### 1. **Composio SDKのインストール**: - ```bash - npm install composio-core - ``` - -### 2. **OpenAIとComposioツールセットの設定**: - ```javascript - import { OpenAI } from "openai"; - import { OpenAIToolSet } from "composio-core"; - - const toolset = new OpenAIToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, - }); - - async function setupUserConnectionIfNotExists(entityId) { - const entity = await toolset.client.getEntity(entityId); - const connection = await entity.getConnection('github'); - - if (!connection) { - // このエンティティ/ユーザーがまだアカウントを接続していない場合 - const connection = await entity.initiateConnection(appName); - console.log("次のURLでログインしてください: ", connection.redirectUrl); - return connection.waitUntilActive(60); - } - - return connection; - } - - async function executeAgent(entityName) { - const entity = await toolset.client.getEntity(entityName) - await setupUserConnectionIfNotExists(entity.id); - - const tools = await toolset.get_actions({ actions: ["github_issues_create"] }, entity.id); - const instruction = "リポジトリ - himanshu-dixit/custom-repo-breakingにサンプルタイトルのissueを作成する" +## JavaScript を使い始める - const client = new OpenAI({ apiKey: process.env.OPEN_AI_API_KEY }) - const response = await client.chat.completions.create({ - model: "gpt-4-turbo", - messages: [{ - role: "user", - content: instruction, - }], - tools: tools, - tool_choice: "auto", - }) +JavaScript で Composio SDK を使い始めるには、次の手順に従います: - console.log(response.choices[0].message.tool_calls); - await toolset.handle_tool_call(response, entity.id); - } +### 1. インストール: +```bash +npm install composio-core +``` - executeAgent("your-entity-name"); - ``` +### 2. エージェントの作成とツールの実行 -### 3. **スクリプトを実行**: - ```bash - node your_script.js - ``` +OpenAI を使用して AI エージェントを作成し、Composio の GitHub ツールを使用して GitHub リポジトリにスターを付けましょう -これにより、Composio SDKが設定され、提供された指示を使用してGitHubのissueを作成するエージェントが実行されます。 +> [!NOTE] +> 環境変数に COMPOSIO_API_KEY と OPENAI_API_KEY を設定します。 -詳細については、[Composio SDKドキュメント](https://docs.composio.dev/)を参照してください。 +GitHubアカウントをComposioに接続する +```bash +composio add github # ターミナルでこれを実行する +``` -## 💡 例 +```javascript +import { OpenAIToolSet } from "composio-core"; +import OpenAI from "openai"; + +const toolset = new OpenAIToolSet({ apiKey: process.env.COMPOSIO_API_KEY }); +const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); + +const tools = await toolset.getTools({ actions: ["GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER"] }); + +async function createGithubAssistant(openai, tools) { + return await openai.beta.assistants.create({ + name: "Github Assistant", + instructions: "You're a GitHub Assistant, you can do operations on GitHub", + tools: tools, + model: "gpt-4o" + }); +} + +async function executeAssistantTask(openai, toolset, assistant, task) { + const thread = await openai.beta.threads.create(); + const run = await openai.beta.threads.runs.create(thread.id, { + assistant_id: assistant.id, + instructions: task, + tools: tools, + model: "gpt-4o", + stream: false + }); + const call = await toolset.waitAndHandleAssistantToolCalls(openai, run, thread); + console.log(call); +} + +(async () => { + const githubAssistant = await createGithubAssistant(openai, tools); + await executeAssistantTask( + openai, + toolset, + githubAssistant, + "Star the repository 'composiohq/composio'" + ); +})(); +``` -### [Python](https://docs.composio.dev/guides/python/) +## 例 -### [Javascript](https://docs.composio.dev/guides/javascript/) +### [Python の例](https://docs.composio.dev/guides/python/) -## Star履歴 +### [JavaScript の例](https://docs.composio.dev/guides/javascript/) -[![Star History Chart](https://api.star-history.com/svg?repos=composiohq/composio&type=Date)](https://star-history.com/#composiohq/composio&Date) +## 星の履歴 -## 📋 行動規範を読む - -私たちのオープンソースコミュニティの一員として、私たちは自分自身と他の貢献者に高いコミュニケーション基準を求めています。このプロジェクトの参加者および貢献者として、あなたは私たちの[行動規範](https://github.com/composiodev/composio/blob/master/CODE_OF_CONDUCT.md)に従うことに同意します。 +[![星の履歴 +チャート](https://api.star-history.com/svg?repos=composiohq/composio&type=Date)](https://star-history.com/#composiohq/composio&Date) -## 🤗 貢献 +## ヘルプの取得 -Composioはオープンソースであり、貢献を歓迎します。リポジトリをフォークし、機能のための新しいブランチを作成し、機能や改善を追加し、プルリクエストを送信してください。 +- docs.composio.dev でドキュメントを読む +- discord -始める前に、[貢献ガイドライン](https://github.com/composiodev/composio/blob/master/CONTRIBUTING.md)と[行動規範](https://github.com/composiodev/composio/blob/master/CODE_OF_CONDUCT.md)をお読みください。 +## 貢献 -## 🔗 リンク +私たちはオープンソース プロジェクトであり、貢献を歓迎しています。詳細については、貢献ガイドをお読みになり、開始する前に、行動規範を確認してください。 -- [ホームページ](https://composio.dev?utm_campaign=github-readme) -- [貢献ガイドライン](https://github.com/composiodev/composio/blob/master/CONTRIBUTING.md) -- [ドキュメント](https://docs.composio.dev/?utm_campaign=github-readme) +## 機能のリクエスト -## 🛡️ ライセンス +- 機能のリクエストがある場合は、問題を開くか、プルリクエストを作成するか、機能リクエスト チャンネルに送信してください。 -ComposioはElasticライセンスの下でライセンスされています - 詳細については[LICENSE](https://github.com/composiodev/composio/blob/master/LICENSE)ファイルを参照してください。 +- 改善のアイデアがある場合は、GitHub リポジトリでディスカッションを開始することもできます。 -## 💪 すべての貢献者に感謝 +## すべての貢献者に感謝 - 貢献者のリスト + 貢献者リスト + +

+ +
+

+ + discord +     + + youtube +     + + x +     + + linkedin + +

+
diff --git a/README.md b/README.md index 4d267b7d1e7..8c8f263566c 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,8 @@ -

- - Follow me - -

-

-

- - Sign up - - -

-

- EN | CN | JP + EN | CN | JP

-

Composio logo @@ -24,110 +12,87 @@

- - Tests + + Read the Docs +

+ +

- PyPI + PyPI - NPM + NPM - Downloads + Downloads -

-

+

Production Ready Toolset for AI Agents -

- -

Equip your agent with high-quality tools & integrations without worrying about authentication, accuracy, and reliability in a single line of code! -

- - -
-
-

- ✨ Socials >> - Discord | - Youtube | - Twitter | - Linkedin -

-

- ⛏️ Contribute >> - Report Bugs | - Request Feature | - Contribute -

-
- -## 📋 Table of contents - -- [📋 Table of contents](#-table-of-contents) -- [🤔 Why Composio?](#-why-composio) -- [🔥 Key Features](#-key-features) -- [🚀 Getting Started with Python](#-getting-started-with-python) + + +Illustration + +

What is Composio?

+

Composio provides production-ready toolset for AI agents, offering:

+
    +
  • Support for over 250+ tools across multiple categories: +
      +
    • Software tools like GitHub, Notion, Linear, Gmail, Slack, Hubspot, Salesforce & + + more + +
    • +
    • OS operations including file tool, shell tool, code analysis tool & + + more + +
    • +
    • Search capabilities through Google, Perplexity, Tavily, and Exa & + + more + +
    • +
    +
  • +
  • Comprehensive framework support including OpenAI, Groq, Claude, LlamaIndex, Langchain, CrewAI, Autogen, Gemini, + and more
  • +
  • Managed authentication supporting multiple protocols (OAuth, API Keys, Basic JWT)
  • +
  • Up to 40% improved tool call accuracy through optimized design
  • +
  • Whitelabel solution for backend integration
  • +
  • Pluggable architecture supporting custom tools and extensions
  • +
+ +## Table of contents + +- [Getting Started with Python](#1-installation) - [1. Installation](#1-installation) - - [2. Testing Composio in Action](#2-testing-composio-in-action) -- [🚀 Getting Started with Javascript](#-getting-started-with-javascript) - - [1. **Install the Composio SDK**:](#1-install-the-composio-sdk) - - [2. **Setup the OpenAI and Composio Tool Set**:](#2-setup-the-openai-and-composio-tool-set) - - [3. **Run your script**:](#3-run-your-script) -- [💡 Examples](#-examples) + - [2. Creating an agent & executing a tool](#2-creating-an-agent--executing-a-tool) +- [Getting Started with Javascript](#getting-started-with-javascript) + - [1. Installation](#1-installation-1) + - [2. Creating an agent & executing a tool](#2-creating-an-agent--executing-a-tool-1) +- [Examples](#examples) - [Python Examples](#python-examples) - [Javascript Examples](#javascript-examples) - [Star History](#star-history) -- [📋 Read Our Code Of Conduct](#-read-our-code-of-conduct) -- [🤗 Contributions](#-contributions) -- [🔗 Links](#-links) -- [🛡️ License](#️-license) -- [💪 Thanks To All Contributors](#-thanks-to-all-contributors) - -## 🤔 Why Composio? - -We believe AI Based Agents/Workflows are the future. -Composio is the best toolset to integrate AI Agents to best Agentic Tools and use them to accomplish tasks. +- [Getting help](#getting-help) +- [Contributions](#contributions) +- [Request a feature](#request-a-feature) +- [Thanks To All Contributors](#thanks-to-all-contributors) -Illustration -## 🔥 Key Features - -- **100+ Tools**: Support for a range of different categories - - - **Software**: Do anything on GitHub, Notion, Linear, Gmail, Slack, Hubspot, Salesforce, & 90 more. - - **OS**: Click anywhere, Type anything, Copy to Clipboard, & more. - - **Browser**: Smart Search, Take a screenshot, MultiOn, Download, Upload, & more. - - **Search**: Google Search, Perplexity Search, Tavily, Exa & more. - - **SWE**: Ngrok, Database, Redis, Vercel, Git, etc. - - **RAG**: Agentic RAG for any type of data on the fly! - -- **Frameworks**: Use tools with agent frameworks like **OpenAI, Groq (OpenAI compatible), Claude, LlamaIndex, Langchain, CrewAI, Autogen, Gemini, Julep, Lyzr**, and more in a single line of code. -- **Managed Authorisation**: Supports six different auth protocols. _Access Token, Refresh token, OAuth, API Keys, JWT, and more_ abstracted out so you can focus on the building agents. -- **Accuracy**: Get _up to 40% better agentic accuracy_ in your tool calls due to better tool designs. -- **Embeddable**: Whitelabel in the backend of your applications managing Auth & Integrations for all your users & agents and maintain a consistent experience. -- **Pluggable**: Designed to be extended with additional Tools, Frameworks and Authorisation Protocols very easily. - -## 🚀 Getting Started with Python +## Getting Started with Python ### 1. Installation -To get started, type the following command in your Terminal. +Start by installing the package ```bash pip install composio-core @@ -135,12 +100,16 @@ pip install composio-core If you want to install the 'composio' package along with its openai plugin: `pip install composio-openai`. -### 2. Testing Composio in Action +### 2. Creating an agent & executing a tool -Let's use Composio to create an AI Agent that can star a GitHub Repo. +Let's create an AI Agent using OpenAI and use Composio's GitHub tool to star a GitHub repository +> [!NOTE] +> Set your COMPOSIO_API_KEY & OPENAI_API_KEY in your environment variables. + +Connect your GitHub account to Composio ```bash -composio add github # Connect your GitHub - Run this in terminal +composio add github # Run this in terminal ``` ```python @@ -149,7 +118,7 @@ from openai import OpenAI from composio_openai import ComposioToolSet, App, Action openai_client = OpenAI( - api_key="{{OPENAIKEY}}" +api_key="{{OPENAIKEY}}" ) # Initialise the Composio Tool Set @@ -158,7 +127,7 @@ composio_tool_set = ComposioToolSet() # Get GitHub tools that are pre-configured actions = composio_tool_set.get_actions( - actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER] +actions=[Action.GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER] ) my_task = "Star a repo composiodev/composio on GitHub" @@ -167,140 +136,155 @@ my_task = "Star a repo composiodev/composio on GitHub" assistant_instruction = "You are a super intelligent personal assistant" assistant = openai_client.beta.assistants.create( - name="Personal Assistant", - instructions=assistant_instruction, - model="gpt-4-turbo", - tools=actions, +name="Personal Assistant", +instructions=assistant_instruction, +model="gpt-4-turbo", +tools=actions, ) # create a thread thread = openai_client.beta.threads.create() message = openai_client.beta.threads.messages.create( - thread_id=thread.id, - role="user", - content=my_task +thread_id=thread.id, +role="user", +content=my_task ) # Execute Agent with integrations run = openai_client.beta.threads.runs.create( - thread_id=thread.id, - assistant_id=assistant.id +thread_id=thread.id, +assistant_id=assistant.id ) # Execute Function calls response_after_tool_calls = composio_tool_set.wait_and_handle_assistant_tool_calls( - client=openai_client, - run=run, - thread=thread, +client=openai_client, +run=run, +thread=thread, ) print(response_after_tool_calls) ``` -## 🚀 Getting Started with Javascript - -To get started with the Composio SDK in Javascript, follow these steps: - -### 1. **Install the Composio SDK**: - ```bash - npm install composio-core - ``` - -### 2. **Setup the OpenAI and Composio Tool Set**: - ```javascript - import { OpenAI } from "openai"; - import { OpenAIToolSet } from "composio-core"; +## Getting Started with JavaScript - const toolset = new OpenAIToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, - }); +To get started with the Composio SDK in JavaScript, follow these steps: - async function setupUserConnectionIfNotExists(entityId) { - const entity = await toolset.client.getEntity(entityId); - const connection = await entity.getConnection('github'); - - if (!connection) { - // If this entity/user hasn't already connected the account - const connection = await entity.initiateConnection(appName); - console.log("Log in via: ", connection.redirectUrl); - return connection.waitUntilActive(60); - } - - return connection; - } - - async function executeAgent(entityName) { - const entity = await toolset.client.getEntity(entityName) - await setupUserConnectionIfNotExists(entity.id); - - const tools = await toolset.get_actions({ actions: ["github_issues_create"] }, entity.id); - const instruction = "Make an issue with sample title in the repo - himanshu-dixit/custom-repo-breaking" - - const client = new OpenAI({ apiKey: process.env.OPEN_AI_API_KEY }) - const response = await client.chat.completions.create({ - model: "gpt-4-turbo", - messages: [{ - role: "user", - content: instruction, - }], - tools: tools, - tool_choice: "auto", - }) - - console.log(response.choices[0].message.tool_calls); - await toolset.handle_tool_call(response, entity.id); - } +### 1. Installation: +```bash +npm install composio-core +``` - executeAgent("your-entity-name"); - ``` +### 2. Creating an agent & executing a tool -### 3. **Run your script**: - ```bash - node your_script.js - ``` +Let's create an AI Agent using OpenAI and use Composio's GitHub tool to star a GitHub repository -This will set up the Composio SDK and execute an agent that creates a GitHub issue using the provided instructions. +> [!NOTE] +> Set your COMPOSIO_API_KEY & OPENAI_API_KEY in your environment variables. -For more details, refer to the [Composio SDK Documentation](https://docs.composio.dev/). +Connect your GitHub account to Composio +```bash +composio add github # Run this in terminal +``` +```javascript +import { OpenAIToolSet } from "composio-core"; +import OpenAI from "openai"; + +const toolset = new OpenAIToolSet({ apiKey: process.env.COMPOSIO_API_KEY }); +const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); + +const tools = await toolset.getTools({ actions: ["GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER"] }); + +async function createGithubAssistant(openai, tools) { +return await openai.beta.assistants.create({ +name: "Github Assistant", +instructions: "You're a GitHub Assistant, you can do operations on GitHub", +tools: tools, +model: "gpt-4o" +}); +} + +async function executeAssistantTask(openai, toolset, assistant, task) { +const thread = await openai.beta.threads.create(); +const run = await openai.beta.threads.runs.create(thread.id, { +assistant_id: assistant.id, +instructions: task, +tools: tools, +model: "gpt-4o", +stream: false +}); +const call = await toolset.waitAndHandleAssistantToolCalls(openai, run, thread); +console.log(call); +} + +(async () => { +const githubAssistant = await createGithubAssistant(openai, tools); +await executeAssistantTask( +openai, +toolset, +githubAssistant, +"Star the repository 'composiohq/composio'" +); +})(); +``` -## 💡 Examples +## Examples ### [Python Examples](https://docs.composio.dev/guides/python/) ### [Javascript Examples](https://docs.composio.dev/guides/javascript/) - - ## Star History -[![Star History Chart](https://api.star-history.com/svg?repos=composiohq/composio&type=Date)](https://star-history.com/#composiohq/composio&Date) - +[![Star History +Chart](https://api.star-history.com/svg?repos=composiohq/composio&type=Date)](https://star-history.com/#composiohq/composio&Date) -## 📋 Read Our Code Of Conduct +## Getting help -As part of our open-source community, we hold ourselves and other contributors to a high standard of communication. As a participant and contributor to this project, you agree to abide by our [Code of Conduct](https://github.com/composiodev/composio/blob/master/CODE_OF_CONDUCT.md). +- Read the docs at docs.composio.dev +- Post your questions on discord -## 🤗 Contributions +## Contributions -Composio is open-source and we welcome contributions. Please fork the repository, create a new branch for your feature, add your feature or improvement, and send a pull request. +We're an open-source project and welcome contributions. Please read the contributing guide for more information and check our code of conduct before you start. -Also go through our [Contribution Guidelines](https://github.com/composiodev/composio/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/composiodev/composio/blob/master/CODE_OF_CONDUCT.md) before you start. +## Request a feature -## 🔗 Links +- If you have a feature request, please open an issue, +make a pull request, or submit it in our feature requests channel. +- If you have ideas for improvements, you can also start a discussion in our GitHub repository. -- [Home page](https://composio.dev?utm_campaign=github-readme) -- [Contribution Guidelines](https://github.com/composiodev/composio/blob/master/CONTRIBUTING.md) -- [Docs](https://docs.composio.dev/?utm_campaign=github-readme) - -## 🛡️ License - -Composio is licensed under the Elastic License - see the [LICENSE](https://github.com/composiodev/composio/blob/master/LICENSE) file for details. - -## 💪 Thanks To All Contributors +## Thanks To All Contributors - List of Contributors + List of Contributors + +

+ +
+

+ + discord +     + + youtube +     + + x +     + + linkedin + +

+
From d444e543e626c43f23cd6b427badec94eac291fb Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Wed, 15 Jan 2025 18:38:57 +0530 Subject: [PATCH 23/34] feat: make test env agnostic (#1197) --- .github/workflows/run_js_test.yml | 34 ++++++- js/Testing.MD | 17 ++++ js/config/test.config.local.json | 4 + js/config/test.config.staging.json | 4 + js/src/frameworks/langchain.spec.ts | 8 +- js/src/sdk/index.spec.ts | 109 ++++++++++++++--------- js/src/sdk/index2.spec.ts | 20 +++++ js/src/sdk/models/Entity.spec.ts | 21 ++++- js/src/sdk/models/backendClient.ts | 4 + js/src/sdk/models/integrations.spec.ts | 15 +++- js/src/sdk/utils/errors/src/formatter.ts | 2 +- 11 files changed, 186 insertions(+), 52 deletions(-) create mode 100644 js/Testing.MD create mode 100644 js/config/test.config.local.json create mode 100644 js/config/test.config.staging.json create mode 100644 js/src/sdk/index2.spec.ts diff --git a/.github/workflows/run_js_test.yml b/.github/workflows/run_js_test.yml index 8b228ead4e4..7abcdef513d 100644 --- a/.github/workflows/run_js_test.yml +++ b/.github/workflows/run_js_test.yml @@ -9,7 +9,21 @@ on: pull_request: paths: - 'js/**' - + workflow_dispatch: + inputs: + environment: + type: choice + options: + - prod + - staging + - custom + default: prod + baseUrl: + type: string + required: false + apiKey: + type: string + required: false jobs: run-js-tests: @@ -35,9 +49,23 @@ jobs: run: cd js && pnpm install --frozen-lockfile - name: pnpm build run: cd js && pnpm build - - name: run test - run: cd js && pnpm test:coverage --max-workers 16 + - name: Set environment variables + run: | + echo "COMPOSIO_API_KEY=${{ inputs.apiKey }}" >> $GITHUB_ENV + echo "BACKEND_HERMES_URL=${{ inputs.baseUrl }}" >> $GITHUB_ENV + - name: If base URL, create js/test.config.custom.json + run: | + if [ -n "${{ inputs.baseUrl }}" ]; then + echo "Creating test.config.custom.json with base URL: $BACKEND_HERMES_URL" + echo "{\n \"COMPOSIO_API_KEY\": \"${{ inputs.apiKey }}\",\n \"BACKEND_HERMES_URL\": \"${{ inputs.baseUrl }}\"\n}" > js/config/test.config.custom.json + fi + + - name: Print config file + run: | + echo "Running test with environment: ${{ inputs.environment }}" + - name: run test + run: cd js && TEST_ENVIRONMENT=${{ inputs.environment }} pnpm test:coverage --max-workers 16 - name: Upload `coverage` folder to R2 if: ${{ always() }} diff --git a/js/Testing.MD b/js/Testing.MD new file mode 100644 index 00000000000..10d29fa73d5 --- /dev/null +++ b/js/Testing.MD @@ -0,0 +1,17 @@ +# Test Environment Setup Requirements + +The test suite is designed to run across multiple environments. Before running tests, ensure the following prerequisites are met: + +1. Authentication Configuration + - Valid API key is configured + - Base URL is properly set for the target environment + +2. Required Active Services + - GitHub integration is enabled and active + - Gmail integration is enabled and active + - CodeInterpreter is configured for the default entity + +3. Trigger Configuration + - At least one trigger must be active in the system + +Please verify all requirements are satisfied before executing the test suite to ensure proper test execution and validation. \ No newline at end of file diff --git a/js/config/test.config.local.json b/js/config/test.config.local.json new file mode 100644 index 00000000000..04910d0fb52 --- /dev/null +++ b/js/config/test.config.local.json @@ -0,0 +1,4 @@ +{ + "COMPOSIO_API_KEY": "", + "BACKEND_HERMES_URL": "http://localhost:9900" +} diff --git a/js/config/test.config.staging.json b/js/config/test.config.staging.json new file mode 100644 index 00000000000..fd68c232bce --- /dev/null +++ b/js/config/test.config.staging.json @@ -0,0 +1,4 @@ +{ + "COMPOSIO_API_KEY": "gxpf3a5v864651jp741heq", + "BACKEND_HERMES_URL": "https://staging-backend.composio.dev" +} diff --git a/js/src/frameworks/langchain.spec.ts b/js/src/frameworks/langchain.spec.ts index fa305509215..8c3a1e40d4d 100644 --- a/js/src/frameworks/langchain.spec.ts +++ b/js/src/frameworks/langchain.spec.ts @@ -65,6 +65,12 @@ describe("Apps class tests", () => { }); await expect(tools.length).toBe(1); + + const connectedAccount = await langchainToolSet.connectedAccounts.list({ + appNames: "github", + showActiveOnly: true, + }); + const actionOuput = await langchainToolSet.executeAction({ action: "starRepositoryCustomAction", params: { @@ -72,7 +78,7 @@ describe("Apps class tests", () => { repo: "achievementsof.life", }, entityId: "default", - connectedAccountId: "9442cab3-d54f-4903-976c-ee67ef506c9b", + connectedAccountId: connectedAccount.items[0].id, }); expect(actionOuput).toHaveProperty("successful", true); diff --git a/js/src/sdk/index.spec.ts b/js/src/sdk/index.spec.ts index bc069b9864d..42b1ad8633d 100644 --- a/js/src/sdk/index.spec.ts +++ b/js/src/sdk/index.spec.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from "@jest/globals"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; import AxiosMockAdapter from "axios-mock-adapter"; import { getTestConfig } from "../../config/getTestConfig"; import { client as axiosClient } from "./client/services.gen"; @@ -11,8 +11,17 @@ import { const { COMPOSIO_API_KEY, BACKEND_HERMES_URL } = getTestConfig(); describe("Basic SDK spec suite", () => { - it("should create a basic client", () => { - const client = new Composio({ apiKey: COMPOSIO_API_KEY }); + const mock = new AxiosMockAdapter(axiosClient.instance); + + beforeEach(() => { + mock.reset(); + }); + + it("should create a basic client", async () => { + const client = new Composio({ + apiKey: COMPOSIO_API_KEY, + baseUrl: getTestConfig().BACKEND_HERMES_URL, + }); expect(client).toBeInstanceOf(Composio); }); @@ -21,43 +30,47 @@ describe("Basic SDK spec suite", () => { // @ts-expect-error process.exit = jest.fn(); - expect(() => new Composio()).toThrow("🔑 API Key is not provided"); + expect( + () => new Composio({ baseUrl: getTestConfig().BACKEND_HERMES_URL }) + ).toThrow("🔑 API Key is not provided"); process.exit = originalExit; }); it("should handle 404 error gracefully", async () => { - const mock = new AxiosMockAdapter(axiosClient.instance); const mockError = { type: "NotFoundError", name: "AppNotFoundError", message: "Not found", }; - mock.onGet("/api/v1/apps").reply(404, mockError); + mock.onGet(/.*\/api\/v1\/apps/).reply(404, mockError); - const client = new Composio({ apiKey: COMPOSIO_API_KEY }); + const client = new Composio({ + apiKey: COMPOSIO_API_KEY, + baseUrl: getTestConfig().BACKEND_HERMES_URL, + }); + let errorWasThrown = false; try { await client.apps.list(); } catch (e) { + errorWasThrown = true; if (e instanceof ComposioError) { expect(e.errCode).toBe(COMPOSIO_SDK_ERROR_CODES.BACKEND.NOT_FOUND); expect(e.description).toBe("Not found"); expect(e.errorId).toBeDefined(); expect(e.name).toBe("ComposioError"); expect(e.possibleFix).toBe(e.possibleFix); - expect(e.message).toContain(mockError.message); + expect(e.message).toContain(mockError.type); expect(e.message).toContain(mockError.name); } else { throw e; } } - - mock.reset(); + expect(errorWasThrown).toBe(true); }); it("should handle 400 error gracefully", async () => { - const mock = new AxiosMockAdapter(axiosClient.instance); - mock.onGet("/api/v1/apps").reply(400, { + mock.onGet(/.*\/api\/v1\/apps/).reply(400, { type: "BadRequestError", name: "InvalidRequestError", message: "Invalid request for apps", @@ -72,10 +85,15 @@ describe("Basic SDK spec suite", () => { ], }); - const client = new Composio({ apiKey: COMPOSIO_API_KEY }); + let errorWasThrown = false; + const client = new Composio({ + apiKey: COMPOSIO_API_KEY, + baseUrl: getTestConfig().BACKEND_HERMES_URL, + }); try { await client.apps.list(); } catch (e) { + errorWasThrown = true; const error = e as ComposioError; const errorCode = COMPOSIO_SDK_ERROR_CODES.BACKEND.BAD_REQUEST; expect(error.errCode).toBe(errorCode); @@ -84,33 +102,36 @@ describe("Basic SDK spec suite", () => { `Validation Errors: {"property":"triggerConfig","children":[],"constraints":{"isObject":"triggerConfig must be an object"}}` ); } - - mock.reset(); + expect(errorWasThrown).toBe(true); }); it("should handle 500 and 502 error gracefully, and without backend fix", async () => { - const mock = new AxiosMockAdapter(axiosClient.instance); - mock.onGet("/api/v1/apps").reply(500, { + mock.onGet(/.*\/api\/v1\/apps/).reply(500, { type: "InternalServerError", name: "ServerError", message: "Internal Server Error", }); - const client = new Composio({ apiKey: COMPOSIO_API_KEY }); + let errorWasThrown = false; + const client = new Composio({ + apiKey: COMPOSIO_API_KEY, + baseUrl: getTestConfig().BACKEND_HERMES_URL, + }); try { await client.apps.list(); } catch (e) { + errorWasThrown = true; const error = e as ComposioError; const errorCode = COMPOSIO_SDK_ERROR_CODES.BACKEND.SERVER_ERROR; const errorInfo = BASE_ERROR_CODE_INFO[errorCode]; expect(error.errCode).toBe(errorCode); - expect(error.message).toContain(errorInfo.message); - expect(error.description).toContain(errorInfo.description); + expect(error.message).toContain("ServerError - InternalServerError"); + expect(error.description).toContain("Internal Server"); expect(error.errorId).toBeDefined(); expect(error.name).toBe("ComposioError"); expect(error.possibleFix).toContain(errorInfo.possibleFix); } - - mock.onGet("/api/v1/apps").reply(502, { detail: "Bad Gateway" }); + expect(errorWasThrown).toBe(true); + mock.onGet(/.*\/api\/v1\/apps/).reply(502, { detail: "Bad Gateway" }); try { await client.apps.list(); @@ -120,7 +141,9 @@ describe("Basic SDK spec suite", () => { const errorInfo = BASE_ERROR_CODE_INFO[errorCode]; expect(error.errCode).toBe(errorCode); expect(error.message).toContain(errorInfo.message); - expect(error.description).toContain(errorInfo.description); + expect(error.description).toContain( + "er is currently unable to handle the reque" + ); expect(error.errorId).toBeDefined(); expect(error.name).toBe("ComposioError"); expect(error.possibleFix).toContain(errorInfo.possibleFix); @@ -128,7 +151,7 @@ describe("Basic SDK spec suite", () => { mock.reset(); - mock.onGet("/api/v1/apps").reply(500, { + mock.onGet(/.*\/api\/v1\/apps/).reply(500, { error: { type: "NotFoundError", name: "AppNotFoundError", @@ -139,18 +162,28 @@ describe("Basic SDK spec suite", () => { await client.apps.list(); } catch (e) { const error = e as ComposioError; - expect(error.message).toContain("AppNotFoundError - NotFoundError"); + expect(error.errCode).toBe(COMPOSIO_SDK_ERROR_CODES.BACKEND.SERVER_ERROR); } }); it("should give request timeout error", async () => { - const client = new Composio({ apiKey: COMPOSIO_API_KEY }); - const mock = new AxiosMockAdapter(axiosClient.instance); - mock.onGet("/api/v1/apps").reply(408, {}); + const client = new Composio({ + apiKey: COMPOSIO_API_KEY, + baseUrl: getTestConfig().BACKEND_HERMES_URL, + }); + mock.onGet(/.*\/api\/v1\/apps/).reply(408, { + error: { + type: "NotFoundError", + name: "AppNotFoundError", + message: "Not found", + }, + }); + let errorWasThrown = false; try { await client.apps.list(); } catch (e) { + errorWasThrown = true; const error = e as ComposioError; const errorCode = COMPOSIO_SDK_ERROR_CODES.COMMON.REQUEST_TIMEOUT; const errorInfo = BASE_ERROR_CODE_INFO[errorCode]; @@ -160,24 +193,16 @@ describe("Basic SDK spec suite", () => { expect(error.possibleFix).toBe(errorInfo.possibleFix); } - mock.reset(); + expect(errorWasThrown).toBe(true); }); - it("syntax error handling", () => { + it("syntax error handling", async () => { expect(() => new Composio()).toThrow("🔑 API Key is not provided"); }); - it("should get an entity and then fetch a connection", async () => { - const app = "github"; - const composio = new Composio({ - apiKey: COMPOSIO_API_KEY, - baseUrl: BACKEND_HERMES_URL, - }); - const entity = composio.getEntity("default"); - - expect(entity.id).toBe("default"); - - const connection = await entity.getConnection({ app: app! }); - expect(connection?.appUniqueId).toBe(app); + afterEach(() => { + mock.reset(); + mock.resetHandlers(); + mock.restore(); }); }); diff --git a/js/src/sdk/index2.spec.ts b/js/src/sdk/index2.spec.ts new file mode 100644 index 00000000000..6dc3a26c587 --- /dev/null +++ b/js/src/sdk/index2.spec.ts @@ -0,0 +1,20 @@ +import { getTestConfig } from "../../config/getTestConfig"; +import { Composio } from "./index"; + +const { COMPOSIO_API_KEY, BACKEND_HERMES_URL } = getTestConfig(); + +describe("Entity spec suite", () => { + it("should get an entity and then fetch a connection for a normal app", async () => { + const app = "github"; + const composio = new Composio({ + apiKey: COMPOSIO_API_KEY, + baseUrl: BACKEND_HERMES_URL, + }); + const entity = composio.getEntity("default"); + + expect(entity.id).toBe("default"); + + const connection = await entity.getConnection({ app: app! }); + expect(connection?.appUniqueId).toBe(app); + }); +}); diff --git a/js/src/sdk/models/Entity.spec.ts b/js/src/sdk/models/Entity.spec.ts index b3d69c7b39a..c3839744686 100644 --- a/js/src/sdk/models/Entity.spec.ts +++ b/js/src/sdk/models/Entity.spec.ts @@ -61,7 +61,26 @@ describe("Entity class tests", () => { it("should have an Id of a connected account with label - primary", async () => { const entityW2Connection = new Entity(backendClient, "ckemvy"); - const getConnection = await entityW2Connection.getConnection({ + + const entity = new Entity(backendClient, "ckemvy"); + + // Remove test with normal app where reinitiate connection is not needed + // await entity.initiateConnection({ + // appName: "github", + // }); + // const getConnection = await entity.getConnection({ + // app: "github", + + // }); + // expect(getConnection).toHaveProperty("id"); + }); + + it("should have an Id of a connected account with default - primary", async () => { + const entityW2Connection = new Entity(backendClient, "default"); + + const entity = new Entity(backendClient, "default"); + + const getConnection = await entity.getConnection({ app: "github", }); expect(getConnection).toHaveProperty("id"); diff --git a/js/src/sdk/models/backendClient.ts b/js/src/sdk/models/backendClient.ts index 764b3b18ae7..e19a9f00401 100644 --- a/js/src/sdk/models/backendClient.ts +++ b/js/src/sdk/models/backendClient.ts @@ -97,4 +97,8 @@ export class BackendClient { setAxiosClientConfig(axiosClient.instance); this.instance = axiosClient.instance; } + + getAxiosInstance() { + return axiosClient.instance; + } } diff --git a/js/src/sdk/models/integrations.spec.ts b/js/src/sdk/models/integrations.spec.ts index 3e10a2c578e..95f76e13041 100644 --- a/js/src/sdk/models/integrations.spec.ts +++ b/js/src/sdk/models/integrations.spec.ts @@ -1,15 +1,18 @@ import { beforeAll, describe, expect, it } from "@jest/globals"; import { getBackendClient } from "../testUtils/getBackendClient"; +import { Apps } from "./apps"; import { Integrations } from "./integrations"; describe("Integrations class tests", () => { - let backendClient; let integrations: Integrations; let createdIntegrationId: string; + let apps: Apps; + let appId: string; beforeAll(() => { - backendClient = getBackendClient(); + const backendClient = getBackendClient(); integrations = new Integrations(backendClient); + apps = new Apps(backendClient); }); it("Retrieve integrations list", async () => { @@ -19,8 +22,12 @@ describe("Integrations class tests", () => { }); it("should create an integration and verify its properties", async () => { + const app = await apps.get({ appKey: "github" }); + if (!app) throw new Error("App not found"); + appId = app.appId; + const integrationCreation = await integrations.create({ - appId: "01e22f33-dc3f-46ae-b58d-050e4d2d1909", + appId: appId, name: "test_integration_220", useComposioAuth: true, forceNewIntegration: true, @@ -37,7 +44,7 @@ describe("Integrations class tests", () => { integrationId: createdIntegrationId, }); expect(integration?.id).toBe(createdIntegrationId); - expect(integration?.appId).toBe("01e22f33-dc3f-46ae-b58d-050e4d2d1909"); + expect(integration?.appId).toBe(appId); expect(integration?.authScheme).toBe("OAUTH2"); expect(integration?.expectedInputFields).toBeDefined(); }); diff --git a/js/src/sdk/utils/errors/src/formatter.ts b/js/src/sdk/utils/errors/src/formatter.ts index bd04a39be35..4bf5a9951da 100644 --- a/js/src/sdk/utils/errors/src/formatter.ts +++ b/js/src/sdk/utils/errors/src/formatter.ts @@ -50,7 +50,7 @@ export const getAPIErrorDetails = ( if (hasNotReceivedResponseFromBE) { genericMessage = predefinedError.message as string; } else if (axiosError.config?.baseURL && axiosError.config?.url) { - genericMessage = `${errorNameFromBE || ""} ${errorTypeFromBE ? `- ${errorTypeFromBE}` : ""} on ${axiosError.config?.baseURL! + axiosError.config?.url!}`; + genericMessage = `${errorNameFromBE || predefinedError.message} ${errorTypeFromBE ? `- ${errorTypeFromBE}` : ""} on ${axiosError.config?.baseURL! + axiosError.config?.url!}`; } switch (errorCode) { From c61edc48433d2218a49c933e171a0064727758ba Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Wed, 15 Jan 2025 18:57:55 +0530 Subject: [PATCH 24/34] feat: change TEST_ENVIRONMENT -> TEST_ENV and log base url for CI (#1198) --- .github/workflows/run_js_test.yml | 5 ++--- js/src/sdk/index.ts | 6 ++++++ js/src/utils/external.ts | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run_js_test.yml b/.github/workflows/run_js_test.yml index 7abcdef513d..9d8dbeca853 100644 --- a/.github/workflows/run_js_test.yml +++ b/.github/workflows/run_js_test.yml @@ -62,10 +62,10 @@ jobs: - name: Print config file run: | - echo "Running test with environment: ${{ inputs.environment }}" + echo "Running test with environment: ${{ inputs.environment || 'prod' }}" - name: run test - run: cd js && TEST_ENVIRONMENT=${{ inputs.environment }} pnpm test:coverage --max-workers 16 + run: cd js && TEST_ENV=${{ inputs.environment || 'prod' }} pnpm test:coverage --max-workers 16 - name: Upload `coverage` folder to R2 if: ${{ always() }} @@ -126,4 +126,3 @@ jobs: https://pub-92e668239ab84bfd80ee07d61e9d2f40.r2.dev/html-report-${{ github.run_id }}/html-report/report.html reactions: rocket comment-id: ${{ steps.fc.outputs.comment-id }} - diff --git a/js/src/sdk/index.ts b/js/src/sdk/index.ts index 2e8287b365b..7d76685f6b3 100644 --- a/js/src/sdk/index.ts +++ b/js/src/sdk/index.ts @@ -18,6 +18,7 @@ import { Triggers } from "./models/triggers"; import { ZAuthMode } from "./types/integration"; import ComposioSDKContext from "./utils/composioContext"; import { getSDKConfig } from "./utils/config"; +import { IS_DEVELOPMENT_OR_CI } from "./utils/constants"; import { CEG } from "./utils/error"; import { COMPOSIO_SDK_ERROR_CODES } from "./utils/errors/src/constants"; import { isNewerVersion } from "./utils/other"; @@ -62,6 +63,11 @@ export class Composio { config?.apiKey ); + if (IS_DEVELOPMENT_OR_CI) { + logger.info( + `Initializing Composio w API Key: [REDACTED] and baseURL: ${baseURLParsed}` + ); + } ComposioSDKContext.apiKey = apiKeyParsed; ComposioSDKContext.sessionId = getUUID(); ComposioSDKContext.baseURL = baseURLParsed; diff --git a/js/src/utils/external.ts b/js/src/utils/external.ts index 4d790a5304c..62cb6e21750 100644 --- a/js/src/utils/external.ts +++ b/js/src/utils/external.ts @@ -24,7 +24,7 @@ export function sendProcessReq(info: { }) { if (IS_DEVELOPMENT_OR_CI) { // eslint-disable-next-line no-console - console.log( + logger.debug( `Hitting ${info.url}[${info.method}] with ${serializeValue(info.data)}` ); return true; From 0eb60c70685c989b9c7cf596b1cf389818ef36e2 Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Thu, 16 Jan 2025 13:07:50 +0530 Subject: [PATCH 25/34] feat: integration list, reinitiate and update schema (#1189) --- js/Makefile | 7 + js/config/getTestConfig.ts | 6 +- js/package.json | 2 +- js/src/sdk/client/client.ts | 2 + js/src/sdk/client/schemas.gen.ts | 2219 +++++++++++++++--------- js/src/sdk/client/services.gen.ts | 103 ++ js/src/sdk/client/types.gen.ts | 1718 ++++++++++++------ js/src/sdk/index.ts | 7 +- js/src/sdk/models/Entity.spec.ts | 9 +- js/src/sdk/models/connectedAccounts.ts | 163 +- js/src/sdk/models/integrations.spec.ts | 2 +- js/src/sdk/models/integrations.ts | 68 +- js/src/sdk/types/connectedAccount.ts | 8 +- js/src/sdk/types/integration.ts | 1 + 14 files changed, 2815 insertions(+), 1500 deletions(-) diff --git a/js/Makefile b/js/Makefile index 68eeb2bad76..228764fbbcc 100644 --- a/js/Makefile +++ b/js/Makefile @@ -7,6 +7,13 @@ install: build: pnpm run build +.PHONY: api_client_generate +api_client_generate: + pnpm run openapispec:generate + sed -i '' '/export type in = '\''query'\'' | '\''header'\'';/d' src/sdk/client/types.gen.ts + sed -i '' 's/successfull: boolean/successfull?: boolean/g' src/sdk/client/types.gen.ts + pnpm prettier + .PHONY: lint lint: pnpm run lint diff --git a/js/config/getTestConfig.ts b/js/config/getTestConfig.ts index 6a63a6baf09..f36d1fe9672 100644 --- a/js/config/getTestConfig.ts +++ b/js/config/getTestConfig.ts @@ -1,4 +1,4 @@ -export const env = process.env.TEST_ENV || "prod" +export const env = process.env.TEST_ENV || "staging" const CURRENT_FILE_DIR = __dirname; export type BACKEND_CONFIG = { @@ -12,6 +12,6 @@ export const getTestConfig = (): BACKEND_CONFIG => { return JSON.parse(JSON.stringify(require(path))) as unknown as BACKEND_CONFIG; } catch (error) { console.error("Error loading test config file:", error); - throw new Error("Error loading test config file. You can create test.{{env}}.json file in the config folder."); + throw new Error(`Error loading test config file. You can create test.config.${env}.json file in the config folder.`); } -} \ No newline at end of file +} diff --git a/js/package.json b/js/package.json index 8656a8a9171..2bb05840cd0 100644 --- a/js/package.json +++ b/js/package.json @@ -14,7 +14,7 @@ "test:watch": "jest --testMatch=\"**/*.spec.ts\" --watch", "test:coverage": "jest --coverage --testMatch=\"**/*.spec.ts\"", "type-docs": "typedoc", - "openapispec:generate": "npx @hey-api/openapi-ts", + "openapispec:generate": "npx @hey-api/openapi-ts ", "run:cli": "ts-node src/cli/index.ts", "run:sample": "ts-node sample.ts", "prettier": "prettier --write 'src/**/*.{ts,js,cjs}'", diff --git a/js/src/sdk/client/client.ts b/js/src/sdk/client/client.ts index 85dd4361bd5..07c4dcd9496 100644 --- a/js/src/sdk/client/client.ts +++ b/js/src/sdk/client/client.ts @@ -8,7 +8,9 @@ export default { clientAuth: SDKClient.ClientService, cli: SDKClient.CliService, appConnector: SDKClient.IntegrationsService, + appConnectorV2: SDKClient.IntegrationsV2Service, apps: SDKClient.AppsService, connections: SDKClient.ConnectionsService, + connectionsV2: SDKClient.Connectionsv2Service, triggers: SDKClient.TriggersService, }; diff --git a/js/src/sdk/client/schemas.gen.ts b/js/src/sdk/client/schemas.gen.ts index c388c43142e..d59ef218ecb 100644 --- a/js/src/sdk/client/schemas.gen.ts +++ b/js/src/sdk/client/schemas.gen.ts @@ -333,6 +333,172 @@ export const $ProjectIdNotFoundError = { required: ["name", "status", "message", "requestId", "details", "type"], } as const; +export const $ApiKeyNotFoundError = { + properties: { + name: { + minLength: 1, + type: "string", + enum: ["ApiKeyNotFoundError"], + description: "The error name", + }, + status: { + minLength: 1, + type: "number", + description: "HTTP status code", + }, + message: { + minLength: 1, + type: "string", + description: "Error message", + }, + requestId: { + type: "string", + description: + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", + }, + }, + type: "object", + required: ["name", "status", "message", "requestId"], +} as const; + +export const $DeleteFailedError = { + properties: { + name: { + minLength: 1, + type: "string", + enum: ["DeleteFailedError"], + description: "The error name", + }, + status: { + minLength: 1, + type: "number", + description: "HTTP status code", + }, + message: { + minLength: 1, + type: "string", + description: "Error message", + }, + requestId: { + type: "string", + description: + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", + }, + type: { + minLength: 1, + type: "string", + enum: ["InternalServerError"], + description: "The type of error", + }, + }, + type: "object", + required: ["name", "status", "message", "requestId", "type"], +} as const; + +export const $InvalidMagicLinkTokenError = { + properties: { + name: { + minLength: 1, + type: "string", + enum: ["InvalidMagicLinkTokenError"], + description: "The error name", + }, + status: { + minLength: 1, + type: "number", + description: "HTTP status code", + }, + message: { + minLength: 1, + type: "string", + description: "Error message", + }, + requestId: { + type: "string", + description: + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", + }, + details: { + type: "object", + description: "Additional arguments that caused the error", + }, + type: { + minLength: 1, + type: "string", + enum: ["BadRequestError"], + description: "The type of error", + }, + }, + type: "object", + required: ["name", "status", "message", "requestId", "details", "type"], +} as const; + +export const $UserAlreadyExistError = { + properties: { + name: { + minLength: 1, + type: "string", + enum: ["UserAlreadyExistError"], + description: "The error name", + }, + status: { + minLength: 1, + type: "number", + description: "HTTP status code", + }, + message: { + minLength: 1, + type: "string", + description: "Error message", + }, + requestId: { + type: "string", + description: + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", + }, + details: { + type: "object", + description: "Additional arguments that caused the error", + }, + type: { + minLength: 1, + type: "string", + enum: ["BadRequestError"], + description: "The type of error", + }, + }, + type: "object", + required: ["name", "status", "message", "requestId", "details", "type"], +} as const; + +export const $FetchTokenError = { + properties: { + name: { + minLength: 1, + type: "string", + enum: ["FetchTokenError"], + description: "The error name", + }, + status: { + minLength: 1, + type: "number", + description: "HTTP status code", + }, + message: { + minLength: 1, + type: "string", + description: "Error message", + }, + requestId: { + type: "string", + description: + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", + }, + }, + type: "object", + required: ["name", "status", "message", "requestId"], +} as const; + export const $MagicLinkResDTO = { properties: { status: { @@ -1315,6 +1481,13 @@ export const $AppQueryDTO = { example: "true", default: "false", }, + sortBy: { + enum: ["alphabet", "usage", "no_sort"], + type: "string", + description: "Sort the apps by usage or alphabetically", + example: "usage", + default: "alphabetically", + }, }, type: "object", } as const; @@ -1793,7 +1966,7 @@ export const $GetConnectorListResDTO = { properties: { items: { items: { - type: "object", + $ref: "#/components/schemas/ConnectorListItemDTO", }, type: "array", description: @@ -2208,7 +2381,7 @@ export const $ConnectedAccountResponseDTO = { "The entity ID associated with the connection. Learn more about entities [here](https://docs.composio.dev/patterns/Auth/connected_account#entities).", }, status: { - enum: ["INITIATED", "ACTIVE", "FAILED"], + enum: ["INITIATED", "ACTIVE", "FAILED", "EXPIRED"], type: "string", description: "The current status of the connection (e.g. 'active', 'inactive', 'pending').", @@ -2366,9 +2539,9 @@ export const $GetConnectionsQueryDto = { "Flag to show only active connections. Defaults to false if not specified.", }, status: { - enum: ["INITIATED", "ACTIVE", "FAILED"], type: "string", - description: "The status of the connection to filter by.", + description: + "Comma-separated list of connection statuses to filter by. The statuses are 'ACTIVE', 'EXPIRED', 'FAILED', 'INITIATED'.", }, integrationId: { format: "uuid", @@ -2467,6 +2640,23 @@ export const $InitiateConnectionPayloadDto = { required: ["data", "integrationId"], } as const; +export const $ReinitiateConnectionPayloadDto = { + properties: { + data: { + type: "object", + description: + "The data required to initiate a connection. Structure varies by integration type.", + }, + redirectUri: { + type: "string", + description: + "The URL to redirect to after the connection is successfully initiated.", + }, + }, + type: "object", + required: ["data"], +} as const; + export const $UpdateConnectionLabelsPayloadDto = { properties: { labels: { @@ -2537,1309 +2727,1432 @@ export const $ConnectedAccountNotFoundError = { required: ["name", "status", "message", "requestId", "type"], } as const; -export const $ToolsExecuteReqDto = { +export const $ListTriggersQueryDTO = { properties: { - actionName: { + appNames: { type: "string", + description: + "Comma-separated list of app names to filter connections by. You can get the app names from the `name` field in the response of the `GET /api/v1/apps` endpoint.", }, - runInSandbox: { - type: "boolean", - }, - input: { - type: "object", - }, - nlaInput: { + connectedAccountIds: { type: "string", + description: + "Comma-separated list of connected account IDs to filter triggers by. Returns all the possible triggers you can setup for these connected accounts. You can get the connected account IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint.", }, - authorizationData: { - type: "object", - }, - appSchema: { - type: "object", + triggerIds: { + type: "string", + description: + "(Deprecated) Please use `triggerNames` instead. Comma-separated list of trigger names to filter triggers by. You can get the trigger names from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", + deprecated: true, }, - customDescription: { + triggerNames: { type: "string", + description: + "Comma-separated list of trigger names to filter triggers by. You can get the trigger names from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", }, - systemPrompt: { + integrationIds: { type: "string", + description: + "Comma-separated list of integration IDs to filter triggers by. You can get the integration IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint.", + }, + showEnabledOnly: { + type: "boolean", + description: + "When set to true, returns only enabled triggers. This field is deprecated and will be removed in future versions.", + deprecated: true, }, }, type: "object", - required: ["actionName", "runInSandbox", "input"], } as const; -export const $DirectExecuteReqDto = { +export const $GetActiveTriggersQueryDTO = { properties: { - endpoint: { + connectedAccountIds: { type: "string", + description: + "Comma-separated list of connected account IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint.", }, - base_url: { + integrationIds: { + type: "string", + description: + "Comma-separated list of integration IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint.", + }, + triggerIds: { type: "string", + description: + "Comma-separated list of trigger IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/triggers` endpoint.", }, - headers: { - type: "object", + triggerNames: { + type: "string", + description: + "Comma-separated list of trigger names to filter triggers by. You can get these names from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", }, - queryParams: { - type: "object", + page: { + type: "number", + description: "Page number for pagination. Starts from 1.", }, - body: { - type: "object", + limit: { + type: "number", + description: "Number of items to return per page.", + }, + showDisabled: { + type: "boolean", + description: + "When set to true, includes disabled triggers in the response.", }, }, type: "object", - required: ["endpoint", "base_url", "headers", "queryParams"], } as const; -export const $ActionExecutionResDto = { +export const $GetLogsQueryDTO = { properties: { - data: { - type: "object", - description: "The response data returned by the action execution.", - }, - error: { + connectionId: { type: "string", description: - "The error message, if the action failed to execute. If the action is successful, this will be null.", + "Filter logs by connection ID. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", }, - successfull: { - type: "boolean", + integrationId: { + type: "string", description: - "Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message.", - deprecated: true, + "Filter logs by integration ID. You can get this from the `id` field in the response of the `GET /api/v1/integrations` endpoint.", }, - successful: { - type: "boolean", - description: - "Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message.", + page: { + type: "number", + description: "Page number for pagination. Starts from 1.", + }, + limit: { + type: "number", + description: "Number of items to return per page.", }, }, type: "object", - required: ["data", "successfull", "successful"], } as const; -export const $CustomAuthDTO = { +export const $TriggerResDTO = { properties: { - base_url: { + name: { type: "string", description: - "The base URL (root address) what you should use while making http requests to the connected account. For example, for gmail, it would be 'https://gmail.googleapis.com'", + "Unique identifier of the trigger. This is used to reference the trigger in other API calls.", }, - parameters: { - items: { - $ref: "#/components/schemas/Parameter", - }, - type: "array", + display_name: { + type: "string", + description: "Human-readable name of the trigger shown in the UI.", }, - body: { + description: { + type: "string", + description: "Detailed description of what the trigger does.", + }, + enabled: { + type: "boolean", + description: "Indicates whether the trigger is currently enabled.", + }, + config: { type: "object", description: - "The body to be sent to the endpoint for authentication. This can either be a JSON field or a string. Note: This is very rarely neeed and is only required by very few apps.", + "Configuration parameters required for the trigger. Structure varies based on trigger type.", }, - }, - type: "object", - required: ["parameters"], - description: - "Custom authentication credentials to use while executing an action.", -} as const; - -export const $ActionProxyRequestMethodDTO = { - properties: { - type: { - enum: ["formData", "urlEncoded", "raw", "binary", "graphql", "none"], + payload: { + type: "object", + description: "Sample payload that will be sent when the trigger fires.", + }, + logo: { + type: "string", + description: "URL of the trigger's icon or logo.", + }, + count: { + type: "number", + description: "Number of times this trigger has been activated.", + }, + appKey: { + type: "string", + description: "Unique key identifying the app this trigger belongs to.", + }, + appId: { type: "string", description: - "The type of request body to use for the action. Defaults to 'none'.", + "Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint.", }, - data: { + appName: { + type: "string", + description: "Name of the app this trigger belongs to.", + }, + instructions: { type: "string", description: - "The data to be sent to the endpoint. This will override the body set in the connected account.", + "Step-by-step instructions on how to set up and use this trigger.", + }, + type: { + type: "string", + description: "Classification or category of the trigger.", }, }, type: "object", + required: ["name", "display_name", "appKey", "appId", "appName"], } as const; -export const $GetSingleActionReqDTO = { +export const $SingleTriggerResDTO = { properties: { - actionId: { - minLength: 1, + name: { type: "string", description: - "The id of the action to get details for. This can be found in the id field in [/api/v2/actions](/api-reference/actions/list-actions) endpoint.", + "Unique identifier of the trigger. Used to reference the trigger in other API calls.", }, - }, - type: "object", - required: ["actionId"], -} as const; - -export const $ActionProxyRequestConfigDTO = { - properties: { - connectedAccountId: { + displayName: { type: "string", - description: "The connected account uuid to use for the action.", + description: "Human-readable name of the trigger shown in the UI.", }, - endpoint: { + description: { type: "string", description: - "The endpoint to call for the action. If the given url is relative, it will be resolved relative to the base_url set in the connected account info.", + "Detailed description of what the trigger does and when it fires.", }, - method: { - enum: ["GET", "POST", "PUT", "PATCH", "DELETE"], + type: { type: "string", - description: "The HTTP method to use for the action.", - }, - parameters: { - items: { - $ref: "#/components/schemas/Parameter", - }, - type: "array", + description: "Classification or category of the trigger.", }, - body: { - type: "object", + appId: { + type: "string", description: - "The body to be sent to the endpoint. This can either be a JSON field or a string.", + "Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint.", }, - }, - type: "object", - required: ["connectedAccountId", "endpoint", "method", "parameters"], -} as const; - -export const $SessionInfoDTO = { - properties: { - sessionId: { + appName: { type: "string", + description: "Name of the app this trigger belongs to.", }, - metadata: { + instructions: { + type: "string", + description: + "Step-by-step instructions on how to set up and use this trigger.", + }, + payload: { + type: "object", + description: "Sample payload that will be sent when the trigger fires.", + }, + config: { type: "object", + description: + "Configuration parameters required for the trigger. Structure varies based on trigger type.", }, }, type: "object", - description: - "Used internally by our SDK's to keep track of the source of execution, ignore it.", + required: [ + "name", + "displayName", + "description", + "type", + "appId", + "appName", + "payload", + "config", + ], } as const; -export const $NLAArgumentsResponseDTO = { +export const $TriggerConfig = { properties: { - arguments: { - type: "object", - description: - "The arguments for the action needed to execute the given task.", + repo: { + type: "string", + description: "Name of the repository to monitor.", }, - error: { + owner: { type: "string", - description: - "The error message if the arguments were not generated successfully.", + description: "Owner (user or organization) of the repository.", }, }, type: "object", + required: ["repo", "owner"], + description: "Configuration parameters for a trigger", } as const; -export const $ActionExecutionReqDTO = { +export const $ActiveTriggerInstance = { properties: { - connectedAccountId: { - format: "uuid", + id: { type: "string", - description: - "Connected account uuid for the account you want to run the action on. You can get this from the id field in [/api/v1/connectedAccounts](/api-reference/connections/list-connections) endpoint.", + description: "Unique identifier of the trigger instance.", }, - appName: { + connectionId: { type: "string", description: - "The name/id of the app that the action belongs to. To get the app name, you can use the [/api/v1/apps](/api-reference/apps/list-apps) endpoint.", + "ID of the connected account this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", }, - entityId: { + triggerName: { type: "string", description: - "(Optional) EntityId that represents your users connections - if the required connection is availabe for the user, it'll be auto-picked. If you are passing this, there's no need to pass `connectedAccountId`. To know more about entityId, [click here](https://backend.composio.dev/patterns/Auth/connected_account#entities)", - }, - input: { - type: "object", - description: - "Action inputs or aguments to execute the action. This is a dict/map with key-value structure, depdning on the action schema you can find in [/api/v2/actions/{actionName}](/api-reference/actions/get-single-action) endpoint.", + "Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", }, - sessionInfo: { - $ref: "#/components/schemas/SessionInfoDTO", + triggerData: { + type: "string", + description: "Additional data associated with the trigger instance.", }, - authConfig: { - $ref: "#/components/schemas/CustomAuthDTO", + triggerConfig: { + $ref: "#/components/schemas/TriggerConfig", }, - text: { + createdAt: { type: "string", - description: - "The use-case description for the action, this will give context to LLM to generate the correct inputs for the action.", + description: "ISO 8601 timestamp when the trigger instance was created.", + format: "date-time", }, - customDescription: { + updatedAt: { type: "string", description: - "The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case.", + "ISO 8601 timestamp when the trigger instance was last updated.", + format: "date-time", }, - systemPrompt: { + disabledAt: { type: "string", description: - "The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM.", + "ISO 8601 timestamp when the trigger instance was disabled, if applicable.", + format: "date-time", + nullable: true, }, }, type: "object", + required: [ + "connectionId", + "triggerName", + "triggerConfig", + "createdAt", + "updatedAt", + ], } as const; -export const $ActionGetNLAInputsReqDTO = { +export const $PageInfoDTO = { properties: { - text: { - minLength: 1, - type: "string", - description: - "The use-case description for the action, this will give context to LLM to generate the correct inputs for the action.", + currentPage: { + type: "number", + description: "Current page number.", }, - customDescription: { - type: "string", - description: - "The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case.", + perPage: { + type: "number", + description: "Number of items per page.", }, - systemPrompt: { - type: "string", - description: - "The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM.", + totalPages: { + type: "number", + description: "Total number of pages available.", }, }, type: "object", - required: ["text"], + required: ["currentPage", "perPage", "totalPages"], } as const; -export const $ProxyExecutionReqDTO = { +export const $ActiveTriggersResDTO = { properties: { - endpoint: { - type: "string", + triggers: { + items: { + $ref: "#/components/schemas/ActiveTriggerInstance", + }, + type: "array", + description: "List of active trigger instances.", }, - connectedAccountId: { - type: "string", + pageInfo: { + items: { + $ref: "#/components/schemas/PageInfoDTO", + }, + type: "array", + description: "Pagination information for the response.", }, }, type: "object", - required: ["endpoint", "connectedAccountId"], + required: ["triggers", "pageInfo"], } as const; -export const $ActionNotFoundError = { +export const $TriggerLogsResDTO = { properties: { - name: { - minLength: 1, - type: "string", - enum: ["ActionNotFoundError"], - description: "The error name", - }, - status: { - minLength: 1, - type: "number", - description: "HTTP status code", - }, - message: { - minLength: 1, - type: "string", - description: "Error message", - }, - requestId: { - type: "string", - description: - "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", + data: { + items: { + $ref: "#/components/schemas/TriggerLogItemDTO", + }, + type: "array", + description: "List of trigger log entries.", }, - type: { - minLength: 1, - type: "string", - enum: ["NotFoundError"], - description: "The name of the operation that caused the error", + pageInfo: { + $ref: "#/components/schemas/PageInfoDTO", + description: "Pagination information for the response.", }, }, type: "object", - required: ["name", "status", "message", "requestId", "type"], + required: ["data", "pageInfo"], } as const; -export const $ActionDetailsMinimal = { +export const $TriggerLogItemDTO = { properties: { - description: { + clientId: { type: "string", description: - "The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description.", + "Unique identifier of the client that initiated the trigger.", }, - displayName: { + connectionId: { type: "string", description: - "The display name of the action, used to identify the action in the UI.", + "ID of the connection associated with this log entry. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", }, - logo: { + triggerType: { + enum: ["poll", "webhook"], type: "string", - description: "The logo of the app that the action belongs to.", + description: "Type of the trigger.", }, - name: { + errorTrigger: { type: "string", - description: - "The name of the action, used to identify the action in the UI.", + description: "Error message if the trigger failed.", + nullable: true, }, - tags: { - items: { - type: "string", - }, - type: "array", - description: - "The tags of the action, used to categorize the action in the UI.", + triggerClientError: { + type: "string", + description: "Client-side error message if any occurred.", + nullable: true, }, - deprecated: { - type: "boolean", - description: - "Whether the action is deprecated, if true, avoid using this action.", + triggerClientPayload: { + type: "string", + description: "Payload sent by the client when the trigger was activated.", + nullable: true, + }, + triggerClientResponse: { + type: "object", + description: "Payload sent by the client when the trigger was activated.", + nullable: true, + }, + triggerProviderPayload: { + type: "string", + description: "Payload received from the provider's API.", + nullable: true, + }, + triggerName: { + type: "string", + description: "Name of the trigger that generated this log entry.", + nullable: true, + }, + id: { + type: "string", + description: "Unique identifier for this log entry.", + }, + appKey: { + type: "string", + description: "Key identifying the app associated with this log entry.", + }, + createdAt: { + type: "string", + description: "ISO 8601 timestamp when this log entry was created.", + format: "date-time", }, }, type: "object", - required: ["description", "displayName", "logo", "name", "tags"], + required: ["clientId", "connectionId", "id", "appKey", "createdAt"], } as const; -export const $ActionsTagQueryReqDTO = { +export const $HandleTriggerParamsDTO = { properties: { - apps: { + appName: { type: "string", description: - "Comma separated list of app names to filter the action tags by.", + "Name of the app handling the trigger. You can get this from the `name` field in the response of the `GET /api/v1/apps` endpoint.", + }, + clientId: { + type: "string", + description: "Unique identifier of the client initiating the trigger.", }, }, type: "object", + required: ["appName", "clientId"], } as const; -export const $ActionDetails = { +export const $HandleTriggerBodyDTO = { properties: { - parameters: { - type: "object", - description: - "Required parameters for the action to execute. For example, if the action is GMAIL_SEND_EMAIL, the required parameters for actions execution would be the email address, subject, and body.", - }, - response: { + body: { type: "object", - description: - "Expected response structure after action execution. You can use this to quickly check what happened with the action execution.", + description: "Payload data to be processed by the trigger.", }, - appKey: { + }, + type: "object", + required: ["body"], +} as const; + +export const $EnableTriggerParamsDTO = { + properties: { + connectedAccountId: { type: "string", description: - "The name of the app that the action belongs to. This is same as appId.", - }, - appName: { - type: "string", - description: "The name of the app that the action belongs to, ", + "ID of the connected account to enable the trigger for. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", }, - appId: { + triggerName: { type: "string", description: - "The id of the app that the action belongs to. This is same as the appKey. Please use appKey instead.", - deprecated: true, + "Name of the trigger to enable. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", }, - description: { + }, + type: "object", + required: ["connectedAccountId", "triggerName"], +} as const; + +export const $GetTriggerParamsDTO = { + properties: { + triggerId: { type: "string", description: - "The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description.", + "Unique identifier of the trigger to retrieve. You can get this from the `id` field in the response of the `GET /api/v1/triggers` endpoint.", }, - displayName: { - type: "string", + }, + type: "object", + required: ["triggerId"], +} as const; + +export const $EnableTriggerBodyDTO = { + properties: { + triggerConfig: { + type: "object", description: - "The display name of the action, used to identify the action in the UI.", + "Configuration parameters for the trigger. Structure varies based on trigger type.", }, - logo: { + verifyHost: { type: "string", - description: "The logo of the app that the action belongs to.", + description: "Host URL for webhook verification, if required.", }, - name: { + }, + type: "object", + required: ["triggerConfig"], +} as const; + +export const $SwitchTriggerStatusParamsDTO = { + properties: { + triggerId: { type: "string", description: - "The name of the action, used to identify the action in the UI.", - }, - tags: { - items: { - type: "string", - }, - type: "array", - description: - "The tags of the action, used to categorize the action in the UI.", + "Unique identifier of the trigger instance to update. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint.", }, - deprecated: { + }, + type: "object", + required: ["triggerId"], +} as const; + +export const $SwitchTriggerStatusBodyDTO = { + properties: { + enabled: { type: "boolean", - description: - "Whether the action is deprecated, if true, avoid using this action.", + description: "New enabled/disabled state for the trigger.", }, }, type: "object", - required: [ - "parameters", - "response", - "appKey", - "appName", - "appId", - "description", - "displayName", - "logo", - "name", - "tags", - ], + required: ["enabled"], } as const; -export const $ActionsTagsResponseDTO = { +export const $TriggerInstanceParamsDTO = { properties: { - items: { - items: { - type: "string", - }, - type: "array", - description: "List of all the action tags available in composio", + triggerInstanceId: { + type: "string", + description: + "Unique identifier of the trigger instance to modify. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint.", }, }, type: "object", - required: ["items"], + required: ["triggerInstanceId"], } as const; -export const $ActionsListResponseDTO = { +export const $SetCallbackUrlBodyDTO = { properties: { - items: { - items: { - $ref: "#/components/schemas/ActionDetails", - }, - type: "array", - }, - page: { - type: "number", - description: "Current page number in the paginated response", - example: 1, - }, - totalPages: { - type: "number", - description: "Total number of pages available", + callbackURL: { + type: "string", + description: + "URL where webhook notifications should be sent when the trigger fires.", }, }, type: "object", - required: ["items", "page", "totalPages"], + required: ["callbackURL"], } as const; -export const $ActionsMinimalListResponseDTO = { +export const $TriggerResponseDTO = { properties: { - items: { - items: { - $ref: "#/components/schemas/ActionDetailsMinimal", - }, - type: "array", + status: { + type: "string", + description: "Status of the operation (success/error).", }, - page: { - type: "number", + message: { + type: "string", + description: "Additional information about the operation result.", }, - totalPages: { - type: "number", + triggerId: { + type: "string", + description: "Unique identifier of the affected trigger.", + }, + isNew: { + type: "boolean", + description: + "Indicates whether a new trigger was created (true) or an existing one was modified (false).", }, }, type: "object", - required: ["items", "page", "totalPages"], + required: ["status"], } as const; -export const $AdvancedUseCaseSearchBodyDTO = { +export const $WebhookURLResponseDTO = { properties: { - useCase: { + status: { + type: "string", + description: "Status of the operation (success/error).", + }, + callbackURL: { type: "string", + description: "The currently configured webhook callback URL.", }, }, type: "object", + required: ["status"], } as const; -export const $AdvancedUseCaseSearchQueryDTO = { +export const $TriggerMetadataDTO = { properties: { - useCase: { + id: { + type: "string", + description: "Unique identifier of the trigger.", + }, + connectionId: { type: "string", - deprecated: true, description: - "Use case is deprecated. Please provide this in the body instead to avoid max-uri-length error.", + "ID of the connection this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", }, - limit: { - type: "number", + triggerName: { + type: "string", + description: + "Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", }, - maxActionsPerTask: { - type: "number", + triggerData: { + type: "string", + description: "Additional data associated with the trigger.", }, - minActionsPerTask: { - type: "number", + triggerConfig: { + type: "object", + description: + "Configuration parameters for the trigger. Structure varies based on trigger type.", }, - apps: { + state: { + type: "object", + description: "Current state of the trigger.", + }, + createdAt: { type: "string", + description: "ISO 8601 timestamp when the trigger was created.", + format: "date-time", }, - filterByAvailableApps: { - type: "boolean", + updatedAt: { + type: "string", + description: "ISO 8601 timestamp when the trigger was last updated.", + format: "date-time", + }, + disabledAt: { + type: "string", + description: + "ISO 8601 timestamp when the trigger was disabled, if applicable.", + format: "date-time", + nullable: true, + }, + disabledReason: { + type: "string", + description: "Reason why the trigger was disabled, if applicable.", + nullable: true, }, }, type: "object", + required: [ + "id", + "connectionId", + "triggerName", + "triggerData", + "triggerConfig", + "state", + "createdAt", + "updatedAt", + ], + description: "Detailed information about a trigger", } as const; -export const $AdvancedUseCaseSearchTask = { +export const $GetTriggerResponseDTO = { properties: { - app: { - type: "string", - }, - actions: { - items: { - type: "string", - }, - type: "array", - }, - description: { + status: { type: "string", + description: "Status of the operation (success/error).", }, - order: { - type: "number", + trigger: { + $ref: "#/components/schemas/TriggerMetadataDTO", }, }, type: "object", - required: ["app", "actions", "description", "order"], + required: ["status"], } as const; -export const $AdvancedUseCaseSearchResponse = { +export const $WehbookNewFormatDTO = { properties: { - items: { - items: { - $ref: "#/components/schemas/AdvancedUseCaseSearchTask", - }, - type: "array", + id: { + type: "string", + description: "Unique identifier of the project.", + }, + isNewWebhook: { + type: "boolean", + description: "Indicates whether this is a newly created webhook.", }, }, type: "object", - required: ["items"], + required: ["id", "isNewWebhook"], } as const; -export const $ExecuteActionResDTO = { +export const $TriggerNotFoundError = { properties: { - response_data: { - type: "boolean", - description: "Indicates if the action was executed successfully", + name: { + enum: ["TriggerNotFoundError"], + type: "string", + description: "The name of the error", + example: "TriggerNotFoundError", }, - execution_details: { - type: "object", - description: "Details of the execution status", + status: { + minLength: 1, + type: "number", + description: "HTTP status code", + }, + message: { + minLength: 1, + type: "string", + description: "Error message", + }, + requestId: { + type: "string", + description: + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", + }, + type: { + minLength: 1, + type: "string", + enum: ["NotFoundError"], + description: "The name of the operation that caused the error", }, }, type: "object", - required: ["response_data", "execution_details"], + required: ["name", "status", "message", "requestId", "type"], } as const; -export const $ActionsQueryDTO = { +export const $InvalidTriggerConfigError = { properties: { - appNames: { + name: { + enum: ["InvalidTriggerConfigError"], type: "string", - description: "Names of the apps", + description: "The name of the error", + example: "InvalidTriggerConfigError", }, - useCase: { + status: { + minLength: 1, + type: "number", + description: "HTTP status code", + }, + message: { + minLength: 1, type: "string", - description: "Use case", + description: "Error message", }, - showEnabledOnly: { - type: "boolean", - description: "Show enabled only", + requestId: { + type: "string", + description: + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", }, - limit: { - type: "number", - description: "Limit", + details: { + type: "object", + description: "Additional arguments that caused the error", }, - apps: { + type: { + minLength: 1, type: "string", + enum: ["BadRequestError"], + description: "The type of error", }, - actions: { + }, + type: "object", + required: ["name", "status", "message", "requestId", "details", "type"], +} as const; + +export const $ToolsExecuteReqDto = { + properties: { + actionName: { type: "string", }, - tags: { + runInSandbox: { + type: "boolean", + }, + input: { + type: "object", + }, + nlaInput: { type: "string", }, - usecaseLimit: { - type: "number", + authorizationData: { + type: "object", }, - filterImportantActions: { - type: "boolean", + appSchema: { + type: "object", }, - showAll: { - type: "boolean", + customDescription: { + type: "string", }, - page: { - type: "number", + systemPrompt: { + type: "string", }, - }, - type: "object", -} as const; - -export const $ActionsControllerV1 = { - properties: { - getAction: { - items: { - type: "object", - }, - type: "array", + version: { + type: "string", }, }, type: "object", - required: ["getAction"], + required: ["actionName", "runInSandbox", "input"], } as const; -export const $OAuth2CallbackQueryDto = { +export const $DirectExecuteReqDto = { properties: { - state: { + endpoint: { type: "string", }, - }, - type: "object", - required: ["state"], -} as const; - -export const $RedirectUriDTO = { - properties: { - redirectUri: { + base_url: { type: "string", }, + headers: { + type: "object", + }, + queryParams: { + type: "object", + }, + body: { + type: "object", + }, }, type: "object", + required: ["endpoint", "base_url", "headers", "queryParams"], } as const; -export const $ListTriggersQueryDTO = { +export const $ActionExecutionResDto = { properties: { - appNames: { - type: "string", - description: - "Comma-separated list of app names to filter connections by. You can get the app names from the `name` field in the response of the `GET /api/v1/apps` endpoint.", - }, - connectedAccountIds: { - type: "string", - description: - "Comma-separated list of connected account IDs to filter triggers by. Returns all the possible triggers you can setup for these connected accounts. You can get the connected account IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint.", + data: { + type: "object", + description: "The response data returned by the action execution.", }, - triggerIds: { + error: { type: "string", description: - "Comma-separated list of trigger names to filter triggers by. You can get the trigger names from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", + "The error message, if the action failed to execute. If the action is successful, this will be null.", }, - integrationIds: { - type: "string", + successfull: { + type: "boolean", description: - "Comma-separated list of integration IDs to filter triggers by. You can get the integration IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint.", + "Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message.", + deprecated: true, }, - showEnabledOnly: { + successful: { type: "boolean", description: - "When set to true, returns only enabled triggers. This field is deprecated and will be removed in future versions.", - deprecated: true, + "Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message.", }, }, type: "object", + required: ["data", "successfull", "successful"], } as const; -export const $GetActiveTriggersQueryDTO = { +export const $CustomAuthDTO = { properties: { - connectedAccountIds: { + base_url: { type: "string", description: - "Comma-separated list of connected account IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint.", + "The base URL (root address) what you should use while making http requests to the connected account. For example, for gmail, it would be 'https://gmail.googleapis.com'", }, - integrationIds: { - type: "string", - description: - "Comma-separated list of integration IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint.", + parameters: { + items: { + $ref: "#/components/schemas/Parameter", + }, + type: "array", }, - triggerIds: { - type: "string", + body: { + type: "object", description: - "Comma-separated list of trigger IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/triggers` endpoint.", + "The body to be sent to the endpoint for authentication. This can either be a JSON field or a string. Note: This is very rarely neeed and is only required by very few apps.", }, - triggerNames: { + }, + type: "object", + required: ["parameters"], + description: + "Custom authentication credentials to use while executing an action.", +} as const; + +export const $ActionProxyRequestMethodDTO = { + properties: { + type: { + enum: ["formData", "urlEncoded", "raw", "binary", "graphql", "none"], type: "string", description: - "Comma-separated list of trigger names to filter triggers by. You can get these names from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", - }, - page: { - type: "number", - description: "Page number for pagination. Starts from 1.", - }, - limit: { - type: "number", - description: "Number of items to return per page.", + "The type of request body to use for the action. Defaults to 'none'.", }, - showDisabled: { - type: "boolean", + data: { + type: "string", description: - "When set to true, includes disabled triggers in the response.", + "The data to be sent to the endpoint. This will override the body set in the connected account.", }, }, type: "object", } as const; -export const $GetLogsQueryDTO = { +export const $GetSingleActionReqDTO = { properties: { - connectionId: { + actionId: { + minLength: 1, type: "string", description: - "Filter logs by connection ID. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", + "The id of the action to get details for. This can be found in the id field in [/api/v2/actions](/api-reference/actions/list-actions) endpoint.", }, - integrationId: { + }, + type: "object", + required: ["actionId"], +} as const; + +export const $GetSingleActionQueryDTO = { + properties: { + version: { type: "string", - description: - "Filter logs by integration ID. You can get this from the `id` field in the response of the `GET /api/v1/integrations` endpoint.", - }, - page: { - type: "number", - description: "Page number for pagination. Starts from 1.", - }, - limit: { - type: "number", - description: "Number of items to return per page.", + description: "Version for the action", }, }, type: "object", } as const; -export const $TriggerResDTO = { +export const $ActionProxyRequestConfigDTO = { properties: { - name: { + connectedAccountId: { type: "string", - description: - "Unique identifier of the trigger. This is used to reference the trigger in other API calls.", + description: "The connected account uuid to use for the action.", }, - display_name: { + endpoint: { type: "string", - description: "Human-readable name of the trigger shown in the UI.", + description: + "The endpoint to call for the action. If the given url is relative, it will be resolved relative to the base_url set in the connected account info.", }, - description: { + method: { + enum: ["GET", "POST", "PUT", "PATCH", "DELETE"], type: "string", - description: "Detailed description of what the trigger does.", + description: "The HTTP method to use for the action.", }, - enabled: { - type: "boolean", - description: "Indicates whether the trigger is currently enabled.", + parameters: { + items: { + $ref: "#/components/schemas/Parameter", + }, + type: "array", }, - config: { + body: { type: "object", description: - "Configuration parameters required for the trigger. Structure varies based on trigger type.", - }, - payload: { - type: "object", - description: "Sample payload that will be sent when the trigger fires.", + "The body to be sent to the endpoint. This can either be a JSON field or a string.", }, - logo: { + }, + type: "object", + required: ["connectedAccountId", "endpoint", "method", "parameters"], +} as const; + +export const $SessionInfoDTO = { + properties: { + sessionId: { type: "string", - description: "URL of the trigger's icon or logo.", }, - count: { - type: "number", - description: "Number of times this trigger has been activated.", - }, - appKey: { - type: "string", - description: "Unique key identifying the app this trigger belongs to.", + metadata: { + type: "object", }, - appId: { - type: "string", + }, + type: "object", + description: + "Used internally by our SDK's to keep track of the source of execution, ignore it.", +} as const; + +export const $NLAArgumentsResponseDTO = { + properties: { + arguments: { + type: "object", description: - "Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint.", - }, - appName: { - type: "string", - description: "Name of the app this trigger belongs to.", + "The arguments for the action needed to execute the given task.", }, - instructions: { + error: { type: "string", description: - "Step-by-step instructions on how to set up and use this trigger.", - }, - type: { - type: "string", - description: "Classification or category of the trigger.", + "The error message if the arguments were not generated successfully.", }, }, type: "object", - required: ["name", "display_name", "appKey", "appId", "appName"], } as const; -export const $SingleTriggerResDTO = { +export const $ActionExecutionReqDTO = { properties: { - name: { + connectedAccountId: { + format: "uuid", type: "string", description: - "Unique identifier of the trigger. Used to reference the trigger in other API calls.", + "Connected account uuid for the account you want to run the action on. You can get this from the id field in [/api/v1/connectedAccounts](/api-reference/connections/list-connections) endpoint.", }, - displayName: { + appName: { type: "string", - description: "Human-readable name of the trigger shown in the UI.", + description: + "The name/id of the app that the action belongs to. To get the app name, you can use the [/api/v1/apps](/api-reference/apps/list-apps) endpoint.", + }, + entityId: { + type: "string", + description: + "(Optional) EntityId that represents your users connections - if the required connection is availabe for the user, it'll be auto-picked. If you are passing this, there's no need to pass `connectedAccountId`. To know more about entityId, [click here](https://backend.composio.dev/patterns/Auth/connected_account#entities)", + }, + input: { + type: "object", + description: + "Action inputs or aguments to execute the action. This is a dict/map with key-value structure, depdning on the action schema you can find in [/api/v2/actions/{actionName}](/api-reference/actions/get-single-action) endpoint.", + }, + sessionInfo: { + $ref: "#/components/schemas/SessionInfoDTO", + }, + authConfig: { + $ref: "#/components/schemas/CustomAuthDTO", }, - description: { + text: { type: "string", description: - "Detailed description of what the trigger does and when it fires.", + "The use-case description for the action, this will give context to LLM to generate the correct inputs for the action.", }, - type: { + customDescription: { type: "string", - description: "Classification or category of the trigger.", + description: + "The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case.", }, - appId: { + systemPrompt: { type: "string", description: - "Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint.", + "The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM.", }, - appName: { + version: { type: "string", - description: "Name of the app this trigger belongs to.", + description: "Version of the action you want to execute.", }, - instructions: { + }, + type: "object", +} as const; + +export const $ActionGetNLAInputsReqDTO = { + properties: { + text: { + minLength: 1, type: "string", description: - "Step-by-step instructions on how to set up and use this trigger.", + "The use-case description for the action, this will give context to LLM to generate the correct inputs for the action.", }, - payload: { - type: "object", - description: "Sample payload that will be sent when the trigger fires.", + customDescription: { + type: "string", + description: + "The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case.", }, - config: { - type: "object", + systemPrompt: { + type: "string", description: - "Configuration parameters required for the trigger. Structure varies based on trigger type.", + "The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM.", }, }, type: "object", - required: [ - "name", - "displayName", - "description", - "type", - "appId", - "appName", - "payload", - "config", - ], + required: ["text"], } as const; -export const $TriggerConfig = { +export const $ProxyExecutionReqDTO = { properties: { - repo: { + endpoint: { type: "string", - description: "Name of the repository to monitor.", }, - owner: { + connectedAccountId: { type: "string", - description: "Owner (user or organization) of the repository.", }, }, type: "object", - required: ["repo", "owner"], - description: "Configuration parameters for a trigger", + required: ["endpoint", "connectedAccountId"], } as const; -export const $ActiveTriggerInstance = { +export const $ActionNotFoundError = { properties: { - id: { - type: "string", - description: "Unique identifier of the trigger instance.", - }, - connectionId: { - type: "string", - description: - "ID of the connected account this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", - }, - triggerName: { - type: "string", - description: - "Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", - }, - triggerData: { + name: { + minLength: 1, type: "string", - description: "Additional data associated with the trigger instance.", + enum: ["ActionNotFoundError"], + description: "The error name", }, - triggerConfig: { - $ref: "#/components/schemas/TriggerConfig", + status: { + minLength: 1, + type: "number", + description: "HTTP status code", }, - createdAt: { + message: { + minLength: 1, type: "string", - description: "ISO 8601 timestamp when the trigger instance was created.", - format: "date-time", + description: "Error message", }, - updatedAt: { + requestId: { type: "string", description: - "ISO 8601 timestamp when the trigger instance was last updated.", - format: "date-time", + "Request ID, used for tracing the request. This is very helpful for internal teams to debug issues.", }, - disabledAt: { + type: { + minLength: 1, type: "string", - description: - "ISO 8601 timestamp when the trigger instance was disabled, if applicable.", - format: "date-time", - nullable: true, + enum: ["NotFoundError"], + description: "The name of the operation that caused the error", }, }, type: "object", - required: [ - "connectionId", - "triggerName", - "triggerConfig", - "createdAt", - "updatedAt", - ], + required: ["name", "status", "message", "requestId", "type"], } as const; -export const $PageInfoDTO = { +export const $ActionDetailsMinimal = { properties: { - currentPage: { - type: "number", - description: "Current page number.", + description: { + type: "string", + description: + "The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description.", }, - perPage: { - type: "number", - description: "Number of items per page.", + displayName: { + type: "string", + description: + "The display name of the action, used to identify the action in the UI.", }, - totalPages: { - type: "number", - description: "Total number of pages available.", + logo: { + type: "string", + description: "The logo of the app that the action belongs to.", }, - }, - type: "object", - required: ["currentPage", "perPage", "totalPages"], -} as const; - -export const $ActiveTriggersResDTO = { - properties: { - triggers: { - items: { - type: "object", - }, - type: "array", - description: "List of active trigger instances.", + name: { + type: "string", + description: + "The name of the action, used to identify the action in the UI.", }, - pageInfo: { + tags: { items: { - $ref: "#/components/schemas/PageInfoDTO", + type: "string", }, type: "array", - description: "Pagination information for the response.", + description: + "The tags of the action, used to categorize the action in the UI.", + }, + deprecated: { + type: "boolean", + description: + "Whether the action is deprecated, if true, avoid using this action.", }, }, type: "object", - required: ["triggers", "pageInfo"], + required: ["description", "displayName", "logo", "name", "tags"], } as const; -export const $TriggerLogsResDTO = { +export const $ActionsTagQueryReqDTO = { properties: { - data: { - items: { - $ref: "#/components/schemas/TriggerLogItemDTO", - }, - type: "array", - description: "List of trigger log entries.", - }, - pageInfo: { - $ref: "#/components/schemas/PageInfoDTO", - description: "Pagination information for the response.", + apps: { + type: "string", + description: + "Comma separated list of app names to filter the action tags by.", }, }, type: "object", - required: ["data", "pageInfo"], } as const; -export const $TriggerLogItemDTO = { +export const $ActionDetails = { properties: { - clientId: { - type: "string", + parameters: { + type: "object", description: - "Unique identifier of the client that initiated the trigger.", + "Required parameters for the action to execute. For example, if the action is GMAIL_SEND_EMAIL, the required parameters for actions execution would be the email address, subject, and body.", }, - connectionId: { - type: "string", + response: { + type: "object", description: - "ID of the connection associated with this log entry. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", + "Expected response structure after action execution. You can use this to quickly check what happened with the action execution.", }, - errorTrigger: { + appKey: { type: "string", - description: "Error message if the trigger failed.", - nullable: true, + description: + "The name of the app that the action belongs to. This is same as appId.", }, - triggerClientError: { + appName: { type: "string", - description: "Client-side error message if any occurred.", - nullable: true, + description: "The name of the app that the action belongs to, ", }, - triggerClientPayload: { + appId: { type: "string", - description: "Payload sent by the client when the trigger was activated.", - nullable: true, + description: + "The id of the app that the action belongs to. This is same as the appKey. Please use appKey instead.", + deprecated: true, }, - triggerProviderPayload: { + version: { type: "string", - description: "Payload received from the provider's API.", - nullable: true, + description: "Version of the action schema.", }, - triggerName: { - type: "string", - description: "Name of the trigger that generated this log entry.", - nullable: true, + available_versions: { + items: { + type: "object", + }, + type: "array", + description: "List of availavle versions of the action.", }, - id: { - type: "string", - description: "Unique identifier for this log entry.", + no_auth: { + type: "boolean", + description: "Whether or not the action requires auth or not", }, - appKey: { + description: { type: "string", - description: "Key identifying the app associated with this log entry.", + description: + "The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description.", }, - createdAt: { + displayName: { type: "string", - description: "ISO 8601 timestamp when this log entry was created.", - format: "date-time", + description: + "The display name of the action, used to identify the action in the UI.", }, - }, - type: "object", - required: ["clientId", "connectionId", "id", "appKey", "createdAt"], -} as const; - -export const $HandleTriggerParamsDTO = { - properties: { - appName: { + logo: { + type: "string", + description: "The logo of the app that the action belongs to.", + }, + name: { type: "string", description: - "Name of the app handling the trigger. You can get this from the `name` field in the response of the `GET /api/v1/apps` endpoint.", + "The name of the action, used to identify the action in the UI.", }, - clientId: { - type: "string", - description: "Unique identifier of the client initiating the trigger.", + tags: { + items: { + type: "string", + }, + type: "array", + description: + "The tags of the action, used to categorize the action in the UI.", + }, + deprecated: { + type: "boolean", + description: + "Whether the action is deprecated, if true, avoid using this action.", }, }, type: "object", - required: ["appName", "clientId"], + required: [ + "parameters", + "response", + "appKey", + "appName", + "appId", + "version", + "available_versions", + "no_auth", + "description", + "displayName", + "logo", + "name", + "tags", + ], } as const; -export const $HandleTriggerBodyDTO = { +export const $ActionsTagsResponseDTO = { properties: { - body: { - type: "object", - description: "Payload data to be processed by the trigger.", + items: { + items: { + type: "string", + }, + type: "array", + description: "List of all the action tags available in composio", }, }, type: "object", - required: ["body"], + required: ["items"], } as const; -export const $EnableTriggerParamsDTO = { +export const $ActionsListResponseDTO = { properties: { - connectedAccountId: { - type: "string", - description: - "ID of the connected account to enable the trigger for. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", + items: { + items: { + $ref: "#/components/schemas/ActionDetails", + }, + type: "array", }, - triggerName: { - type: "string", - description: - "Name of the trigger to enable. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", + page: { + type: "number", + description: "Current page number in the paginated response", + example: 1, + }, + totalPages: { + type: "number", + description: "Total number of pages available", }, }, type: "object", - required: ["connectedAccountId", "triggerName"], + required: ["items", "page", "totalPages"], } as const; -export const $GetTriggerParamsDTO = { +export const $ActionsMinimalListResponseDTO = { properties: { - triggerId: { - type: "string", - description: - "Unique identifier of the trigger to retrieve. You can get this from the `id` field in the response of the `GET /api/v1/triggers` endpoint.", + items: { + items: { + $ref: "#/components/schemas/ActionDetailsMinimal", + }, + type: "array", + }, + page: { + type: "number", + }, + totalPages: { + type: "number", }, }, type: "object", - required: ["triggerId"], + required: ["items", "page", "totalPages"], } as const; -export const $EnableTriggerBodyDTO = { +export const $AdvancedUseCaseSearchBodyDTO = { properties: { - triggerConfig: { - type: "object", - description: - "Configuration parameters for the trigger. Structure varies based on trigger type.", - }, - verifyHost: { + useCase: { type: "string", - description: "Host URL for webhook verification, if required.", }, }, type: "object", - required: ["triggerConfig"], } as const; -export const $SwitchTriggerStatusParamsDTO = { +export const $AdvancedUseCaseSearchQueryDTO = { properties: { - triggerId: { + useCase: { type: "string", + deprecated: true, description: - "Unique identifier of the trigger instance to update. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint.", + "Use case is deprecated. Please provide this in the body instead to avoid max-uri-length error.", }, - }, - type: "object", - required: ["triggerId"], -} as const; - -export const $SwitchTriggerStatusBodyDTO = { - properties: { - enabled: { + limit: { + type: "number", + }, + maxActionsPerTask: { + type: "number", + }, + minActionsPerTask: { + type: "number", + }, + apps: { + type: "string", + }, + filterByAvailableApps: { type: "boolean", - description: "New enabled/disabled state for the trigger.", }, }, type: "object", - required: ["enabled"], } as const; -export const $TriggerInstanceParamsDTO = { +export const $AdvancedUseCaseSearchTask = { properties: { - triggerInstanceId: { + app: { type: "string", - description: - "Unique identifier of the trigger instance to modify. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint.", }, - }, - type: "object", - required: ["triggerInstanceId"], -} as const; - -export const $SetCallbackUrlBodyDTO = { - properties: { - callbackURL: { + actions: { + items: { + type: "string", + }, + type: "array", + }, + description: { type: "string", - description: - "URL where webhook notifications should be sent when the trigger fires.", + }, + order: { + type: "number", }, }, type: "object", - required: ["callbackURL"], + required: ["app", "actions", "description", "order"], } as const; -export const $TriggerResponseDTO = { +export const $AdvancedUseCaseSearchResponse = { properties: { - status: { - type: "string", - description: "Status of the operation (success/error).", - }, - message: { - type: "string", - description: "Additional information about the operation result.", - }, - triggerId: { - type: "string", - description: "Unique identifier of the affected trigger.", - }, - isNew: { - type: "boolean", - description: - "Indicates whether a new trigger was created (true) or an existing one was modified (false).", + items: { + items: { + $ref: "#/components/schemas/AdvancedUseCaseSearchTask", + }, + type: "array", }, }, type: "object", - required: ["status"], + required: ["items"], } as const; -export const $WebhookURLResponseDTO = { +export const $ExecuteActionResDTO = { properties: { - status: { - type: "string", - description: "Status of the operation (success/error).", + response_data: { + type: "boolean", + description: "Indicates if the action was executed successfully", }, - callbackURL: { - type: "string", - description: "The currently configured webhook callback URL.", + execution_details: { + type: "object", + description: "Details of the execution status", }, }, type: "object", - required: ["status"], + required: ["response_data", "execution_details"], } as const; -export const $TriggerMetadataDTO = { +export const $ActionsQueryDTO = { properties: { - id: { + appNames: { type: "string", - description: "Unique identifier of the trigger.", + description: "Names of the apps", }, - connectionId: { + useCase: { type: "string", - description: - "ID of the connection this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint.", + description: "Use case", }, - triggerName: { + showEnabledOnly: { + type: "boolean", + description: "Show enabled only", + }, + limit: { + type: "number", + description: "Limit", + }, + apps: { type: "string", - description: - "Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint.", }, - triggerData: { + actions: { type: "string", - description: "Additional data associated with the trigger.", }, - triggerConfig: { - type: "object", - description: - "Configuration parameters for the trigger. Structure varies based on trigger type.", + tags: { + type: "string", }, - state: { - type: "object", - description: "Current state of the trigger.", + usecaseLimit: { + type: "number", }, - createdAt: { - type: "string", - description: "ISO 8601 timestamp when the trigger was created.", - format: "date-time", + filterImportantActions: { + type: "boolean", }, - updatedAt: { - type: "string", - description: "ISO 8601 timestamp when the trigger was last updated.", - format: "date-time", + showAll: { + type: "boolean", }, - disabledAt: { - type: "string", - description: - "ISO 8601 timestamp when the trigger was disabled, if applicable.", - format: "date-time", - nullable: true, + page: { + type: "number", }, - disabledReason: { - type: "string", - description: "Reason why the trigger was disabled, if applicable.", - nullable: true, + }, + type: "object", +} as const; + +export const $ActionsControllerV1 = { + properties: { + getAction: { + items: { + type: "object", + }, + type: "array", }, }, type: "object", - required: [ - "id", - "connectionId", - "triggerName", - "triggerData", - "triggerConfig", - "state", - "createdAt", - "updatedAt", - ], - description: "Detailed information about a trigger", + required: ["getAction"], } as const; -export const $GetTriggerResponseDTO = { +export const $OAuth2CallbackQueryDto = { properties: { - status: { + state: { type: "string", - description: "Status of the operation (success/error).", - }, - trigger: { - $ref: "#/components/schemas/TriggerMetadataDTO", }, }, type: "object", - required: ["status"], + required: ["state"], } as const; -export const $WehbookNewFormatDTO = { +export const $RedirectUriDTO = { properties: { - id: { + redirectUri: { type: "string", - description: "Unique identifier of the project.", - }, - isNewWebhook: { - type: "boolean", - description: "Indicates whether this is a newly created webhook.", }, }, type: "object", - required: ["id", "isNewWebhook"], } as const; export const $ReadOnlyQueryReqDTO = { @@ -4267,49 +4580,50 @@ export const $LogsResDTO = { export const $GetLogsDTO = { properties: { - type: { - enum: ["error", "info", "debug"], - type: "string", - description: "Type of the log", - }, time: { enum: ["5m", "30m", "6h", "1d", "1w", "1month", "1y"], type: "string", - description: "Time interval for which data needs to be fetched", + description: "Return logs from the last N time units", }, status: { enum: ["all", "success", "error"], type: "string", - description: "Status of the log", + description: "Filter logs by their status level, defaults to all", }, search: { type: "string", - description: "Search term in the log", + description: "Search term to filter logs by", }, integrationId: { + format: "uuid", type: "string", - description: "Integration UUID", + description: + "The ID/UUID of the integration to filter connections by. You can get the integration ID from the [/api/v1/integrations](/api-reference/integrations/list-integrations) endpoint.", }, entityId: { type: "string", - description: "Entity id", + description: + "Filter logs by entity Id, useful for debugging issues for your specific users. Learn more about entityId [here](https://docs.composio.dev/patterns/Auth/connected_account)", }, limit: { type: "number", - description: "Limit of the logs", + description: "Maximum number of logs to return, defaults to 10", default: 10, }, cursor: { type: "string", - description: "Cursor for pagination", + description: + "Cursor for pagination, used to fetch next set of logs. You can get the cursor from the previous response of this endpoint.", }, logsType: { + enum: ["action", "trigger"], type: "string", description: "Type of the log", }, sessionId: { type: "string", - description: "Session ID of the log", + description: + "Session ID of the log, used to filter logs by session. Helpful in debugging issues with specific logs.", }, }, type: "object", @@ -4402,6 +4716,11 @@ export const $ActionsQueryV2DTO = { description: "Filter and return only important actions. This is equivalent to setting tags='important' in the query params mentioned above.", }, + sortBy: { + enum: ["alphabet", "usage", "no_sort"], + type: "string", + description: "Sort the actions by usage or alphabetical", + }, }, type: "object", } as const; @@ -4752,3 +5071,303 @@ export const $UpdateRowAPIDTO = { type: "object", required: ["status", "count"], } as const; + +export const $AppFilterDTO = { + properties: { + uniqueKey: { + type: "string", + description: "List of app unique keys to filter by", + }, + integrationId: { + type: "string", + description: "List of app unique keys to filter by", + }, + }, + type: "object", +} as const; + +export const $ComposioSearchConfigDTO = { + properties: { + useComposioAuth: { + type: "boolean", + description: "Whether to use Composio authentication", + }, + authScheme: { + type: "string", + enum: [ + "OAUTH2", + "OAUTH1", + "OAUTH1A", + "API_KEY", + "BASIC", + "BEARER_TOKEN", + "GOOGLE_SERVICE_ACCOUNT", + "NO_AUTH", + "BASIC_WITH_JWT", + "COMPOSIO_LINK", + "CALCOM_AUTH", + ], + description: "Authentication scheme to use", + }, + }, + type: "object", + required: ["authScheme"], +} as const; + +export const $ConnectorSearchFilterDTOV2 = { + properties: { + app: { + $ref: "#/components/schemas/AppFilterDTO", + description: "Filter options for the connector", + }, + config: { + $ref: "#/components/schemas/ComposioSearchConfigDTO", + description: "Filter options for the connector", + }, + }, + type: "object", + required: ["app", "config"], +} as const; + +export const $ConnectorSearchResDTO = { + properties: { + matchedIntegrationIds: { + items: { + type: "string", + }, + type: "array", + description: "List of matched integration ids", + }, + appInfo: { + type: "object", + description: "App info", + }, + }, + type: "object", + required: ["matchedIntegrationIds", "appInfo"], +} as const; + +export const $AppInfoPayload = { + properties: { + uniqueKey: { + type: "string", + description: "List of app unique keys to filter by", + }, + }, + type: "object", +} as const; + +export const $ComposioCreateConfigDTO = { + properties: { + name: { + type: "string", + description: "Name of the integration", + }, + useComposioAuth: { + type: "boolean", + description: "Whether to use Composio authentication", + }, + authScheme: { + type: "string", + enum: [ + "OAUTH2", + "OAUTH1", + "OAUTH1A", + "API_KEY", + "BASIC", + "BEARER_TOKEN", + "GOOGLE_SERVICE_ACCOUNT", + "NO_AUTH", + "BASIC_WITH_JWT", + "COMPOSIO_LINK", + "CALCOM_AUTH", + ], + description: "Authentication scheme to use", + }, + integrationSecrets: { + type: "object", + description: "Authentication configuration", + }, + }, + type: "object", + required: ["authScheme"], +} as const; + +export const $ConnectorCreateReqDTO = { + properties: { + app: { + $ref: "#/components/schemas/AppInfoPayload", + description: "Filter options for the connector", + }, + config: { + $ref: "#/components/schemas/ComposioCreateConfigDTO", + description: "Filter options for the connector", + }, + }, + type: "object", + required: ["app", "config"], +} as const; + +export const $CreateConnectorResDTO = { + properties: { + integrationId: { + type: "string", + description: "List of matched integration IDs", + }, + }, + type: "object", + required: ["integrationId"], +} as const; + +export const $GetOrCreateConnectorInfo = { + properties: { + app: { + $ref: "#/components/schemas/AppFilterDTO", + description: "Filter options for the connector", + }, + config: { + $ref: "#/components/schemas/ComposioCreateConfigDTO", + description: "Filter options for the connector", + }, + }, + type: "object", + required: ["app", "config"], +} as const; + +export const $GetOrCreateConnectorResDTOV2 = { + properties: { + integrationId: { + type: "string", + description: "Matched integration ID", + }, + isNewIntegration: { + type: "boolean", + description: "Whether a new integration was created", + }, + }, + type: "object", + required: ["integrationId"], +} as const; + +export const $ConnectionExtraData = { + properties: { + redirectURL: { + type: "string", + description: + "The URL to redirect to after the connection is successfully initiated.", + }, + labels: { + items: { + type: "string", + }, + type: "array", + description: + "Array of labels to associate with the connection for organization and filtering.", + }, + }, + type: "object", +} as const; + +export const $ConnectionInitData = { + properties: { + initiateData: { + minLength: 1, + type: "object", + description: + "Data required to initiate the connection. The structure varies based on the integration type.", + }, + entityId: { + type: "string", + description: + "The entity ID to associate with the connection. Learn more about entities [here](https://docs.composio.dev/patterns/Auth/connected_account#entities).", + }, + extra: { + $ref: "#/components/schemas/ConnectionExtraData", + type: "object", + description: + "The URL to redirect to after the connection is successfully initiated.", + }, + }, + type: "object", + required: ["initiateData"], +} as const; + +export const $InitiateConnectionPayloadDtoV2 = { + properties: { + app: { + $ref: "#/components/schemas/AppFilterDTO", + description: + "Filter criteria to identify the app for which to create a connection.", + }, + config: { + $ref: "#/components/schemas/ComposioCreateConfigDTO", + description: + "Configuration options for the connection, including authentication scheme and settings.", + }, + connection: { + $ref: "#/components/schemas/ConnectionInitData", + description: + "Additional metadata and configuration options for the connection.", + }, + }, + type: "object", + required: ["app", "config", "connection"], +} as const; + +export const $IntegrationData = { + properties: { + id: { + minLength: 1, + type: "string", + description: + "Unique identifier of the integration used for this connection.", + }, + isNewIntegration: { + minLength: 1, + type: "boolean", + description: + "Indicates whether a new integration was created during this connection process.", + }, + }, + type: "object", + required: ["id", "isNewIntegration"], +} as const; + +export const $ConnectionResponseV2 = { + properties: { + redirectUrl: { + type: "string", + description: + "The URL to redirect to after the connection is successfully initiated.", + }, + connectionStatus: { + minLength: 1, + type: "string", + enum: ["INITIATED", "ACTIVE", "FAILED", "EXPIRED"], + description: "The current status of the connection.", + }, + connectedAccountId: { + minLength: 1, + type: "string", + description: "The unique identifier of the connected account.", + }, + }, + type: "object", + required: ["connectionStatus", "connectedAccountId"], +} as const; + +export const $InitiateConnectionResponseV2 = { + properties: { + integration: { + $ref: "#/components/schemas/IntegrationData", + description: + "Details about the integration associated with this connection.", + }, + connectionResponse: { + $ref: "#/components/schemas/ConnectionResponseV2", + description: "Response data containing connection details and status.", + }, + }, + type: "object", + required: ["integration", "connectionResponse"], +} as const; diff --git a/js/src/sdk/client/services.gen.ts b/js/src/sdk/client/services.gen.ts index 9236468e2bb..ffff0e27844 100644 --- a/js/src/sdk/client/services.gen.ts +++ b/js/src/sdk/client/services.gen.ts @@ -15,6 +15,9 @@ import type { CreateConnectorData, CreateConnectorError, CreateConnectorResponse, + CreateConnectorV2Data, + CreateConnectorV2Error, + CreateConnectorV2Response, CreateProjectData, CreateProjectError, CreateProjectResponse, @@ -86,6 +89,9 @@ import type { GetLogsData, GetLogsError, GetLogsResponse, + GetOrCreateConnectorData, + GetOrCreateConnectorError, + GetOrCreateConnectorResponse, GetOrgApiKeyError, GetOrgApiKeyResponse, GetProjectData, @@ -106,6 +112,9 @@ import type { InitiateConnectionData, InitiateConnectionError, InitiateConnectionResponse2, + InitiateConnectionV2Data, + InitiateConnectionV2Error, + InitiateConnectionV2Response, InviteMemberData, InviteMemberError, InviteMemberResponse, @@ -151,9 +160,15 @@ import type { RegenerateProjectApiKeyData, RegenerateProjectApiKeyError, RegenerateProjectApiKeyResponse, + ReinitiateConnectionData, + ReinitiateConnectionError, + ReinitiateConnectionResponse, RenameProjectData, RenameProjectError, RenameProjectResponse, + SearchConnectorData, + SearchConnectorError, + SearchConnectorResponse, SetCallbackUrlData, SetCallbackUrlError, SetCallbackUrlResponse, @@ -738,6 +753,23 @@ export class ConnectionsService { }); } + /** + * Reinitiate connection + * Reinitiate an existing connection to get new credentials + */ + public static reinitiateConnection( + options: Options + ) { + return (options?.client ?? client).post< + ReinitiateConnectionResponse, + ReinitiateConnectionError, + ThrowOnError + >({ + ...options, + url: "/api/v1/connectedAccounts/{connectedAccountId}/reinitiate", + }); + } + /** * Get single connection */ @@ -1214,3 +1246,74 @@ export class ProjectsService { }); } } + +export class IntegrationsV2Service { + /** + * Search connector + * Search for a connector + */ + public static searchConnector( + options?: Options + ) { + return (options?.client ?? client).post< + SearchConnectorResponse, + SearchConnectorError, + ThrowOnError + >({ + ...options, + url: "/api/v2/integrations/search-by-filters", + }); + } + + /** + * Create connector + * Create a new connector + */ + public static createConnectorV2( + options?: Options + ) { + return (options?.client ?? client).post< + CreateConnectorV2Response, + CreateConnectorV2Error, + ThrowOnError + >({ + ...options, + url: "/api/v2/integrations/create", + }); + } + + /** + * Get or create connector + * Get or create a connector + */ + public static getOrCreateConnector( + options?: Options + ) { + return (options?.client ?? client).post< + GetOrCreateConnectorResponse, + GetOrCreateConnectorError, + ThrowOnError + >({ + ...options, + url: "/api/v2/integrations/get-or-create", + }); + } +} + +export class Connectionsv2Service { + /** + * Initiate connection + */ + public static initiateConnectionV2( + options?: Options + ) { + return (options?.client ?? client).post< + InitiateConnectionV2Response, + InitiateConnectionV2Error, + ThrowOnError + >({ + ...options, + url: "/api/v2/connectedAccounts/initiateConnection", + }); + } +} diff --git a/js/src/sdk/client/types.gen.ts b/js/src/sdk/client/types.gen.ts index ebf1ecfac39..d035cef7c34 100644 --- a/js/src/sdk/client/types.gen.ts +++ b/js/src/sdk/client/types.gen.ts @@ -261,6 +261,150 @@ export type ProjectIdNotFoundError = { */ export type name3 = "ProjectNotFoundError"; +export type ApiKeyNotFoundError = { + /** + * The error name + */ + name: "ApiKeyNotFoundError"; + /** + * HTTP status code + */ + status: number; + /** + * Error message + */ + message: string; + /** + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. + */ + requestId: string; +}; + +/** + * The error name + */ +export type name4 = "ApiKeyNotFoundError"; + +export type DeleteFailedError = { + /** + * The error name + */ + name: "DeleteFailedError"; + /** + * HTTP status code + */ + status: number; + /** + * Error message + */ + message: string; + /** + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. + */ + requestId: string; + /** + * The type of error + */ + type: "InternalServerError"; +}; + +/** + * The error name + */ +export type name5 = "DeleteFailedError"; + +export type InvalidMagicLinkTokenError = { + /** + * The error name + */ + name: "InvalidMagicLinkTokenError"; + /** + * HTTP status code + */ + status: number; + /** + * Error message + */ + message: string; + /** + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. + */ + requestId: string; + /** + * Additional arguments that caused the error + */ + details: { + [key: string]: unknown; + }; + /** + * The type of error + */ + type: "BadRequestError"; +}; + +/** + * The error name + */ +export type name6 = "InvalidMagicLinkTokenError"; + +export type UserAlreadyExistError = { + /** + * The error name + */ + name: "UserAlreadyExistError"; + /** + * HTTP status code + */ + status: number; + /** + * Error message + */ + message: string; + /** + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. + */ + requestId: string; + /** + * Additional arguments that caused the error + */ + details: { + [key: string]: unknown; + }; + /** + * The type of error + */ + type: "BadRequestError"; +}; + +/** + * The error name + */ +export type name7 = "UserAlreadyExistError"; + +export type FetchTokenError = { + /** + * The error name + */ + name: "FetchTokenError"; + /** + * HTTP status code + */ + status: number; + /** + * Error message + */ + message: string; + /** + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. + */ + requestId: string; +}; + +/** + * The error name + */ +export type name8 = "FetchTokenError"; + export type MagicLinkResDTO = { status: string; }; @@ -908,6 +1052,10 @@ export type AppQueryDTO = { * Filter to include locally developed/testing apps in the response. Must be 'true' or 'false' */ includeLocal?: "true" | "false"; + /** + * Sort the apps by usage or alphabetically + */ + sortBy?: "alphabet" | "usage" | "no_sort"; }; /** @@ -915,6 +1063,11 @@ export type AppQueryDTO = { */ export type includeLocal = "true" | "false"; +/** + * Sort the apps by usage or alphabetically + */ +export type sortBy = "alphabet" | "usage" | "no_sort"; + export type AppInfoResponseDto = { /** * Unique identifier (UUID) for the app @@ -1210,9 +1363,7 @@ export type GetConnectorListResDTO = { /** * Array of connector items matching the query parameters. Each item contains detailed information about a connector and its associated connections. */ - items: Array<{ - [key: string]: unknown; - }>; + items: Array; /** * Total number of pages available based on the current page size. Use this for implementing pagination controls. */ @@ -1441,7 +1592,7 @@ export type ConnectedAccountResponseDTO = { /** * The current status of the connection (e.g. 'active', 'inactive', 'pending'). */ - status: "INITIATED" | "ACTIVE" | "FAILED"; + status: "INITIATED" | "ACTIVE" | "FAILED" | "EXPIRED"; /** * Flag to indicate if the connected account is enabled. This will be true if the connected account is active and can be used to perform actions. */ @@ -1459,7 +1610,7 @@ export type ConnectedAccountResponseDTO = { /** * The current status of the connection (e.g. 'active', 'inactive', 'pending'). */ -export type status3 = "INITIATED" | "ACTIVE" | "FAILED"; +export type status3 = "INITIATED" | "ACTIVE" | "FAILED" | "EXPIRED"; export type GetConnectionsResponseDto = { /** @@ -1508,6 +1659,10 @@ export type Parameter = { value: string; }; +/** + * The location of the parameter. Can be 'query' or 'header'. + */ + export type Data = { /** * First field of the data object. @@ -1548,9 +1703,9 @@ export type GetConnectionsQueryDto = { */ showActiveOnly?: boolean; /** - * The status of the connection to filter by. + * Comma-separated list of connection statuses to filter by. The statuses are 'ACTIVE', 'EXPIRED', 'FAILED', 'INITIATED'. */ - status?: "INITIATED" | "ACTIVE" | "FAILED"; + status?: string; /** * The ID/UUID of the integration to filter connections by. You can get the integration ID from the [/api/v1/integrations](/api-reference/integrations/list-integrations) endpoint. */ @@ -1617,6 +1772,19 @@ export type InitiateConnectionPayloadDto = { labels?: Array; }; +export type ReinitiateConnectionPayloadDto = { + /** + * The data required to initiate a connection. Structure varies by integration type. + */ + data: { + [key: string]: unknown; + }; + /** + * The URL to redirect to after the connection is successfully initiated. + */ + redirectUri?: string; +}; + export type UpdateConnectionLabelsPayloadDto = { /** * Array of new labels to assign to the connection. @@ -1665,912 +1833,1018 @@ export type ConnectedAccountNotFoundError = { /** * The name of the error */ -export type name4 = "ConnectedAccountNotFoundError"; - -export type ToolsExecuteReqDto = { - actionName: string; - runInSandbox: boolean; - input: { - [key: string]: unknown; - }; - nlaInput?: string; - authorizationData?: { - [key: string]: unknown; - }; - appSchema?: { - [key: string]: unknown; - }; - customDescription?: string; - systemPrompt?: string; -}; - -export type DirectExecuteReqDto = { - endpoint: string; - base_url: string; - headers: { - [key: string]: unknown; - }; - queryParams: { - [key: string]: unknown; - }; - body?: { - [key: string]: unknown; - }; -}; +export type name9 = "ConnectedAccountNotFoundError"; -export type ActionExecutionResDto = { +export type ListTriggersQueryDTO = { /** - * The response data returned by the action execution. + * Comma-separated list of app names to filter connections by. You can get the app names from the `name` field in the response of the `GET /api/v1/apps` endpoint. */ - data: { - [key: string]: unknown; - }; + appNames?: string; /** - * The error message, if the action failed to execute. If the action is successful, this will be null. + * Comma-separated list of connected account IDs to filter triggers by. Returns all the possible triggers you can setup for these connected accounts. You can get the connected account IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint. */ - error?: string; + connectedAccountIds?: string; /** - * Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message. + * (Deprecated) Please use `triggerNames` instead. Comma-separated list of trigger names to filter triggers by. You can get the trigger names from the `name` field in the response of the `GET /api/v1/triggers` endpoint. * @deprecated */ - successfull?: boolean; + triggerIds?: string; /** - * Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message. + * Comma-separated list of trigger names to filter triggers by. You can get the trigger names from the `name` field in the response of the `GET /api/v1/triggers` endpoint. */ - successful: boolean; -}; - -/** - * Custom authentication credentials to use while executing an action. - */ -export type CustomAuthDTO = { + triggerNames?: string; /** - * The base URL (root address) what you should use while making http requests to the connected account. For example, for gmail, it would be 'https://gmail.googleapis.com' + * Comma-separated list of integration IDs to filter triggers by. You can get the integration IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint. */ - base_url?: string; - parameters: Array; + integrationIds?: string; /** - * The body to be sent to the endpoint for authentication. This can either be a JSON field or a string. Note: This is very rarely neeed and is only required by very few apps. + * When set to true, returns only enabled triggers. This field is deprecated and will be removed in future versions. + * @deprecated */ - body?: { - [key: string]: unknown; - }; + showEnabledOnly?: boolean; }; -export type ActionProxyRequestMethodDTO = { +export type GetActiveTriggersQueryDTO = { /** - * The type of request body to use for the action. Defaults to 'none'. + * Comma-separated list of connected account IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint. */ - type?: "formData" | "urlEncoded" | "raw" | "binary" | "graphql" | "none"; + connectedAccountIds?: string; /** - * The data to be sent to the endpoint. This will override the body set in the connected account. + * Comma-separated list of integration IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint. */ - data?: string; -}; - -/** - * The type of request body to use for the action. Defaults to 'none'. - */ -export type type4 = - | "formData" - | "urlEncoded" - | "raw" - | "binary" - | "graphql" - | "none"; - -export type GetSingleActionReqDTO = { + integrationIds?: string; /** - * The id of the action to get details for. This can be found in the id field in [/api/v2/actions](/api-reference/actions/list-actions) endpoint. + * Comma-separated list of trigger IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/triggers` endpoint. */ - actionId: string; -}; - -export type ActionProxyRequestConfigDTO = { + triggerIds?: string; /** - * The connected account uuid to use for the action. + * Comma-separated list of trigger names to filter triggers by. You can get these names from the `name` field in the response of the `GET /api/v1/triggers` endpoint. */ - connectedAccountId: string; + triggerNames?: string; /** - * The endpoint to call for the action. If the given url is relative, it will be resolved relative to the base_url set in the connected account info. + * Page number for pagination. Starts from 1. */ - endpoint: string; + page?: number; /** - * The HTTP method to use for the action. + * Number of items to return per page. */ - method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; - parameters: Array; + limit?: number; /** - * The body to be sent to the endpoint. This can either be a JSON field or a string. + * When set to true, includes disabled triggers in the response. */ - body?: { - [key: string]: unknown; - }; -}; - -/** - * The HTTP method to use for the action. - */ -export type method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; - -/** - * Used internally by our SDK's to keep track of the source of execution, ignore it. - */ -export type SessionInfoDTO = { - sessionId?: string; - metadata?: { - [key: string]: unknown; - }; + showDisabled?: boolean; }; -export type NLAArgumentsResponseDTO = { +export type GetLogsQueryDTO = { /** - * The arguments for the action needed to execute the given task. + * Filter logs by connection ID. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. */ - arguments?: { - [key: string]: unknown; - }; + connectionId?: string; /** - * The error message if the arguments were not generated successfully. + * Filter logs by integration ID. You can get this from the `id` field in the response of the `GET /api/v1/integrations` endpoint. */ - error?: string; -}; - -export type ActionExecutionReqDTO = { + integrationId?: string; /** - * Connected account uuid for the account you want to run the action on. You can get this from the id field in [/api/v1/connectedAccounts](/api-reference/connections/list-connections) endpoint. + * Page number for pagination. Starts from 1. */ - connectedAccountId?: string; + page?: number; /** - * The name/id of the app that the action belongs to. To get the app name, you can use the [/api/v1/apps](/api-reference/apps/list-apps) endpoint. + * Number of items to return per page. */ - appName?: string; + limit?: number; +}; + +export type TriggerResDTO = { /** - * (Optional) EntityId that represents your users connections - if the required connection is availabe for the user, it'll be auto-picked. If you are passing this, there's no need to pass `connectedAccountId`. To know more about entityId, [click here](https://backend.composio.dev/patterns/Auth/connected_account#entities) + * Unique identifier of the trigger. This is used to reference the trigger in other API calls. */ - entityId?: string; + name: string; /** - * Action inputs or aguments to execute the action. This is a dict/map with key-value structure, depdning on the action schema you can find in [/api/v2/actions/{actionName}](/api-reference/actions/get-single-action) endpoint. + * Human-readable name of the trigger shown in the UI. */ - input?: { - [key: string]: unknown; - }; - sessionInfo?: SessionInfoDTO; - authConfig?: CustomAuthDTO; + display_name: string; /** - * The use-case description for the action, this will give context to LLM to generate the correct inputs for the action. + * Detailed description of what the trigger does. */ - text?: string; + description?: string; /** - * The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case. + * Indicates whether the trigger is currently enabled. */ - customDescription?: string; + enabled?: boolean; /** - * The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM. + * Configuration parameters required for the trigger. Structure varies based on trigger type. */ - systemPrompt?: string; -}; - -export type ActionGetNLAInputsReqDTO = { + config?: { + [key: string]: unknown; + }; /** - * The use-case description for the action, this will give context to LLM to generate the correct inputs for the action. + * Sample payload that will be sent when the trigger fires. */ - text: string; + payload?: { + [key: string]: unknown; + }; /** - * The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case. + * URL of the trigger's icon or logo. */ - customDescription?: string; + logo?: string; /** - * The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM. + * Number of times this trigger has been activated. */ - systemPrompt?: string; -}; - -export type ProxyExecutionReqDTO = { - endpoint: string; - connectedAccountId: string; -}; - -export type ActionNotFoundError = { + count?: number; /** - * The error name + * Unique key identifying the app this trigger belongs to. */ - name: "ActionNotFoundError"; + appKey: string; /** - * HTTP status code + * Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint. */ - status: number; + appId: string; /** - * Error message + * Name of the app this trigger belongs to. */ - message: string; + appName: string; /** - * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. + * Step-by-step instructions on how to set up and use this trigger. */ - requestId: string; + instructions?: string; /** - * The name of the operation that caused the error + * Classification or category of the trigger. */ - type: "NotFoundError"; + type?: string; }; -/** - * The error name - */ -export type name5 = "ActionNotFoundError"; - -export type ActionDetailsMinimal = { +export type SingleTriggerResDTO = { /** - * The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description. + * Unique identifier of the trigger. Used to reference the trigger in other API calls. */ - description: string; + name: string; /** - * The display name of the action, used to identify the action in the UI. + * Human-readable name of the trigger shown in the UI. */ displayName: string; /** - * The logo of the app that the action belongs to. + * Detailed description of what the trigger does and when it fires. */ - logo: string; + description: string; /** - * The name of the action, used to identify the action in the UI. + * Classification or category of the trigger. */ - name: string; + type: string; /** - * The tags of the action, used to categorize the action in the UI. + * Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint. */ - tags: Array; + appId: string; /** - * Whether the action is deprecated, if true, avoid using this action. + * Name of the app this trigger belongs to. */ - deprecated?: boolean; -}; - -export type ActionsTagQueryReqDTO = { + appName: string; /** - * Comma separated list of app names to filter the action tags by. + * Step-by-step instructions on how to set up and use this trigger. */ - apps?: string; -}; - -export type ActionDetails = { + instructions?: string; /** - * Required parameters for the action to execute. For example, if the action is GMAIL_SEND_EMAIL, the required parameters for actions execution would be the email address, subject, and body. + * Sample payload that will be sent when the trigger fires. */ - parameters: { + payload: { [key: string]: unknown; }; /** - * Expected response structure after action execution. You can use this to quickly check what happened with the action execution. + * Configuration parameters required for the trigger. Structure varies based on trigger type. */ - response: { + config: { [key: string]: unknown; }; +}; + +/** + * Configuration parameters for a trigger + */ +export type TriggerConfig = { /** - * The name of the app that the action belongs to. This is same as appId. + * Name of the repository to monitor. */ - appKey: string; + repo: string; /** - * The name of the app that the action belongs to, + * Owner (user or organization) of the repository. */ - appName: string; + owner: string; +}; + +export type ActiveTriggerInstance = { /** - * The id of the app that the action belongs to. This is same as the appKey. Please use appKey instead. - * @deprecated + * Unique identifier of the trigger instance. */ - appId: string; + id?: string; /** - * The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description. + * ID of the connected account this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. */ - description: string; + connectionId: string; /** - * The display name of the action, used to identify the action in the UI. + * Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint. */ - displayName: string; + triggerName: string; /** - * The logo of the app that the action belongs to. + * Additional data associated with the trigger instance. */ - logo: string; + triggerData?: string; + triggerConfig: TriggerConfig; /** - * The name of the action, used to identify the action in the UI. + * ISO 8601 timestamp when the trigger instance was created. */ - name: string; + createdAt: string; /** - * The tags of the action, used to categorize the action in the UI. + * ISO 8601 timestamp when the trigger instance was last updated. */ - tags: Array; + updatedAt: string; /** - * Whether the action is deprecated, if true, avoid using this action. + * ISO 8601 timestamp when the trigger instance was disabled, if applicable. */ - deprecated?: boolean; + disabledAt?: string | null; }; -export type ActionsTagsResponseDTO = { +export type PageInfoDTO = { /** - * List of all the action tags available in composio + * Current page number. */ - items: Array; -}; - -export type ActionsListResponseDTO = { - items: Array; + currentPage: number; /** - * Current page number in the paginated response + * Number of items per page. */ - page: number; + perPage: number; /** - * Total number of pages available + * Total number of pages available. */ totalPages: number; }; -export type ActionsMinimalListResponseDTO = { - items: Array; - page: number; - totalPages: number; -}; - -export type AdvancedUseCaseSearchBodyDTO = { - useCase?: string; +export type ActiveTriggersResDTO = { + /** + * List of active trigger instances. + */ + triggers: Array; + /** + * Pagination information for the response. + */ + pageInfo: Array; }; -export type AdvancedUseCaseSearchQueryDTO = { +export type TriggerLogsResDTO = { /** - * Use case is deprecated. Please provide this in the body instead to avoid max-uri-length error. - * @deprecated + * List of trigger log entries. */ - useCase?: string; - limit?: number; - maxActionsPerTask?: number; - minActionsPerTask?: number; - apps?: string; - filterByAvailableApps?: boolean; + data: Array; + /** + * Pagination information for the response. + */ + pageInfo: PageInfoDTO; }; -export type AdvancedUseCaseSearchTask = { - app: string; - actions: Array; - description: string; - order: number; +export type TriggerLogItemDTO = { + /** + * Unique identifier of the client that initiated the trigger. + */ + clientId: string; + /** + * ID of the connection associated with this log entry. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. + */ + connectionId: string; + /** + * Type of the trigger. + */ + triggerType?: "poll" | "webhook"; + /** + * Error message if the trigger failed. + */ + errorTrigger?: string | null; + /** + * Client-side error message if any occurred. + */ + triggerClientError?: string | null; + /** + * Payload sent by the client when the trigger was activated. + */ + triggerClientPayload?: string | null; + /** + * Payload sent by the client when the trigger was activated. + */ + triggerClientResponse?: { + [key: string]: unknown; + } | null; + /** + * Payload received from the provider's API. + */ + triggerProviderPayload?: string | null; + /** + * Name of the trigger that generated this log entry. + */ + triggerName?: string | null; + /** + * Unique identifier for this log entry. + */ + id: string; + /** + * Key identifying the app associated with this log entry. + */ + appKey: string; + /** + * ISO 8601 timestamp when this log entry was created. + */ + createdAt: string; }; -export type AdvancedUseCaseSearchResponse = { - items: Array; -}; +/** + * Type of the trigger. + */ +export type triggerType = "poll" | "webhook"; -export type ExecuteActionResDTO = { +export type HandleTriggerParamsDTO = { /** - * Indicates if the action was executed successfully + * Name of the app handling the trigger. You can get this from the `name` field in the response of the `GET /api/v1/apps` endpoint. */ - response_data: boolean; + appName: string; /** - * Details of the execution status + * Unique identifier of the client initiating the trigger. */ - execution_details: { + clientId: string; +}; + +export type HandleTriggerBodyDTO = { + /** + * Payload data to be processed by the trigger. + */ + body: { [key: string]: unknown; }; }; -export type ActionsQueryDTO = { +export type EnableTriggerParamsDTO = { /** - * Names of the apps + * ID of the connected account to enable the trigger for. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. */ - appNames?: string; + connectedAccountId: string; /** - * Use case + * Name of the trigger to enable. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint. */ - useCase?: string; + triggerName: string; +}; + +export type GetTriggerParamsDTO = { /** - * Show enabled only + * Unique identifier of the trigger to retrieve. You can get this from the `id` field in the response of the `GET /api/v1/triggers` endpoint. */ - showEnabledOnly?: boolean; + triggerId: string; +}; + +export type EnableTriggerBodyDTO = { /** - * Limit + * Configuration parameters for the trigger. Structure varies based on trigger type. */ - limit?: number; - apps?: string; - actions?: string; - tags?: string; - usecaseLimit?: number; - filterImportantActions?: boolean; - showAll?: boolean; - page?: number; + triggerConfig: { + [key: string]: unknown; + }; + /** + * Host URL for webhook verification, if required. + */ + verifyHost?: string; }; -export type ActionsControllerV1 = { - getAction: Array<{ - [key: string]: unknown; - }>; +export type SwitchTriggerStatusParamsDTO = { + /** + * Unique identifier of the trigger instance to update. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint. + */ + triggerId: string; }; -export type OAuth2CallbackQueryDto = { - state: string; +export type SwitchTriggerStatusBodyDTO = { + /** + * New enabled/disabled state for the trigger. + */ + enabled: boolean; }; -export type RedirectUriDTO = { - redirectUri?: string; +export type TriggerInstanceParamsDTO = { + /** + * Unique identifier of the trigger instance to modify. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint. + */ + triggerInstanceId: string; }; -export type ListTriggersQueryDTO = { +export type SetCallbackUrlBodyDTO = { /** - * Comma-separated list of app names to filter connections by. You can get the app names from the `name` field in the response of the `GET /api/v1/apps` endpoint. + * URL where webhook notifications should be sent when the trigger fires. */ - appNames?: string; + callbackURL: string; +}; + +export type TriggerResponseDTO = { /** - * Comma-separated list of connected account IDs to filter triggers by. Returns all the possible triggers you can setup for these connected accounts. You can get the connected account IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint. + * Status of the operation (success/error). */ - connectedAccountIds?: string; + status: string; /** - * Comma-separated list of trigger names to filter triggers by. You can get the trigger names from the `name` field in the response of the `GET /api/v1/triggers` endpoint. + * Additional information about the operation result. */ - triggerIds?: string; + message?: string; /** - * Comma-separated list of integration IDs to filter triggers by. You can get the integration IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint. + * Unique identifier of the affected trigger. */ - integrationIds?: string; + triggerId?: string; /** - * When set to true, returns only enabled triggers. This field is deprecated and will be removed in future versions. - * @deprecated + * Indicates whether a new trigger was created (true) or an existing one was modified (false). */ - showEnabledOnly?: boolean; + isNew?: boolean; }; -export type GetActiveTriggersQueryDTO = { +export type WebhookURLResponseDTO = { /** - * Comma-separated list of connected account IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/connections` endpoint. + * Status of the operation (success/error). */ - connectedAccountIds?: string; + status: string; /** - * Comma-separated list of integration IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/integrations` endpoint. + * The currently configured webhook callback URL. */ - integrationIds?: string; + callbackURL?: string; +}; + +/** + * Detailed information about a trigger + */ +export type TriggerMetadataDTO = { /** - * Comma-separated list of trigger IDs to filter triggers by. You can get these IDs from the `id` field in the response of the `GET /api/v1/triggers` endpoint. + * Unique identifier of the trigger. */ - triggerIds?: string; + id: string; /** - * Comma-separated list of trigger names to filter triggers by. You can get these names from the `name` field in the response of the `GET /api/v1/triggers` endpoint. + * ID of the connection this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. */ - triggerNames?: string; + connectionId: string; /** - * Page number for pagination. Starts from 1. + * Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint. */ - page?: number; + triggerName: string; /** - * Number of items to return per page. + * Additional data associated with the trigger. */ - limit?: number; + triggerData: string; /** - * When set to true, includes disabled triggers in the response. + * Configuration parameters for the trigger. Structure varies based on trigger type. */ - showDisabled?: boolean; + triggerConfig: { + [key: string]: unknown; + }; + /** + * Current state of the trigger. + */ + state: { + [key: string]: unknown; + }; + /** + * ISO 8601 timestamp when the trigger was created. + */ + createdAt: string; + /** + * ISO 8601 timestamp when the trigger was last updated. + */ + updatedAt: string; + /** + * ISO 8601 timestamp when the trigger was disabled, if applicable. + */ + disabledAt?: string | null; + /** + * Reason why the trigger was disabled, if applicable. + */ + disabledReason?: string | null; }; -export type GetLogsQueryDTO = { +export type GetTriggerResponseDTO = { /** - * Filter logs by connection ID. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. + * Status of the operation (success/error). */ - connectionId?: string; + status: string; + trigger?: TriggerMetadataDTO; +}; + +export type WehbookNewFormatDTO = { /** - * Filter logs by integration ID. You can get this from the `id` field in the response of the `GET /api/v1/integrations` endpoint. + * Unique identifier of the project. */ - integrationId?: string; + id: string; /** - * Page number for pagination. Starts from 1. + * Indicates whether this is a newly created webhook. */ - page?: number; + isNewWebhook: boolean; +}; + +export type TriggerNotFoundError = { /** - * Number of items to return per page. + * The name of the error */ - limit?: number; + name: "TriggerNotFoundError"; + /** + * HTTP status code + */ + status: number; + /** + * Error message + */ + message: string; + /** + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. + */ + requestId: string; + /** + * The name of the operation that caused the error + */ + type: "NotFoundError"; }; -export type TriggerResDTO = { +/** + * The name of the error + */ +export type name10 = "TriggerNotFoundError"; + +export type InvalidTriggerConfigError = { /** - * Unique identifier of the trigger. This is used to reference the trigger in other API calls. + * The name of the error */ - name: string; + name: "InvalidTriggerConfigError"; /** - * Human-readable name of the trigger shown in the UI. + * HTTP status code */ - display_name: string; + status: number; /** - * Detailed description of what the trigger does. + * Error message */ - description?: string; + message: string; /** - * Indicates whether the trigger is currently enabled. + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. */ - enabled?: boolean; + requestId: string; /** - * Configuration parameters required for the trigger. Structure varies based on trigger type. + * Additional arguments that caused the error */ - config?: { + details: { [key: string]: unknown; }; /** - * Sample payload that will be sent when the trigger fires. + * The type of error */ - payload?: { + type: "BadRequestError"; +}; + +/** + * The name of the error + */ +export type name11 = "InvalidTriggerConfigError"; + +export type ToolsExecuteReqDto = { + actionName: string; + runInSandbox: boolean; + input: { [key: string]: unknown; }; + nlaInput?: string; + authorizationData?: { + [key: string]: unknown; + }; + appSchema?: { + [key: string]: unknown; + }; + customDescription?: string; + systemPrompt?: string; + version?: string; +}; + +export type DirectExecuteReqDto = { + endpoint: string; + base_url: string; + headers: { + [key: string]: unknown; + }; + queryParams: { + [key: string]: unknown; + }; + body?: { + [key: string]: unknown; + }; +}; + +export type ActionExecutionResDto = { /** - * URL of the trigger's icon or logo. - */ - logo?: string; - /** - * Number of times this trigger has been activated. + * The response data returned by the action execution. */ - count?: number; + data: { + [key: string]: unknown; + }; /** - * Unique key identifying the app this trigger belongs to. + * The error message, if the action failed to execute. If the action is successful, this will be null. */ - appKey: string; + error?: string; /** - * Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint. + * Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message. + * @deprecated */ - appId: string; + successfull?: boolean; /** - * Name of the app this trigger belongs to. + * Whether the action execution was successfully executed or not. If this is false, error field will be populated with the error message. */ - appName: string; + successful: boolean; +}; + +/** + * Custom authentication credentials to use while executing an action. + */ +export type CustomAuthDTO = { /** - * Step-by-step instructions on how to set up and use this trigger. + * The base URL (root address) what you should use while making http requests to the connected account. For example, for gmail, it would be 'https://gmail.googleapis.com' */ - instructions?: string; + base_url?: string; + parameters: Array; /** - * Classification or category of the trigger. + * The body to be sent to the endpoint for authentication. This can either be a JSON field or a string. Note: This is very rarely neeed and is only required by very few apps. */ - type?: string; + body?: { + [key: string]: unknown; + }; }; -export type SingleTriggerResDTO = { - /** - * Unique identifier of the trigger. Used to reference the trigger in other API calls. - */ - name: string; +export type ActionProxyRequestMethodDTO = { /** - * Human-readable name of the trigger shown in the UI. + * The type of request body to use for the action. Defaults to 'none'. */ - displayName: string; + type?: "formData" | "urlEncoded" | "raw" | "binary" | "graphql" | "none"; /** - * Detailed description of what the trigger does and when it fires. + * The data to be sent to the endpoint. This will override the body set in the connected account. */ - description: string; + data?: string; +}; + +/** + * The type of request body to use for the action. Defaults to 'none'. + */ +export type type4 = + | "formData" + | "urlEncoded" + | "raw" + | "binary" + | "graphql" + | "none"; + +export type GetSingleActionReqDTO = { /** - * Classification or category of the trigger. + * The id of the action to get details for. This can be found in the id field in [/api/v2/actions](/api-reference/actions/list-actions) endpoint. */ - type: string; + actionId: string; +}; + +export type GetSingleActionQueryDTO = { /** - * Unique identifier of the app this trigger belongs to. You can get this from the `id` field in the response of the `GET /api/v1/apps` endpoint. + * Version for the action */ - appId: string; + version?: string; +}; + +export type ActionProxyRequestConfigDTO = { /** - * Name of the app this trigger belongs to. + * The connected account uuid to use for the action. */ - appName: string; + connectedAccountId: string; /** - * Step-by-step instructions on how to set up and use this trigger. + * The endpoint to call for the action. If the given url is relative, it will be resolved relative to the base_url set in the connected account info. */ - instructions?: string; + endpoint: string; /** - * Sample payload that will be sent when the trigger fires. + * The HTTP method to use for the action. */ - payload: { - [key: string]: unknown; - }; + method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; + parameters: Array; /** - * Configuration parameters required for the trigger. Structure varies based on trigger type. + * The body to be sent to the endpoint. This can either be a JSON field or a string. */ - config: { + body?: { [key: string]: unknown; }; }; /** - * Configuration parameters for a trigger + * The HTTP method to use for the action. */ -export type TriggerConfig = { +export type method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; + +/** + * Used internally by our SDK's to keep track of the source of execution, ignore it. + */ +export type SessionInfoDTO = { + sessionId?: string; + metadata?: { + [key: string]: unknown; + }; +}; + +export type NLAArgumentsResponseDTO = { /** - * Name of the repository to monitor. + * The arguments for the action needed to execute the given task. */ - repo: string; + arguments?: { + [key: string]: unknown; + }; /** - * Owner (user or organization) of the repository. + * The error message if the arguments were not generated successfully. */ - owner: string; + error?: string; }; -export type ActiveTriggerInstance = { +export type ActionExecutionReqDTO = { /** - * Unique identifier of the trigger instance. + * Connected account uuid for the account you want to run the action on. You can get this from the id field in [/api/v1/connectedAccounts](/api-reference/connections/list-connections) endpoint. */ - id?: string; + connectedAccountId?: string; /** - * ID of the connected account this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. + * The name/id of the app that the action belongs to. To get the app name, you can use the [/api/v1/apps](/api-reference/apps/list-apps) endpoint. + */ + appName?: string; + /** + * (Optional) EntityId that represents your users connections - if the required connection is availabe for the user, it'll be auto-picked. If you are passing this, there's no need to pass `connectedAccountId`. To know more about entityId, [click here](https://backend.composio.dev/patterns/Auth/connected_account#entities) */ - connectionId: string; + entityId?: string; /** - * Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint. + * Action inputs or aguments to execute the action. This is a dict/map with key-value structure, depdning on the action schema you can find in [/api/v2/actions/{actionName}](/api-reference/actions/get-single-action) endpoint. */ - triggerName: string; + input?: { + [key: string]: unknown; + }; + sessionInfo?: SessionInfoDTO; + authConfig?: CustomAuthDTO; /** - * Additional data associated with the trigger instance. + * The use-case description for the action, this will give context to LLM to generate the correct inputs for the action. */ - triggerData?: string; - triggerConfig: TriggerConfig; + text?: string; /** - * ISO 8601 timestamp when the trigger instance was created. + * The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case. */ - createdAt: string; + customDescription?: string; /** - * ISO 8601 timestamp when the trigger instance was last updated. + * The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM. */ - updatedAt: string; + systemPrompt?: string; /** - * ISO 8601 timestamp when the trigger instance was disabled, if applicable. + * Version of the action you want to execute. */ - disabledAt?: string | null; + version?: string; }; -export type PageInfoDTO = { +export type ActionGetNLAInputsReqDTO = { /** - * Current page number. + * The use-case description for the action, this will give context to LLM to generate the correct inputs for the action. */ - currentPage: number; + text: string; /** - * Number of items per page. + * The custom description for the action, use this to provide customised context about the action to the LLM to suit your use-case. */ - perPage: number; + customDescription?: string; /** - * Total number of pages available. + * The system prompt to be used by LLM, use this to control and guide the behaviour of the LLM. */ - totalPages: number; + systemPrompt?: string; }; -export type ActiveTriggersResDTO = { - /** - * List of active trigger instances. - */ - triggers: Array<{ - [key: string]: unknown; - }>; - /** - * Pagination information for the response. - */ - pageInfo: Array; +export type ProxyExecutionReqDTO = { + endpoint: string; + connectedAccountId: string; }; -export type TriggerLogsResDTO = { - /** - * List of trigger log entries. - */ - data: Array; +export type ActionNotFoundError = { /** - * Pagination information for the response. + * The error name */ - pageInfo: PageInfoDTO; -}; - -export type TriggerLogItemDTO = { + name: "ActionNotFoundError"; /** - * Unique identifier of the client that initiated the trigger. + * HTTP status code */ - clientId: string; + status: number; /** - * ID of the connection associated with this log entry. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. + * Error message */ - connectionId: string; + message: string; /** - * Error message if the trigger failed. + * Request ID, used for tracing the request. This is very helpful for internal teams to debug issues. */ - errorTrigger?: string | null; + requestId: string; /** - * Client-side error message if any occurred. + * The name of the operation that caused the error */ - triggerClientError?: string | null; + type: "NotFoundError"; +}; + +/** + * The error name + */ +export type name12 = "ActionNotFoundError"; + +export type ActionDetailsMinimal = { /** - * Payload sent by the client when the trigger was activated. + * The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description. */ - triggerClientPayload?: string | null; + description: string; /** - * Payload received from the provider's API. + * The display name of the action, used to identify the action in the UI. */ - triggerProviderPayload?: string | null; + displayName: string; /** - * Name of the trigger that generated this log entry. + * The logo of the app that the action belongs to. */ - triggerName?: string | null; + logo: string; /** - * Unique identifier for this log entry. + * The name of the action, used to identify the action in the UI. */ - id: string; + name: string; /** - * Key identifying the app associated with this log entry. + * The tags of the action, used to categorize the action in the UI. */ - appKey: string; + tags: Array; /** - * ISO 8601 timestamp when this log entry was created. + * Whether the action is deprecated, if true, avoid using this action. */ - createdAt: string; + deprecated?: boolean; }; -export type HandleTriggerParamsDTO = { - /** - * Name of the app handling the trigger. You can get this from the `name` field in the response of the `GET /api/v1/apps` endpoint. - */ - appName: string; +export type ActionsTagQueryReqDTO = { /** - * Unique identifier of the client initiating the trigger. + * Comma separated list of app names to filter the action tags by. */ - clientId: string; + apps?: string; }; -export type HandleTriggerBodyDTO = { +export type ActionDetails = { /** - * Payload data to be processed by the trigger. + * Required parameters for the action to execute. For example, if the action is GMAIL_SEND_EMAIL, the required parameters for actions execution would be the email address, subject, and body. */ - body: { + parameters: { [key: string]: unknown; }; -}; - -export type EnableTriggerParamsDTO = { /** - * ID of the connected account to enable the trigger for. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. + * Expected response structure after action execution. You can use this to quickly check what happened with the action execution. */ - connectedAccountId: string; + response: { + [key: string]: unknown; + }; /** - * Name of the trigger to enable. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint. + * The name of the app that the action belongs to. This is same as appId. */ - triggerName: string; -}; - -export type GetTriggerParamsDTO = { + appKey: string; /** - * Unique identifier of the trigger to retrieve. You can get this from the `id` field in the response of the `GET /api/v1/triggers` endpoint. + * The name of the app that the action belongs to, */ - triggerId: string; -}; - -export type EnableTriggerBodyDTO = { + appName: string; /** - * Configuration parameters for the trigger. Structure varies based on trigger type. + * The id of the app that the action belongs to. This is same as the appKey. Please use appKey instead. + * @deprecated */ - triggerConfig: { - [key: string]: unknown; - }; + appId: string; /** - * Host URL for webhook verification, if required. + * Version of the action schema. */ - verifyHost?: string; -}; - -export type SwitchTriggerStatusParamsDTO = { + version: string; /** - * Unique identifier of the trigger instance to update. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint. + * List of availavle versions of the action. */ - triggerId: string; -}; - -export type SwitchTriggerStatusBodyDTO = { + available_versions: Array<{ + [key: string]: unknown; + }>; /** - * New enabled/disabled state for the trigger. + * Whether or not the action requires auth or not */ - enabled: boolean; -}; - -export type TriggerInstanceParamsDTO = { + no_auth: boolean; /** - * Unique identifier of the trigger instance to modify. You can get this from the `id` field in the response of the `GET /api/v1/triggers/active` endpoint. + * The description of the action, tailored to improve the LLM accuracy and reasoning. Use this a tool/function description. */ - triggerInstanceId: string; -}; - -export type SetCallbackUrlBodyDTO = { + description: string; /** - * URL where webhook notifications should be sent when the trigger fires. + * The display name of the action, used to identify the action in the UI. */ - callbackURL: string; -}; - -export type TriggerResponseDTO = { + displayName: string; /** - * Status of the operation (success/error). + * The logo of the app that the action belongs to. */ - status: string; + logo: string; /** - * Additional information about the operation result. + * The name of the action, used to identify the action in the UI. */ - message?: string; + name: string; /** - * Unique identifier of the affected trigger. + * The tags of the action, used to categorize the action in the UI. */ - triggerId?: string; + tags: Array; /** - * Indicates whether a new trigger was created (true) or an existing one was modified (false). + * Whether the action is deprecated, if true, avoid using this action. */ - isNew?: boolean; + deprecated?: boolean; }; -export type WebhookURLResponseDTO = { - /** - * Status of the operation (success/error). - */ - status: string; +export type ActionsTagsResponseDTO = { /** - * The currently configured webhook callback URL. + * List of all the action tags available in composio */ - callbackURL?: string; + items: Array; }; -/** - * Detailed information about a trigger - */ -export type TriggerMetadataDTO = { - /** - * Unique identifier of the trigger. - */ - id: string; +export type ActionsListResponseDTO = { + items: Array; /** - * ID of the connection this trigger is associated with. You can get this from the `id` field in the response of the `GET /api/v1/connections` endpoint. + * Current page number in the paginated response */ - connectionId: string; + page: number; /** - * Name of the trigger. You can get this from the `name` field in the response of the `GET /api/v1/triggers` endpoint. + * Total number of pages available */ - triggerName: string; + totalPages: number; +}; + +export type ActionsMinimalListResponseDTO = { + items: Array; + page: number; + totalPages: number; +}; + +export type AdvancedUseCaseSearchBodyDTO = { + useCase?: string; +}; + +export type AdvancedUseCaseSearchQueryDTO = { /** - * Additional data associated with the trigger. + * Use case is deprecated. Please provide this in the body instead to avoid max-uri-length error. + * @deprecated */ - triggerData: string; + useCase?: string; + limit?: number; + maxActionsPerTask?: number; + minActionsPerTask?: number; + apps?: string; + filterByAvailableApps?: boolean; +}; + +export type AdvancedUseCaseSearchTask = { + app: string; + actions: Array; + description: string; + order: number; +}; + +export type AdvancedUseCaseSearchResponse = { + items: Array; +}; + +export type ExecuteActionResDTO = { /** - * Configuration parameters for the trigger. Structure varies based on trigger type. + * Indicates if the action was executed successfully */ - triggerConfig: { - [key: string]: unknown; - }; + response_data: boolean; /** - * Current state of the trigger. + * Details of the execution status */ - state: { + execution_details: { [key: string]: unknown; }; +}; + +export type ActionsQueryDTO = { /** - * ISO 8601 timestamp when the trigger was created. + * Names of the apps */ - createdAt: string; + appNames?: string; /** - * ISO 8601 timestamp when the trigger was last updated. + * Use case */ - updatedAt: string; + useCase?: string; /** - * ISO 8601 timestamp when the trigger was disabled, if applicable. + * Show enabled only */ - disabledAt?: string | null; + showEnabledOnly?: boolean; /** - * Reason why the trigger was disabled, if applicable. + * Limit */ - disabledReason?: string | null; + limit?: number; + apps?: string; + actions?: string; + tags?: string; + usecaseLimit?: number; + filterImportantActions?: boolean; + showAll?: boolean; + page?: number; }; -export type GetTriggerResponseDTO = { - /** - * Status of the operation (success/error). - */ - status: string; - trigger?: TriggerMetadataDTO; +export type ActionsControllerV1 = { + getAction: Array<{ + [key: string]: unknown; + }>; }; -export type WehbookNewFormatDTO = { - /** - * Unique identifier of the project. - */ - id: string; - /** - * Indicates whether this is a newly created webhook. - */ - isNewWebhook: boolean; +export type OAuth2CallbackQueryDto = { + state: string; +}; + +export type RedirectUriDTO = { + redirectUri?: string; }; export type ReadOnlyQueryReqDTO = { @@ -2848,61 +3122,57 @@ export type LogsResDTO = { export type GetLogsDTO = { /** - * Type of the log - */ - type?: "error" | "info" | "debug"; - /** - * Time interval for which data needs to be fetched + * Return logs from the last N time units */ time?: "5m" | "30m" | "6h" | "1d" | "1w" | "1month" | "1y"; /** - * Status of the log + * Filter logs by their status level, defaults to all */ status?: "all" | "success" | "error"; /** - * Search term in the log + * Search term to filter logs by */ search?: string; /** - * Integration UUID + * The ID/UUID of the integration to filter connections by. You can get the integration ID from the [/api/v1/integrations](/api-reference/integrations/list-integrations) endpoint. */ integrationId?: string; /** - * Entity id + * Filter logs by entity Id, useful for debugging issues for your specific users. Learn more about entityId [here](https://docs.composio.dev/patterns/Auth/connected_account) */ entityId?: string; /** - * Limit of the logs + * Maximum number of logs to return, defaults to 10 */ limit?: number; /** - * Cursor for pagination + * Cursor for pagination, used to fetch next set of logs. You can get the cursor from the previous response of this endpoint. */ cursor?: string; /** * Type of the log */ - logsType?: string; + logsType?: "action" | "trigger"; /** - * Session ID of the log + * Session ID of the log, used to filter logs by session. Helpful in debugging issues with specific logs. */ sessionId?: string; }; /** - * Type of the log + * Return logs from the last N time units */ -export type type5 = "error" | "info" | "debug"; +export type time = "5m" | "30m" | "6h" | "1d" | "1w" | "1month" | "1y"; /** - * Time interval for which data needs to be fetched + * Filter logs by their status level, defaults to all */ -export type time = "5m" | "30m" | "6h" | "1d" | "1w" | "1month" | "1y"; +export type status4 = "all" | "success" | "error"; /** - * Status of the log + * Type of the log */ -export type status4 = "all" | "success" | "error"; +export type logsType = "action" | "trigger"; export type IngestDataDTO = { /** @@ -2971,6 +3241,10 @@ export type ActionsQueryV2DTO = { * Filter and return only important actions. This is equivalent to setting tags='important' in the query params mentioned above. */ filterImportantActions?: boolean; + /** + * Sort the actions by usage or alphabetical + */ + sortBy?: "alphabet" | "usage" | "no_sort"; }; export type TimePeriodReqDTO = { @@ -3218,6 +3492,243 @@ export type UpdateRowAPIDTO = { count: number; }; +export type AppFilterDTO = { + /** + * List of app unique keys to filter by + */ + uniqueKey?: string; + /** + * List of app unique keys to filter by + */ + integrationId?: string; +}; + +export type ComposioSearchConfigDTO = { + /** + * Whether to use Composio authentication + */ + useComposioAuth?: boolean; + /** + * Authentication scheme to use + */ + authScheme: + | "OAUTH2" + | "OAUTH1" + | "OAUTH1A" + | "API_KEY" + | "BASIC" + | "BEARER_TOKEN" + | "GOOGLE_SERVICE_ACCOUNT" + | "NO_AUTH" + | "BASIC_WITH_JWT" + | "COMPOSIO_LINK" + | "CALCOM_AUTH"; +}; + +/** + * Authentication scheme to use + */ +export type authScheme = + | "OAUTH2" + | "OAUTH1" + | "OAUTH1A" + | "API_KEY" + | "BASIC" + | "BEARER_TOKEN" + | "GOOGLE_SERVICE_ACCOUNT" + | "NO_AUTH" + | "BASIC_WITH_JWT" + | "COMPOSIO_LINK" + | "CALCOM_AUTH"; + +export type ConnectorSearchFilterDTOV2 = { + /** + * Filter options for the connector + */ + app: AppFilterDTO; + /** + * Filter options for the connector + */ + config: ComposioSearchConfigDTO; +}; + +export type ConnectorSearchResDTO = { + /** + * List of matched integration ids + */ + matchedIntegrationIds: Array; + /** + * App info + */ + appInfo: { + [key: string]: unknown; + }; +}; + +export type AppInfoPayload = { + /** + * List of app unique keys to filter by + */ + uniqueKey?: string; +}; + +export type ComposioCreateConfigDTO = { + /** + * Name of the integration + */ + name?: string; + /** + * Whether to use Composio authentication + */ + useComposioAuth?: boolean; + /** + * Authentication scheme to use + */ + authScheme: + | "OAUTH2" + | "OAUTH1" + | "OAUTH1A" + | "API_KEY" + | "BASIC" + | "BEARER_TOKEN" + | "GOOGLE_SERVICE_ACCOUNT" + | "NO_AUTH" + | "BASIC_WITH_JWT" + | "COMPOSIO_LINK" + | "CALCOM_AUTH"; + /** + * Authentication configuration + */ + integrationSecrets?: { + [key: string]: unknown; + }; +}; + +export type ConnectorCreateReqDTO = { + /** + * Filter options for the connector + */ + app: AppInfoPayload; + /** + * Filter options for the connector + */ + config: ComposioCreateConfigDTO; +}; + +export type CreateConnectorResDTO = { + /** + * List of matched integration IDs + */ + integrationId: string; +}; + +export type GetOrCreateConnectorInfo = { + /** + * Filter options for the connector + */ + app: AppFilterDTO; + /** + * Filter options for the connector + */ + config: ComposioCreateConfigDTO; +}; + +export type GetOrCreateConnectorResDTOV2 = { + /** + * Matched integration ID + */ + integrationId: string; + /** + * Whether a new integration was created + */ + isNewIntegration?: boolean; +}; + +export type ConnectionExtraData = { + /** + * The URL to redirect to after the connection is successfully initiated. + */ + redirectURL?: string; + /** + * Array of labels to associate with the connection for organization and filtering. + */ + labels?: Array; +}; + +export type ConnectionInitData = { + /** + * Data required to initiate the connection. The structure varies based on the integration type. + */ + initiateData: { + [key: string]: unknown; + }; + /** + * The entity ID to associate with the connection. Learn more about entities [here](https://docs.composio.dev/patterns/Auth/connected_account#entities). + */ + entityId?: string; + /** + * The URL to redirect to after the connection is successfully initiated. + */ + extra?: ConnectionExtraData; +}; + +export type InitiateConnectionPayloadDtoV2 = { + /** + * Filter criteria to identify the app for which to create a connection. + */ + app: AppFilterDTO; + /** + * Configuration options for the connection, including authentication scheme and settings. + */ + config: ComposioCreateConfigDTO; + /** + * Additional metadata and configuration options for the connection. + */ + connection: ConnectionInitData; +}; + +export type IntegrationData = { + /** + * Unique identifier of the integration used for this connection. + */ + id: string; + /** + * Indicates whether a new integration was created during this connection process. + */ + isNewIntegration: boolean; +}; + +export type ConnectionResponseV2 = { + /** + * The URL to redirect to after the connection is successfully initiated. + */ + redirectUrl?: string; + /** + * The current status of the connection. + */ + connectionStatus: "INITIATED" | "ACTIVE" | "FAILED" | "EXPIRED"; + /** + * The unique identifier of the connected account. + */ + connectedAccountId: string; +}; + +/** + * The current status of the connection. + */ +export type connectionStatus = "INITIATED" | "ACTIVE" | "FAILED" | "EXPIRED"; + +export type InitiateConnectionResponseV2 = { + /** + * Details about the integration associated with this connection. + */ + integration: IntegrationData; + /** + * Response data containing connection details and status. + */ + connectionResponse: ConnectionResponseV2; +}; + export type GetUserInfoResponse = ClientInfoResDTO; export type GetUserInfoError = unknown; @@ -3308,6 +3819,7 @@ export type GetAppsData = { additionalFields?: string; category?: string; includeLocal?: "true" | "false"; + sortBy?: "alphabet" | "usage" | "no_sort"; }; }; @@ -3419,6 +3931,7 @@ export type ListActionsMinimalV2Data = { filterImportantActions?: boolean; limit?: number; page?: number; + sortBy?: "alphabet" | "usage" | "no_sort"; tags?: string; useCase?: string; }; @@ -3460,6 +3973,9 @@ export type GetActionV2Data = { path: { actionId: string; }; + query?: { + version?: string; + }; }; export type GetActionV2Response = ActionDetails; @@ -3507,7 +4023,7 @@ export type ListConnectionsData = { pageSize?: number; showActiveOnly?: boolean; showDisabled?: boolean; - status?: "INITIATED" | "ACTIVE" | "FAILED"; + status?: string; user_uuid?: string; }; }; @@ -3541,6 +4057,20 @@ export type UpdateConnectionDataResponse = unknown; export type UpdateConnectionDataError = unknown; +export type ReinitiateConnectionData = { + /** + * ReinitiateConnectionPayloadDto + */ + body?: ReinitiateConnectionPayloadDto; + path: { + connectedAccountId: string; + }; +}; + +export type ReinitiateConnectionResponse = InitiateConnectionResponse; + +export type ReinitiateConnectionError = ConnectedAccountNotFoundError; + export type GetConnectionData = { path: { connectedAccountId: string; @@ -3598,6 +4128,7 @@ export type ListTriggersData = { integrationIds?: string; showEnabledOnly?: boolean; triggerIds?: string; + triggerNames?: string; }; }; @@ -3755,12 +4286,11 @@ export type GetLogsData = { entityId?: string; integrationId?: string; limit?: number; - logsType?: string; + logsType?: "action" | "trigger"; search?: string; sessionId?: string; status?: "all" | "success" | "error"; time?: "5m" | "30m" | "6h" | "1d" | "1w" | "1month" | "1y"; - type?: "error" | "info" | "debug"; }; }; @@ -3826,3 +4356,47 @@ export type RenameProjectData = { export type RenameProjectResponse = UpdateRowAPIDTO; export type RenameProjectError = unknown; + +export type SearchConnectorData = { + /** + * ConnectorSearchFilterDTOV2 + */ + body?: ConnectorSearchFilterDTOV2; +}; + +export type SearchConnectorResponse = ConnectorSearchResDTO; + +export type SearchConnectorError = unknown; + +export type CreateConnectorV2Data = { + /** + * ConnectorCreateReqDTO + */ + body?: ConnectorCreateReqDTO; +}; + +export type CreateConnectorV2Response = CreateConnectorResDTO; + +export type CreateConnectorV2Error = unknown; + +export type GetOrCreateConnectorData = { + /** + * GetOrCreateConnectorInfo + */ + body?: GetOrCreateConnectorInfo; +}; + +export type GetOrCreateConnectorResponse = GetOrCreateConnectorResDTOV2; + +export type GetOrCreateConnectorError = unknown; + +export type InitiateConnectionV2Data = { + /** + * InitiateConnectionPayloadDtoV2 + */ + body?: InitiateConnectionPayloadDtoV2; +}; + +export type InitiateConnectionV2Response = InitiateConnectionResponseV2; + +export type InitiateConnectionV2Error = BadRequestError | NotFoundError; diff --git a/js/src/sdk/index.ts b/js/src/sdk/index.ts index 7d76685f6b3..f70bfa5b13e 100644 --- a/js/src/sdk/index.ts +++ b/js/src/sdk/index.ts @@ -125,9 +125,12 @@ export class Composio { ); const latestVersion = response.data.version; - if (isNewerVersion(latestVersion, currentVersionFromPackageJson)) { + if ( + isNewerVersion(latestVersion, currentVersionFromPackageJson) && + !IS_DEVELOPMENT_OR_CI + ) { // eslint-disable-next-line no-console - console.warn( + logger.info( `🚀 Upgrade available! Your composio-core version (${currentVersionFromPackageJson}) is behind. Latest version: ${latestVersion}.` ); } diff --git a/js/src/sdk/models/Entity.spec.ts b/js/src/sdk/models/Entity.spec.ts index c3839744686..0ee309730f2 100644 --- a/js/src/sdk/models/Entity.spec.ts +++ b/js/src/sdk/models/Entity.spec.ts @@ -25,7 +25,9 @@ describe("Entity class tests", () => { it("should create for different entities", async () => { const entityId = "test-entity"; const entity2 = new Entity(backendClient, entityId); - const connection = await entity2.initiateConnection({ appName: "github" }); + const connection = await entity2.initiateConnection({ + appName: "github", + }); expect(connection.connectionStatus).toBe("INITIATED"); const connection2 = await connectedAccounts.get({ @@ -109,7 +111,10 @@ describe("Entity class tests", () => { }); it("initiate connection", async () => { - const connection = await entity.initiateConnection({ appName: "github" }); + const connection = await entity.initiateConnection({ + appName: "github", + authMode: "OAUTH2", + }); expect(connection.connectionStatus).toBe("INITIATED"); }); }); diff --git a/js/src/sdk/models/connectedAccounts.ts b/js/src/sdk/models/connectedAccounts.ts index 9dced15d1d3..d3ce30b5915 100644 --- a/js/src/sdk/models/connectedAccounts.ts +++ b/js/src/sdk/models/connectedAccounts.ts @@ -1,28 +1,24 @@ import { z } from "zod"; -import logger from "../../utils/logger"; import { ConnectedAccountResponseDTO, ConnectionParams, DeleteRowAPIDTO, GetConnectionsResponseDto, - GetConnectorInfoResDTO, } from "../client"; -import { default as apiClient, default as client } from "../client/client"; +import { default as apiClient } from "../client/client"; import { ZInitiateConnectionDataReq, ZInitiateConnectionPayloadDto, ZListConnectionsData, + ZReinitiateConnectionPayloadDto, ZSaveUserAccessDataParam, ZSingleConnectionParams, } from "../types/connectedAccount"; import { ZAuthMode } from "../types/integration"; import { CEG } from "../utils/error"; -import { COMPOSIO_SDK_ERROR_CODES } from "../utils/errors/src/constants"; import { TELEMETRY_LOGGER } from "../utils/telemetry"; import { TELEMETRY_EVENTS } from "../utils/telemetry/events"; -import { Apps } from "./apps"; import { BackendClient } from "./backendClient"; -import { Integrations } from "./integrations"; // Schema type from conectedAccount.ts type ConnectedAccountsListData = z.infer; @@ -30,6 +26,9 @@ type InitiateConnectionDataReq = z.infer; type SingleConnectionParam = z.infer; type SaveUserAccessDataParam = z.infer; type InitiateConnectionPayload = z.infer; +type ReinitiateConnectionPayload = z.infer< + typeof ZReinitiateConnectionPayloadDto +>; export type ConnectedAccountListResponse = GetConnectionsResponseDto; export type SingleConnectedAccountResponse = ConnectedAccountResponseDTO; @@ -38,14 +37,10 @@ export type ConnectionItem = ConnectionParams; export class ConnectedAccounts { private backendClient: BackendClient; - private integrations: Integrations; - private apps: Apps; private fileName: string = "js/src/sdk/models/connectedAccounts.ts"; constructor(backendClient: BackendClient) { this.backendClient = backendClient; - this.integrations = new Integrations(this.backendClient); - this.apps = new Apps(this.backendClient); } async list( @@ -150,107 +145,61 @@ export class ConnectedAccounts { params: { payload }, }); try { - const { - authMode, - appName, - entityId, - redirectUri, - labels, - authConfig, - integrationId, - connectionParams, - } = payload; - if (!integrationId && !appName) { - throw CEG.getCustomError( - COMPOSIO_SDK_ERROR_CODES.COMMON.INVALID_PARAMS_PASSED, - { - message: "Please pass appName or integrationId", - description: - "We need atleast one of the params to initiate a connection", - } - ); - } - - /* Get the integration */ - const timestamp = new Date().toISOString().replace(/[-:.]/g, ""); - - const isIntegrationIdPassed = !!integrationId; - let integration = isIntegrationIdPassed - ? await this.integrations.get({ integrationId: integrationId }) - : null; - - if (!integration && !!authMode) { - const integrations = await this.integrations.list({ - appName: appName, - }); - integration = integrations.items?.find((integration) => { - return integration.authScheme === authMode; - }) as GetConnectorInfoResDTO; - } - - if (isIntegrationIdPassed && !integration) { - throw CEG.getCustomError( - COMPOSIO_SDK_ERROR_CODES.COMMON.INVALID_PARAMS_PASSED, - { - message: "Integration not found", - description: "The integration with the given id does not exist", - } - ); - } - - /* If integration is not found, create a new integration */ - if (!isIntegrationIdPassed) { - const app = await this.apps.get({ appKey: appName! }); - - if (!!authMode && !!authConfig) { - integration = await this.integrations.create({ - appId: app.appId!, - name: `integration_${timestamp}`, - authScheme: authMode as z.infer, - authConfig: authConfig, - useComposioAuth: false, - }); - } else { - const isTestConnectorAvailable = - app.testConnectors && app.testConnectors.length > 0; + const connection = await apiClient.connectionsV2.initiateConnectionV2({ + body: { + app: { + uniqueKey: payload.appName!, + integrationId: payload.integrationId, + }, + config: { + name: payload.appName!, + useComposioAuth: !!payload.authMode && !!payload.authConfig, + authScheme: payload.authMode as z.infer, + integrationSecrets: payload.authConfig, + }, + connection: { + entityId: payload.entityId, + initiateData: + (payload.connectionParams as Record) || {}, + extra: { + redirectURL: payload.redirectUri, + labels: payload.labels || [], + }, + }, + }, + }); - if (!isTestConnectorAvailable && app.no_auth === false) { - logger.debug( - "Auth schemes not provided, available auth schemes and authConfig" - ); - // @ts-ignore - for (const authScheme of app.auth_schemes) { - logger.debug( - "authScheme:", - authScheme.name, - "\n", - "fields:", - authScheme.fields - ); - } + const connectionResponse = connection?.data?.connectionResponse; - throw new Error("Please pass authMode and authConfig."); - } + return new ConnectionRequest({ + connectionStatus: connectionResponse?.connectionStatus!, + connectedAccountId: connectionResponse?.connectedAccountId!, + redirectUri: connectionResponse?.redirectUrl!, + }); + } catch (error) { + throw CEG.handleAllError(error); + } + } - integration = await this.integrations.create({ - appId: app.appId!, - name: `integration_${timestamp}`, - useComposioAuth: true, - }); - } - } + async reinitiateConnection(data: ReinitiateConnectionPayload) { + TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { + method: "reinitiateConnection", + file: this.fileName, + params: { data }, + }); + try { + ZReinitiateConnectionPayloadDto.parse(data); + const connection = await apiClient.connections.reinitiateConnection({ + path: { + connectedAccountId: data.connectedAccountId, + }, + body: { + data: data.data, + redirectUri: data.redirectUri, + }, + }); - const res = await client.connections - .initiateConnection({ - body: { - integrationId: integration?.id!, - entityId: entityId, - labels: labels, - redirectUri: redirectUri, - data: connectionParams || {}, - }, - }) - .then((res) => res.data); + const res = connection.data; return new ConnectionRequest({ connectionStatus: res?.connectionStatus!, diff --git a/js/src/sdk/models/integrations.spec.ts b/js/src/sdk/models/integrations.spec.ts index 95f76e13041..1b35033a7e2 100644 --- a/js/src/sdk/models/integrations.spec.ts +++ b/js/src/sdk/models/integrations.spec.ts @@ -29,8 +29,8 @@ describe("Integrations class tests", () => { const integrationCreation = await integrations.create({ appId: appId, name: "test_integration_220", + authScheme: "OAUTH2", useComposioAuth: true, - forceNewIntegration: true, }); expect(integrationCreation.id).toBeTruthy(); expect(integrationCreation.appName).toBe("github"); diff --git a/js/src/sdk/models/integrations.ts b/js/src/sdk/models/integrations.ts index 8d42a27d52f..ce05a156887 100644 --- a/js/src/sdk/models/integrations.ts +++ b/js/src/sdk/models/integrations.ts @@ -7,6 +7,7 @@ import { } from "../client"; import apiClient from "../client/client"; import { + ZAuthMode, ZCreateIntegrationParams, ZListIntegrationsParams, ZSingleIntegrationParams, @@ -14,6 +15,7 @@ import { import { CEG } from "../utils/error"; import { TELEMETRY_LOGGER } from "../utils/telemetry"; import { TELEMETRY_EVENTS } from "../utils/telemetry/events"; +import { Apps } from "./apps"; import { BackendClient } from "./backendClient"; // Types generated from zod schemas @@ -34,9 +36,11 @@ export type IntegrationDeleteRes = DeleteRowAPIDTO; export class Integrations { private backendClient: BackendClient; private fileName: string = "js/src/sdk/models/integrations.ts"; + private apps: Apps; constructor(backendClient: BackendClient) { this.backendClient = backendClient; + this.apps = new Apps(backendClient); } /** @@ -140,23 +144,65 @@ export class Integrations { params: { data }, }); try { - if (!data?.authConfig) { - data!.authConfig = {}; - } ZCreateIntegrationParams.parse(data); - const response = await apiClient.appConnector.createConnector({ + const apps = await apiClient.apps.getApps(); + const app = apps.data?.items.find((app) => app.appId === data.appId); + + const response = await apiClient.appConnectorV2.createConnectorV2({ body: { - name: data?.name!, - appId: data?.appId!, - authConfig: data?.authConfig! as Record, - authScheme: data?.authScheme, - useComposioAuth: data?.useComposioAuth!, - forceNewIntegration: true, + app: { + uniqueKey: app!.key || "", + }, + config: { + useComposioAuth: data.useComposioAuth, + name: data.name, + authScheme: data.authScheme as z.infer, + integrationSecrets: data.authConfig, + }, }, throwOnError: true, }); - return response.data; + + const integrationId = response.data.integrationId; + return this.get({ integrationId }); + } catch (error) { + throw CEG.handleAllError(error); + } + } + + async getOrCreateIntegration( + data: IntegrationCreateParams + ): Promise { + TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { + method: "getOrCreateIntegration", + file: this.fileName, + params: { data }, + }); + + try { + ZCreateIntegrationParams.parse(data); + + const apps = await apiClient.apps.getApps(); + const app = apps.data?.items.find((app) => app.appId === data.appId); + + const response = await apiClient.appConnectorV2.getOrCreateConnector({ + body: { + app: { + uniqueKey: app!.key, + }, + config: { + useComposioAuth: data.useComposioAuth, + name: data.name, + authScheme: data.authScheme as z.infer, + integrationSecrets: data.authConfig, + }, + }, + throwOnError: true, + }); + + const integrationId = response.data.integrationId; + return this.get({ integrationId }); } catch (error) { throw CEG.handleAllError(error); } diff --git a/js/src/sdk/types/connectedAccount.ts b/js/src/sdk/types/connectedAccount.ts index e53ac64f438..5ada388db17 100644 --- a/js/src/sdk/types/connectedAccount.ts +++ b/js/src/sdk/types/connectedAccount.ts @@ -20,7 +20,7 @@ export const ZListConnectionsData = z.object({ export const ZInitiateConnectionDataReq = z.object({ connectionParams: z.record(z.string(), z.unknown()).optional(), entityId: z.string().optional(), - labels: z.string().array().optional(), + labels: z.array(z.string()).optional(), integrationId: z.string().optional(), redirectUri: z.string().optional(), authMode: ZAuthMode.optional(), @@ -50,3 +50,9 @@ export const ZInitiateConnectionPayloadDto = z.object({ entityId: z.string().optional(), labels: z.string().array().optional(), }); + +export const ZReinitiateConnectionPayloadDto = z.object({ + connectedAccountId: z.string(), + data: z.record(z.string(), z.unknown()), + redirectUri: z.string().optional(), +}); diff --git a/js/src/sdk/types/integration.ts b/js/src/sdk/types/integration.ts index 7d7bc36d68e..ac7df5dfacb 100644 --- a/js/src/sdk/types/integration.ts +++ b/js/src/sdk/types/integration.ts @@ -10,6 +10,7 @@ export const ZAuthMode = z.enum([ "GOOGLE_SERVICE_ACCOUNT", "NO_AUTH", "BASIC_WITH_JWT", + "COMPOSIO_LINK", ]); export const ZCreateIntegrationParams = z.object({ From 37c7054910e1afc6a2858ae0b2a38cb8d044ac0f Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Thu, 16 Jan 2025 18:43:46 +0530 Subject: [PATCH 26/34] feat: Added helicone for caching openai response (#1202) --- .github/workflows/examples_js.yml | 1 + .github/workflows/run_examples_js.yml | 8 +- js/examples/lead_outreach_agent/demo.mjs | 40 +- js/examples/lead_outreach_agent/package.json | 2 +- .../lead_outreach_agent/pnpm-lock.yaml | 85 +-- js/examples/portfolio-generator/demo.mjs | 6 +- js/examples/portfolio-generator/package.json | 4 +- .../portfolio-generator/pnpm-lock.yaml | 554 ++---------------- js/examples/reddit-research/demo.mjs | 3 +- js/examples/reddit-research/package.json | 4 +- js/examples/reddit-research/pnpm-lock.yaml | 550 ++--------------- js/examples/utils.mjs | 13 + 12 files changed, 202 insertions(+), 1068 deletions(-) create mode 100644 js/examples/utils.mjs diff --git a/.github/workflows/examples_js.yml b/.github/workflows/examples_js.yml index c8b5c866e90..a06d3cc9e82 100644 --- a/.github/workflows/examples_js.yml +++ b/.github/workflows/examples_js.yml @@ -73,6 +73,7 @@ jobs: LISTENNOTES_API_KEY: ${{secrets.LISTENNOTES_API_KEY}} COMPOSIO_API_KEY: ${{ inputs.api_key || secrets.COMPOSIO_API_KEY_RELEASE }} COMPOSIO_BASE_URL: 'https://backend.composio.dev' + HELICONE_API_KEY: ${{secrets.HELICONE_API_KEY}} run: | pnpm exec jest tests/test_examples.test.js - name: Slack Notification on Failure diff --git a/.github/workflows/run_examples_js.yml b/.github/workflows/run_examples_js.yml index 10cba0489d6..ae48fddedd0 100644 --- a/.github/workflows/run_examples_js.yml +++ b/.github/workflows/run_examples_js.yml @@ -5,18 +5,16 @@ on: workflow_dispatch: pull_request: paths: - - '**/*.js' - - '**/*.ts' + - "js/examples/**" push: branches: - master paths: - - '**/*.js' - - '**/*.ts' + - "js/examples/**" jobs: test-examples: uses: ./.github/workflows/examples_js.yml with: working-directory: ./js - secrets: inherit \ No newline at end of file + secrets: inherit diff --git a/js/examples/lead_outreach_agent/demo.mjs b/js/examples/lead_outreach_agent/demo.mjs index 1b1a0c13dd5..c4d90c29cb9 100644 --- a/js/examples/lead_outreach_agent/demo.mjs +++ b/js/examples/lead_outreach_agent/demo.mjs @@ -1,41 +1,43 @@ import { ChatOpenAI } from "@langchain/openai"; -import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; -import { pull } from "langchain/hub"; -import dotenv from 'dotenv'; import { LangchainToolSet } from "composio-core"; +import dotenv from "dotenv"; +import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents"; +import { pull } from "langchain/hub"; +import { heliconeParams } from "../utils.mjs"; dotenv.config(); - - -const llm = new ChatOpenAI({ - model: "gpt-4-turbo", +const llm = new ChatOpenAI( + { + model: "gpt-3.5-turbo", apiKey: process.env.OPENAI_API_KEY, -}); + }, + // Remove Helicone params if you don't want to use it + heliconeParams +); const toolset = new LangchainToolSet({ - apiKey: process.env.COMPOSIO_API_KEY, + apiKey: process.env.COMPOSIO_API_KEY, }); const tools = await toolset.getTools({ - actions: ["HUBSPOT_LIST_CONTACTS_PAGE", "GMAIL_CREATE_EMAIL_DRAFT"] + actions: ["HUBSPOT_LIST_CONTACTS_PAGE", "GMAIL_CREATE_EMAIL_DRAFT"], }); const prompt = await pull("hwchase17/openai-functions-agent"); - const agent = await createOpenAIFunctionsAgent({ - llm, - tools, - prompt, + llm, + tools, + prompt, }); const agentExecutor = new AgentExecutor({ - agent, - tools, - verbose: false, + agent, + tools, + verbose: false, }); const result = await agentExecutor.invoke({ - input: `Draft an email for each lead in my Hubspot contacts page introducing yourself and asking them if they're interested in integrating AI Agents in their workflow.` + input: `Draft an email for each lead in my Hubspot contacts page introducing yourself and asking them if they're interested in integrating AI Agents in their workflow.`, }); -console.log('🎉Output from agent: ', result.output); +console.log("🎉Output from agent: ", result.output); diff --git a/js/examples/lead_outreach_agent/package.json b/js/examples/lead_outreach_agent/package.json index e643de92a4a..a58ea779a11 100644 --- a/js/examples/lead_outreach_agent/package.json +++ b/js/examples/lead_outreach_agent/package.json @@ -14,7 +14,7 @@ "composio-core": "0.5.3", "dotenv": "^16.4.7", "express": "^4.19.2", - "langchain": "^0.3.5", + "langchain": "^0.3.11", "pusher-js": "8.4.0-rc2" } } diff --git a/js/examples/lead_outreach_agent/pnpm-lock.yaml b/js/examples/lead_outreach_agent/pnpm-lock.yaml index dc344e5a027..9ddeb5d8f42 100644 --- a/js/examples/lead_outreach_agent/pnpm-lock.yaml +++ b/js/examples/lead_outreach_agent/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: composio-core: specifier: 0.5.3 - version: 0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(@langchain/openai@0.1.3)(ai@3.4.33(openai@4.68.4(zod@3.23.8))(react@19.0.0)(sswr@2.1.0(svelte@5.16.0))(svelte@5.16.0)(vue@3.5.13)(zod@3.23.8))(langchain@0.3.5(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)))(openai@4.68.4(zod@3.23.8)) + version: 0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(@langchain/openai@0.1.3)(ai@3.4.33(openai@4.68.4(zod@3.23.8))(react@19.0.0)(sswr@2.1.0(svelte@5.16.0))(svelte@5.16.0)(vue@3.5.13)(zod@3.23.8))(langchain@0.3.11(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)))(openai@4.68.4(zod@3.23.8)) dotenv: specifier: ^16.4.7 version: 16.4.7 @@ -18,8 +18,8 @@ importers: specifier: ^4.19.2 version: 4.21.1 langchain: - specifier: ^0.3.5 - version: 0.3.5(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)) + specifier: ^0.3.11 + version: 0.3.11(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)) pusher-js: specifier: 8.4.0-rc2 version: 8.4.0-rc2 @@ -118,13 +118,13 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/parser@7.26.3': - resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} + '@babel/parser@7.26.5': + resolution: {integrity: sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/types@7.26.3': - resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} + '@babel/types@7.26.5': + resolution: {integrity: sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==} engines: {node: '>=6.9.0'} '@cloudflare/workers-types@4.20241230.0': @@ -527,11 +527,11 @@ packages: escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - esm-env@1.2.1: - resolution: {integrity: sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==} + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} - esrap@1.3.2: - resolution: {integrity: sha512-C4PXusxYhFT98GjLSmb20k9PREuUdporer50dhzGuJu9IJXktbMddVCMLAERl5dAHyAi73GWWCE4FVHGP1794g==} + esrap@1.4.3: + resolution: {integrity: sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==} estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} @@ -677,16 +677,18 @@ packages: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} - langchain@0.3.5: - resolution: {integrity: sha512-Gq0xC45Sq6nszS8kQG9suCrmBsuXH0INMmiF7D2TwPb6mtG35Jiq4grCk9ykpwPsarTHdty3SzUbII/FqiYSSw==} + langchain@0.3.11: + resolution: {integrity: sha512-PgAG4ZLeuSRkKsyf98cmWGdwKv3I1hOFC8a4fr7e+bm7E+F6Fx6xUkgbuC78ff0N/Cjs5BBryZIFMrqoKPqsvg==} engines: {node: '>=18'} peerDependencies: '@langchain/anthropic': '*' '@langchain/aws': '*' + '@langchain/cerebras': '*' '@langchain/cohere': '*' '@langchain/core': '>=0.2.21 <0.4.0' '@langchain/google-genai': '*' '@langchain/google-vertexai': '*' + '@langchain/google-vertexai-web': '*' '@langchain/groq': '*' '@langchain/mistralai': '*' '@langchain/ollama': '*' @@ -700,12 +702,16 @@ packages: optional: true '@langchain/aws': optional: true + '@langchain/cerebras': + optional: true '@langchain/cohere': optional: true '@langchain/google-genai': optional: true '@langchain/google-vertexai': optional: true + '@langchain/google-vertexai-web': + optional: true '@langchain/groq': optional: true '@langchain/mistralai': @@ -731,8 +737,8 @@ packages: openai: optional: true - langsmith@0.2.3: - resolution: {integrity: sha512-SPMYPVqR9kwXZVmJ2PXC61HeBnXIFHrjfjDxQ14H0+n5p4gqjLzgSHIQyxBlFeWQUQzArJxe65Ap+s+Xo1cZog==} + langsmith@0.2.15: + resolution: {integrity: sha512-homtJU41iitqIZVuuLW7iarCzD4f39KcfP9RTBWav9jifhrsDa1Ez89Ejr+4qi72iuBu8Y5xykchsGVgiEZ93w==} peerDependencies: openai: '*' peerDependenciesMeta: @@ -864,8 +870,8 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + postcss@8.5.1: + resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} engines: {node: ^10 || ^12 || >=14} proxy-addr@2.0.7: @@ -1079,6 +1085,11 @@ packages: peerDependencies: zod: ^3.23.3 + zod-to-json-schema@3.24.1: + resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==} + peerDependencies: + zod: ^3.24.1 + zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} @@ -1149,7 +1160,7 @@ snapshots: '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) json-schema: 0.4.0 secure-json-parse: 2.7.0 - zod-to-json-schema: 3.23.5(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) optionalDependencies: zod: 3.23.8 @@ -1172,11 +1183,11 @@ snapshots: '@babel/helper-validator-identifier@7.25.9': {} - '@babel/parser@7.26.3': + '@babel/parser@7.26.5': dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.26.5 - '@babel/types@7.26.3': + '@babel/types@7.26.5': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 @@ -1368,7 +1379,7 @@ snapshots: '@vue/compiler-core@3.5.13': dependencies: - '@babel/parser': 7.26.3 + '@babel/parser': 7.26.5 '@vue/shared': 3.5.13 entities: 4.5.0 estree-walker: 2.0.2 @@ -1381,14 +1392,14 @@ snapshots: '@vue/compiler-sfc@3.5.13': dependencies: - '@babel/parser': 7.26.3 + '@babel/parser': 7.26.5 '@vue/compiler-core': 3.5.13 '@vue/compiler-dom': 3.5.13 '@vue/compiler-ssr': 3.5.13 '@vue/shared': 3.5.13 estree-walker: 2.0.2 magic-string: 0.30.17 - postcss: 8.4.49 + postcss: 8.5.1 source-map-js: 1.2.1 '@vue/compiler-ssr@3.5.13': @@ -1453,7 +1464,7 @@ snapshots: json-schema: 0.4.0 jsondiffpatch: 0.6.0 secure-json-parse: 2.7.0 - zod-to-json-schema: 3.23.5(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) optionalDependencies: openai: 4.68.4(zod@3.23.8) react: 19.0.0 @@ -1556,7 +1567,7 @@ snapshots: commander@12.1.0: {} - composio-core@0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(@langchain/openai@0.1.3)(ai@3.4.33(openai@4.68.4(zod@3.23.8))(react@19.0.0)(sswr@2.1.0(svelte@5.16.0))(svelte@5.16.0)(vue@3.5.13)(zod@3.23.8))(langchain@0.3.5(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)))(openai@4.68.4(zod@3.23.8)): + composio-core@0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(@langchain/openai@0.1.3)(ai@3.4.33(openai@4.68.4(zod@3.23.8))(react@19.0.0)(sswr@2.1.0(svelte@5.16.0))(svelte@5.16.0)(vue@3.5.13)(zod@3.23.8))(langchain@0.3.11(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)))(openai@4.68.4(zod@3.23.8)): dependencies: '@ai-sdk/openai': 0.0.36(zod@3.23.8) '@cloudflare/workers-types': 4.20241230.0 @@ -1569,7 +1580,7 @@ snapshots: cli-progress: 3.12.0 commander: 12.1.0 inquirer: 10.2.2 - langchain: 0.3.5(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)) + langchain: 0.3.11(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)) open: 8.4.2 openai: 4.68.4(zod@3.23.8) pusher-js: 8.4.0-rc2 @@ -1635,9 +1646,9 @@ snapshots: escape-html@1.0.3: {} - esm-env@1.2.1: {} + esm-env@1.2.2: {} - esrap@1.3.2: + esrap@1.4.3: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -1813,7 +1824,7 @@ snapshots: jsonpointer@5.0.1: {} - langchain@0.3.5(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)): + langchain@0.3.11(@langchain/core@0.2.36(openai@4.68.4(zod@3.23.8)))(axios@1.7.7)(openai@4.68.4(zod@3.23.8)): dependencies: '@langchain/core': 0.2.36(openai@4.68.4(zod@3.23.8)) '@langchain/openai': 0.1.3 @@ -1821,7 +1832,7 @@ snapshots: js-tiktoken: 1.0.15 js-yaml: 4.1.0 jsonpointer: 5.0.1 - langsmith: 0.2.3(openai@4.68.4(zod@3.23.8)) + langsmith: 0.2.15(openai@4.68.4(zod@3.23.8)) openapi-types: 12.1.3 p-retry: 4.6.2 uuid: 10.0.0 @@ -1845,7 +1856,7 @@ snapshots: optionalDependencies: openai: 4.68.4(zod@3.23.8) - langsmith@0.2.3(openai@4.68.4(zod@3.23.8)): + langsmith@0.2.15(openai@4.68.4(zod@3.23.8)): dependencies: '@types/uuid': 10.0.0 commander: 10.0.1 @@ -1948,7 +1959,7 @@ snapshots: picocolors@1.1.1: {} - postcss@8.4.49: + postcss@8.5.1: dependencies: nanoid: 3.3.8 picocolors: 1.1.1 @@ -2076,8 +2087,8 @@ snapshots: aria-query: 5.3.2 axobject-query: 4.1.0 clsx: 2.1.1 - esm-env: 1.2.1 - esrap: 1.3.2 + esm-env: 1.2.2 + esrap: 1.4.3 is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.17 @@ -2165,4 +2176,8 @@ snapshots: dependencies: zod: 3.23.8 + zod-to-json-schema@3.24.1(zod@3.23.8): + dependencies: + zod: 3.23.8 + zod@3.23.8: {} diff --git a/js/examples/portfolio-generator/demo.mjs b/js/examples/portfolio-generator/demo.mjs index cf817c85406..cfb7818a00e 100644 --- a/js/examples/portfolio-generator/demo.mjs +++ b/js/examples/portfolio-generator/demo.mjs @@ -1,5 +1,6 @@ -import { openai } from "@ai-sdk/openai"; import { VercelAIToolSet } from "composio-core"; +import { openai } from "../utils.mjs"; // Comment this to use the default openai +// import { openai } from "@ai-sdk/openai"; // Uncomment this to use the default openai import dotenv from "dotenv"; import { generateText } from "ai"; dotenv.config(); @@ -21,7 +22,6 @@ async function setupUserConnectionIfNotExists(entityId) { console.log("Log in via: ", newConnection.redirectUrl); return newConnection.waitUntilActive(60); } - return connection; } @@ -35,7 +35,7 @@ async function executeAgent(entityName) { // Generate text using the model and tools const info = `I am a software engineer with 5 years of experience in the field. I have worked on multiple projects like a chatbot and a web app. I have a strong understanding of software development. I am currently looking for a new job and am open to opportunities in the San Francisco Bay Area.`; const output = await generateText({ - model: openai("gpt-4o"), + model: openai("gpt-3.5-turbo"), streamText: false, tools: tools, prompt: `Based on my info: ${info} and generate the reactjs code for a portfolio website, also give the folder directory and steps to set it up. Then put all of it in a google doc`, diff --git a/js/examples/portfolio-generator/package.json b/js/examples/portfolio-generator/package.json index 212739d0702..cf18b06c84b 100644 --- a/js/examples/portfolio-generator/package.json +++ b/js/examples/portfolio-generator/package.json @@ -10,8 +10,8 @@ "author": "", "license": "ISC", "dependencies": { - "@ai-sdk/openai": "^0.0.36", - "ai": "^3.2.24", + "@ai-sdk/openai": "^1.0.19", + "ai": "^4.0.38", "composio-core": "^0.5.3", "dotenv": "^16.4.5", "zod": "^3.23.8" diff --git a/js/examples/portfolio-generator/pnpm-lock.yaml b/js/examples/portfolio-generator/pnpm-lock.yaml index 90b78997d96..ddba5ff4026 100644 --- a/js/examples/portfolio-generator/pnpm-lock.yaml +++ b/js/examples/portfolio-generator/pnpm-lock.yaml @@ -9,14 +9,14 @@ importers: .: dependencies: '@ai-sdk/openai': - specifier: ^0.0.36 - version: 0.0.36(zod@3.23.8) + specifier: ^1.0.19 + version: 1.0.19(zod@3.23.8) ai: - specifier: ^3.2.24 - version: 3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) + specifier: ^4.0.38 + version: 4.0.38(react@18.3.1)(zod@3.23.8) composio-core: specifier: ^0.5.3 - version: 0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8))(langchain@0.2.20(axios@1.7.7)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)) + version: 0.5.3(@ai-sdk/openai@1.0.19(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@4.0.38(react@18.3.1)(zod@3.23.8))(langchain@0.2.20(axios@1.7.7)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)) dotenv: specifier: ^16.4.5 version: 16.4.5 @@ -26,14 +26,14 @@ importers: packages: - '@ai-sdk/openai@0.0.36': - resolution: {integrity: sha512-6IcvR35UMuuQEQPkVjzUtqDAuz6vy+PMCEL0PAS2ufHXdPPm81OTKVetqjgOPjebsikhVP0soK1pKPEe2cztAQ==} + '@ai-sdk/openai@1.0.19': + resolution: {integrity: sha512-7qmLgppWpGUhSgrH0a6CtgD9hZeRh2hARppl1B7fNhVbekYftSMucsdCiVlKbQzSKPxox0vkNMmwjKa/7xf8bQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 - '@ai-sdk/provider-utils@1.0.2': - resolution: {integrity: sha512-57f6O4OFVNEpI8Z8o+K40tIB3YQiTw+VCql/qrAO9Utq7Ti1o6+X9tvm177DlZJL7ft0Rwzvgy48S9YhrEKgmA==} + '@ai-sdk/provider-utils@2.0.7': + resolution: {integrity: sha512-4sfPlKEALHPXLmMFcPlYksst3sWBJXmCDZpIBJisRrmwGG6Nn3mq0N1Zu/nZaGcrWZoOY+HT2Wbxla1oTElYHQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -41,25 +41,12 @@ packages: zod: optional: true - '@ai-sdk/provider-utils@1.0.22': - resolution: {integrity: sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.0.0 - peerDependenciesMeta: - zod: - optional: true - - '@ai-sdk/provider@0.0.12': - resolution: {integrity: sha512-oOwPQD8i2Ynpn22cur4sk26FW3mSy6t6/X/K1Ay2yGBKYiSpRyLfObhOrZEGsXDx+3euKy4nEZ193R36NM+tpQ==} - engines: {node: '>=18'} - - '@ai-sdk/provider@0.0.26': - resolution: {integrity: sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==} + '@ai-sdk/provider@1.0.4': + resolution: {integrity: sha512-lJi5zwDosvvZER3e/pB8lj1MN3o3S7zJliQq56BRr4e9V3fcRyFtwP0JRxaRS5vHYX3OJ154VezVoQNrk0eaKw==} engines: {node: '>=18'} - '@ai-sdk/react@0.0.70': - resolution: {integrity: sha512-GnwbtjW4/4z7MleLiW+TOZC2M29eCg1tOUpuEiYFMmFNZK8mkrqM0PFZMo6UsYeUYMWqEOOcPOU9OQVJMJh7IQ==} + '@ai-sdk/react@1.0.11': + resolution: {integrity: sha512-ndBPA7dx2DqUr7s4zO1cRAPkFGS+wWvSri6OWfCuhfyTAADQ4vdd56vFP9zdTZl4cyL27Vh0hKLfFJMGx83MUQ==} engines: {node: '>=18'} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc @@ -70,26 +57,8 @@ packages: zod: optional: true - '@ai-sdk/solid@0.0.54': - resolution: {integrity: sha512-96KWTVK+opdFeRubqrgaJXoNiDP89gNxFRWUp0PJOotZW816AbhUf4EnDjBjXTLjXL1n0h8tGSE9sZsRkj9wQQ==} - engines: {node: '>=18'} - peerDependencies: - solid-js: ^1.7.7 - peerDependenciesMeta: - solid-js: - optional: true - - '@ai-sdk/svelte@0.0.57': - resolution: {integrity: sha512-SyF9ItIR9ALP9yDNAD+2/5Vl1IT6kchgyDH8xkmhysfJI6WrvJbtO1wdQ0nylvPLcsPoYu+cAlz1krU4lFHcYw==} - engines: {node: '>=18'} - peerDependencies: - svelte: ^3.0.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - svelte: - optional: true - - '@ai-sdk/ui-utils@0.0.50': - resolution: {integrity: sha512-Z5QYJVW+5XpSaJ4jYCCAVG7zIAuKOOdikhgpksneNmKvx61ACFaf98pmOd+xnjahl0pIlc/QIe6O4yVaJ1sEaw==} + '@ai-sdk/ui-utils@1.0.10': + resolution: {integrity: sha512-wZfZNH2IloTx5b1O8CU7/R/icm8EsmURElPckYwNYj2YZrKk9X5XeYSDBF/1/J83obzsn0i7VKkIf40qhRzVVA==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -97,36 +66,6 @@ packages: zod: optional: true - '@ai-sdk/vue@0.0.59': - resolution: {integrity: sha512-+ofYlnqdc8c4F6tM0IKF0+7NagZRAiqBJpGDJ+6EYhDW8FHLUP/JFBgu32SjxSxC6IKFZxEnl68ZoP/Z38EMlw==} - engines: {node: '>=18'} - peerDependencies: - vue: ^3.3.4 - peerDependenciesMeta: - vue: - optional: true - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.26.2': - resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/types@7.26.0': - resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} - engines: {node: '>=6.9.0'} - '@cloudflare/workers-types@4.20241230.0': resolution: {integrity: sha512-dtLD4jY35Lb750cCVyO1i/eIfdZJg2Z0i+B1RYX6BVeRPlgaHx/H18ImKAkYmy0g09Ow8R2jZy3hIxMgXun0WQ==} @@ -195,24 +134,6 @@ packages: resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} engines: {node: '>=18'} - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@langchain/core@0.2.36': resolution: {integrity: sha512-qHLvScqERDeH7y2cLuJaSAlMwg3f/3Oc9nayRSXRU2UuaK/SOhI42cxiPLj1FnuHJSmN0rBQFkrLx02gI4mcVg==} engines: {node: '>=18'} @@ -232,9 +153,6 @@ packages: '@types/diff-match-patch@1.0.36': resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/mute-stream@0.0.4': resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} @@ -256,71 +174,23 @@ packages: '@types/wrap-ansi@3.0.0': resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} - '@vue/compiler-core@3.5.13': - resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} - - '@vue/compiler-dom@3.5.13': - resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} - - '@vue/compiler-sfc@3.5.13': - resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} - - '@vue/compiler-ssr@3.5.13': - resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} - - '@vue/reactivity@3.5.13': - resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} - - '@vue/runtime-core@3.5.13': - resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} - - '@vue/runtime-dom@3.5.13': - resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} - - '@vue/server-renderer@3.5.13': - resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} - peerDependencies: - vue: 3.5.13 - - '@vue/shared@3.5.13': - resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - acorn-typescript@1.4.13: - resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} - peerDependencies: - acorn: '>=8.9.0' - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - agentkeepalive@4.5.0: resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} engines: {node: '>= 8.0.0'} - ai@3.4.33: - resolution: {integrity: sha512-plBlrVZKwPoRTmM8+D1sJac9Bq8eaa2jiZlHLZIWekKWI1yMWYZvCCEezY9ASPwRhULYDJB2VhKOBUUeg3S5JQ==} + ai@4.0.38: + resolution: {integrity: sha512-Lqo39GY8YlfUHgQdYb8qzaz+vfAu/8c8eIDck7NNKrdmwOAr8f4SuDgPVbISn1/4F9gR6WEXnD2f552ZEVT31Q==} engines: {node: '>=18'} peerDependencies: - openai: ^4.42.0 react: ^18 || ^19 || ^19.0.0-rc - sswr: ^2.1.0 - svelte: ^3.0.0 || ^4.0.0 || ^5.0.0 zod: ^3.0.0 peerDependenciesMeta: - openai: - optional: true react: optional: true - sswr: - optional: true - svelte: - optional: true zod: optional: true @@ -343,20 +213,12 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} axios@1.7.7: resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -425,9 +287,6 @@ packages: langchain: ^0.2.11 openai: ^4.50.0 - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} @@ -450,19 +309,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - - esm-env@1.1.4: - resolution: {integrity: sha512-oO82nKPHKkzIj/hbtuDYy/JHqBHFlMIW36SDiPCVsj87ntDLcWN+sJ1erdVryd4NxODacFTsdrIE3b7IamqbOg==} - - esrap@1.2.2: - resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==} - - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -470,9 +316,9 @@ packages: eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - eventsource-parser@1.1.2: - resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} - engines: {node: '>=14.18'} + eventsource-parser@3.0.0: + resolution: {integrity: sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==} + engines: {node: '>=18.0.0'} external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} @@ -522,9 +368,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-reference@3.0.3: - resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} - is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} @@ -739,16 +582,10 @@ packages: openai: optional: true - locate-character@3.0.0: - resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} - loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - magic-string@0.30.13: - resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -768,13 +605,8 @@ packages: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -831,13 +663,6 @@ packages: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} engines: {node: '>=8'} - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} - engines: {node: ^10 || ^12 || >=14} - proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -874,15 +699,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - sswr@2.1.0: - resolution: {integrity: sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ==} - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -895,23 +711,11 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - svelte@5.2.7: - resolution: {integrity: sha512-cEhPGuLHiH2+Z8B1FwQgiZJgA39uUmJR4516TKrM5zrp0/cuwJkfhUfcTxhAkznanAF5fXUKzvYR4o+Ksx3ZCQ==} - engines: {node: '>=18'} - swr@2.2.5: resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==} peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 - swrev@4.0.0: - resolution: {integrity: sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==} - - swrv@1.0.4: - resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==} - peerDependencies: - vue: '>=3.2.26 < 4' - throttleit@2.1.0: resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} engines: {node: '>=18'} @@ -933,11 +737,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - typescript@5.6.3: - resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} - engines: {node: '>=14.17'} - hasBin: true - undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -957,14 +756,6 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true - vue@3.5.13: - resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - web-streams-polyfill@4.0.0-beta.3: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} @@ -1000,116 +791,58 @@ packages: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} - zimmerframe@1.1.2: - resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} - zod-to-json-schema@3.23.5: resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==} peerDependencies: zod: ^3.23.3 + zod-to-json-schema@3.24.1: + resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==} + peerDependencies: + zod: ^3.24.1 + zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} snapshots: - '@ai-sdk/openai@0.0.36(zod@3.23.8)': + '@ai-sdk/openai@1.0.19(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 0.0.12 - '@ai-sdk/provider-utils': 1.0.2(zod@3.23.8) + '@ai-sdk/provider': 1.0.4 + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) zod: 3.23.8 - '@ai-sdk/provider-utils@1.0.2(zod@3.23.8)': + '@ai-sdk/provider-utils@2.0.7(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 0.0.12 - eventsource-parser: 1.1.2 - nanoid: 3.3.6 + '@ai-sdk/provider': 1.0.4 + eventsource-parser: 3.0.0 + nanoid: 3.3.8 secure-json-parse: 2.7.0 optionalDependencies: zod: 3.23.8 - '@ai-sdk/provider-utils@1.0.22(zod@3.23.8)': - dependencies: - '@ai-sdk/provider': 0.0.26 - eventsource-parser: 1.1.2 - nanoid: 3.3.7 - secure-json-parse: 2.7.0 - optionalDependencies: - zod: 3.23.8 - - '@ai-sdk/provider@0.0.12': + '@ai-sdk/provider@1.0.4': dependencies: json-schema: 0.4.0 - '@ai-sdk/provider@0.0.26': + '@ai-sdk/react@1.0.11(react@18.3.1)(zod@3.23.8)': dependencies: - json-schema: 0.4.0 - - '@ai-sdk/react@0.0.70(react@18.3.1)(zod@3.23.8)': - dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + '@ai-sdk/ui-utils': 1.0.10(zod@3.23.8) swr: 2.2.5(react@18.3.1) throttleit: 2.1.0 optionalDependencies: react: 18.3.1 zod: 3.23.8 - '@ai-sdk/solid@0.0.54(zod@3.23.8)': - dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - transitivePeerDependencies: - - zod - - '@ai-sdk/svelte@0.0.57(svelte@5.2.7)(zod@3.23.8)': - dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - sswr: 2.1.0(svelte@5.2.7) - optionalDependencies: - svelte: 5.2.7 - transitivePeerDependencies: - - zod - - '@ai-sdk/ui-utils@0.0.50(zod@3.23.8)': + '@ai-sdk/ui-utils@1.0.10(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 0.0.26 - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - json-schema: 0.4.0 - secure-json-parse: 2.7.0 - zod-to-json-schema: 3.23.5(zod@3.23.8) + '@ai-sdk/provider': 1.0.4 + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) optionalDependencies: zod: 3.23.8 - '@ai-sdk/vue@0.0.59(vue@3.5.13(typescript@5.6.3))(zod@3.23.8)': - dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - swrv: 1.0.4(vue@3.5.13(typescript@5.6.3)) - optionalDependencies: - vue: 3.5.13(typescript@5.6.3) - transitivePeerDependencies: - - zod - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - - '@babel/helper-string-parser@7.25.9': {} - - '@babel/helper-validator-identifier@7.25.9': {} - - '@babel/parser@7.26.2': - dependencies: - '@babel/types': 7.26.0 - - '@babel/types@7.26.0': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@cloudflare/workers-types@4.20241230.0': {} '@hey-api/client-axios@0.2.10(axios@1.7.7)': @@ -1216,23 +949,6 @@ snapshots: dependencies: mute-stream: 1.0.0 - '@jridgewell/gen-mapping@0.3.5': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - '@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8))': dependencies: ansi-styles: 5.2.0 @@ -1245,7 +961,7 @@ snapshots: p-retry: 4.6.2 uuid: 10.0.0 zod: 3.23.8 - zod-to-json-schema: 3.23.5(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) transitivePeerDependencies: - openai @@ -1255,7 +971,7 @@ snapshots: js-tiktoken: 1.0.15 openai: 4.73.0(zod@3.23.8) zod: 3.23.8 - zod-to-json-schema: 3.23.5(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) transitivePeerDependencies: - encoding @@ -1270,8 +986,6 @@ snapshots: '@types/diff-match-patch@1.0.36': {} - '@types/estree@1.0.6': {} - '@types/mute-stream@0.0.4': dependencies: '@types/node': 22.9.1 @@ -1295,98 +1009,25 @@ snapshots: '@types/wrap-ansi@3.0.0': {} - '@vue/compiler-core@3.5.13': - dependencies: - '@babel/parser': 7.26.2 - '@vue/shared': 3.5.13 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.1 - - '@vue/compiler-dom@3.5.13': - dependencies: - '@vue/compiler-core': 3.5.13 - '@vue/shared': 3.5.13 - - '@vue/compiler-sfc@3.5.13': - dependencies: - '@babel/parser': 7.26.2 - '@vue/compiler-core': 3.5.13 - '@vue/compiler-dom': 3.5.13 - '@vue/compiler-ssr': 3.5.13 - '@vue/shared': 3.5.13 - estree-walker: 2.0.2 - magic-string: 0.30.13 - postcss: 8.4.49 - source-map-js: 1.2.1 - - '@vue/compiler-ssr@3.5.13': - dependencies: - '@vue/compiler-dom': 3.5.13 - '@vue/shared': 3.5.13 - - '@vue/reactivity@3.5.13': - dependencies: - '@vue/shared': 3.5.13 - - '@vue/runtime-core@3.5.13': - dependencies: - '@vue/reactivity': 3.5.13 - '@vue/shared': 3.5.13 - - '@vue/runtime-dom@3.5.13': - dependencies: - '@vue/reactivity': 3.5.13 - '@vue/runtime-core': 3.5.13 - '@vue/shared': 3.5.13 - csstype: 3.1.3 - - '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.6.3))': - dependencies: - '@vue/compiler-ssr': 3.5.13 - '@vue/shared': 3.5.13 - vue: 3.5.13(typescript@5.6.3) - - '@vue/shared@3.5.13': {} - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 - acorn-typescript@1.4.13(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - agentkeepalive@4.5.0: dependencies: humanize-ms: 1.2.1 - ai@3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8): + ai@4.0.38(react@18.3.1)(zod@3.23.8): dependencies: - '@ai-sdk/provider': 0.0.26 - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/react': 0.0.70(react@18.3.1)(zod@3.23.8) - '@ai-sdk/solid': 0.0.54(zod@3.23.8) - '@ai-sdk/svelte': 0.0.57(svelte@5.2.7)(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - '@ai-sdk/vue': 0.0.59(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) + '@ai-sdk/provider': 1.0.4 + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + '@ai-sdk/react': 1.0.11(react@18.3.1)(zod@3.23.8) + '@ai-sdk/ui-utils': 1.0.10(zod@3.23.8) '@opentelemetry/api': 1.9.0 - eventsource-parser: 1.1.2 - json-schema: 0.4.0 jsondiffpatch: 0.6.0 - secure-json-parse: 2.7.0 - zod-to-json-schema: 3.23.5(zod@3.23.8) optionalDependencies: - openai: 4.73.0(zod@3.23.8) react: 18.3.1 - sswr: 2.1.0(svelte@5.2.7) - svelte: 5.2.7 zod: 3.23.8 - transitivePeerDependencies: - - solid-js - - vue ansi-escapes@4.3.2: dependencies: @@ -1402,8 +1043,6 @@ snapshots: argparse@2.0.1: {} - aria-query@5.3.2: {} - asynckit@0.4.0: {} axios@1.7.7: @@ -1414,8 +1053,6 @@ snapshots: transitivePeerDependencies: - debug - axobject-query@4.1.0: {} - base64-js@1.5.1: {} binary-extensions@2.3.0: {} @@ -1458,14 +1095,14 @@ snapshots: commander@12.1.0: {} - composio-core@0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8))(langchain@0.2.20(axios@1.7.7)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)): + composio-core@0.5.3(@ai-sdk/openai@1.0.19(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@4.0.38(react@18.3.1)(zod@3.23.8))(langchain@0.2.20(axios@1.7.7)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)): dependencies: - '@ai-sdk/openai': 0.0.36(zod@3.23.8) + '@ai-sdk/openai': 1.0.19(zod@3.23.8) '@cloudflare/workers-types': 4.20241230.0 '@hey-api/client-axios': 0.2.10(axios@1.7.7) '@langchain/core': 0.2.36(openai@4.73.0(zod@3.23.8)) '@langchain/openai': 0.2.11 - ai: 3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) + ai: 4.0.38(react@18.3.1)(zod@3.23.8) axios: 1.7.7 chalk: 4.1.2 cli-progress: 3.12.0 @@ -1481,8 +1118,6 @@ snapshots: transitivePeerDependencies: - debug - csstype@3.1.3: {} - decamelize@1.2.0: {} define-lazy-prop@2.0.0: {} @@ -1495,22 +1130,11 @@ snapshots: emoji-regex@8.0.0: {} - entities@4.5.0: {} - - esm-env@1.1.4: {} - - esrap@1.2.2: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - - estree-walker@2.0.2: {} - event-target-shim@5.0.1: {} eventemitter3@4.0.7: {} - eventsource-parser@1.1.2: {} + eventsource-parser@3.0.0: {} external-editor@3.1.0: dependencies: @@ -1558,10 +1182,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-reference@3.0.3: - dependencies: - '@types/estree': 1.0.6 - is-wsl@2.2.0: dependencies: is-docker: 2.2.1 @@ -1601,7 +1221,7 @@ snapshots: uuid: 10.0.0 yaml: 2.6.1 zod: 3.23.8 - zod-to-json-schema: 3.23.5(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) optionalDependencies: axios: 1.7.7 ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5) @@ -1620,16 +1240,10 @@ snapshots: optionalDependencies: openai: 4.73.0(zod@3.23.8) - locate-character@3.0.0: {} - loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 - magic-string@0.30.13: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - mime-db@1.52.0: {} mime-types@2.1.35: @@ -1642,9 +1256,7 @@ snapshots: mute-stream@1.0.0: {} - nanoid@3.3.6: {} - - nanoid@3.3.7: {} + nanoid@3.3.8: {} node-domexception@1.0.0: {} @@ -1695,14 +1307,6 @@ snapshots: dependencies: p-finally: 1.0.0 - picocolors@1.1.1: {} - - postcss@8.4.49: - dependencies: - nanoid: 3.3.7 - picocolors: 1.1.1 - source-map-js: 1.2.1 - proxy-from-env@1.1.0: {} pusher-js@8.4.0-rc2: @@ -1729,13 +1333,6 @@ snapshots: signal-exit@4.1.0: {} - source-map-js@1.2.1: {} - - sswr@2.1.0(svelte@5.2.7): - dependencies: - svelte: 5.2.7 - swrev: 4.0.0 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -1750,34 +1347,12 @@ snapshots: dependencies: has-flag: 4.0.0 - svelte@5.2.7: - dependencies: - '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - acorn: 8.14.0 - acorn-typescript: 1.4.13(acorn@8.14.0) - aria-query: 5.3.2 - axobject-query: 4.1.0 - esm-env: 1.1.4 - esrap: 1.2.2 - is-reference: 3.0.3 - locate-character: 3.0.0 - magic-string: 0.30.13 - zimmerframe: 1.1.2 - swr@2.2.5(react@18.3.1): dependencies: client-only: 0.0.1 react: 18.3.1 use-sync-external-store: 1.2.2(react@18.3.1) - swrev@4.0.0: {} - - swrv@1.0.4(vue@3.5.13(typescript@5.6.3)): - dependencies: - vue: 3.5.13(typescript@5.6.3) - throttleit@2.1.0: {} tmp@0.0.33: @@ -1792,9 +1367,6 @@ snapshots: type-fest@0.21.3: {} - typescript@5.6.3: - optional: true - undici-types@5.26.5: {} undici-types@6.19.8: {} @@ -1810,16 +1382,6 @@ snapshots: uuid@10.0.0: {} - vue@3.5.13(typescript@5.6.3): - dependencies: - '@vue/compiler-dom': 3.5.13 - '@vue/compiler-sfc': 3.5.13 - '@vue/runtime-dom': 3.5.13 - '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.6.3)) - '@vue/shared': 3.5.13 - optionalDependencies: - typescript: 5.6.3 - web-streams-polyfill@4.0.0-beta.3: {} webidl-conversions@3.0.1: {} @@ -1845,10 +1407,12 @@ snapshots: yoctocolors-cjs@2.1.2: {} - zimmerframe@1.1.2: {} - zod-to-json-schema@3.23.5(zod@3.23.8): dependencies: zod: 3.23.8 + zod-to-json-schema@3.24.1(zod@3.23.8): + dependencies: + zod: 3.23.8 + zod@3.23.8: {} diff --git a/js/examples/reddit-research/demo.mjs b/js/examples/reddit-research/demo.mjs index 9252f402b11..746c38c72fd 100644 --- a/js/examples/reddit-research/demo.mjs +++ b/js/examples/reddit-research/demo.mjs @@ -1,4 +1,5 @@ -import { openai } from "@ai-sdk/openai"; +import { openai } from "../utils.mjs"; // Comment this to use the default openai +// import { openai } from "@ai-sdk/openai"; // Uncomment this to use the default openai import { VercelAIToolSet } from "composio-core"; import dotenv from "dotenv"; import { generateText } from "ai"; diff --git a/js/examples/reddit-research/package.json b/js/examples/reddit-research/package.json index 960cf8ff5bc..846fcf93c0f 100644 --- a/js/examples/reddit-research/package.json +++ b/js/examples/reddit-research/package.json @@ -10,8 +10,8 @@ "author": "", "license": "ISC", "dependencies": { - "@ai-sdk/openai": "^0.0.36", - "ai": "^3.2.24", + "@ai-sdk/openai": "^1.0.19", + "ai": "^4.0.38", "composio-core": "0.5.3", "dotenv": "^16.4.5", "zod": "^3.23.8" diff --git a/js/examples/reddit-research/pnpm-lock.yaml b/js/examples/reddit-research/pnpm-lock.yaml index 3892251e380..6c5ed7331f0 100644 --- a/js/examples/reddit-research/pnpm-lock.yaml +++ b/js/examples/reddit-research/pnpm-lock.yaml @@ -9,14 +9,14 @@ importers: .: dependencies: '@ai-sdk/openai': - specifier: ^0.0.36 - version: 0.0.36(zod@3.23.8) + specifier: ^1.0.19 + version: 1.0.19(zod@3.23.8) ai: - specifier: ^3.2.24 - version: 3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) + specifier: ^4.0.38 + version: 4.0.38(react@18.3.1)(zod@3.23.8) composio-core: specifier: 0.5.3 - version: 0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8))(langchain@0.2.20(axios@1.7.9)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)) + version: 0.5.3(@ai-sdk/openai@1.0.19(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@4.0.38(react@18.3.1)(zod@3.23.8))(langchain@0.2.20(axios@1.7.9)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)) dotenv: specifier: ^16.4.5 version: 16.4.5 @@ -26,14 +26,14 @@ importers: packages: - '@ai-sdk/openai@0.0.36': - resolution: {integrity: sha512-6IcvR35UMuuQEQPkVjzUtqDAuz6vy+PMCEL0PAS2ufHXdPPm81OTKVetqjgOPjebsikhVP0soK1pKPEe2cztAQ==} + '@ai-sdk/openai@1.0.19': + resolution: {integrity: sha512-7qmLgppWpGUhSgrH0a6CtgD9hZeRh2hARppl1B7fNhVbekYftSMucsdCiVlKbQzSKPxox0vkNMmwjKa/7xf8bQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 - '@ai-sdk/provider-utils@1.0.2': - resolution: {integrity: sha512-57f6O4OFVNEpI8Z8o+K40tIB3YQiTw+VCql/qrAO9Utq7Ti1o6+X9tvm177DlZJL7ft0Rwzvgy48S9YhrEKgmA==} + '@ai-sdk/provider-utils@2.0.7': + resolution: {integrity: sha512-4sfPlKEALHPXLmMFcPlYksst3sWBJXmCDZpIBJisRrmwGG6Nn3mq0N1Zu/nZaGcrWZoOY+HT2Wbxla1oTElYHQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -41,25 +41,12 @@ packages: zod: optional: true - '@ai-sdk/provider-utils@1.0.22': - resolution: {integrity: sha512-YHK2rpj++wnLVc9vPGzGFP3Pjeld2MwhKinetA0zKXOoHAT/Jit5O8kZsxcSlJPu9wvcGT1UGZEjZrtO7PfFOQ==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.0.0 - peerDependenciesMeta: - zod: - optional: true - - '@ai-sdk/provider@0.0.12': - resolution: {integrity: sha512-oOwPQD8i2Ynpn22cur4sk26FW3mSy6t6/X/K1Ay2yGBKYiSpRyLfObhOrZEGsXDx+3euKy4nEZ193R36NM+tpQ==} - engines: {node: '>=18'} - - '@ai-sdk/provider@0.0.26': - resolution: {integrity: sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg==} + '@ai-sdk/provider@1.0.4': + resolution: {integrity: sha512-lJi5zwDosvvZER3e/pB8lj1MN3o3S7zJliQq56BRr4e9V3fcRyFtwP0JRxaRS5vHYX3OJ154VezVoQNrk0eaKw==} engines: {node: '>=18'} - '@ai-sdk/react@0.0.70': - resolution: {integrity: sha512-GnwbtjW4/4z7MleLiW+TOZC2M29eCg1tOUpuEiYFMmFNZK8mkrqM0PFZMo6UsYeUYMWqEOOcPOU9OQVJMJh7IQ==} + '@ai-sdk/react@1.0.11': + resolution: {integrity: sha512-ndBPA7dx2DqUr7s4zO1cRAPkFGS+wWvSri6OWfCuhfyTAADQ4vdd56vFP9zdTZl4cyL27Vh0hKLfFJMGx83MUQ==} engines: {node: '>=18'} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc @@ -70,26 +57,8 @@ packages: zod: optional: true - '@ai-sdk/solid@0.0.54': - resolution: {integrity: sha512-96KWTVK+opdFeRubqrgaJXoNiDP89gNxFRWUp0PJOotZW816AbhUf4EnDjBjXTLjXL1n0h8tGSE9sZsRkj9wQQ==} - engines: {node: '>=18'} - peerDependencies: - solid-js: ^1.7.7 - peerDependenciesMeta: - solid-js: - optional: true - - '@ai-sdk/svelte@0.0.57': - resolution: {integrity: sha512-SyF9ItIR9ALP9yDNAD+2/5Vl1IT6kchgyDH8xkmhysfJI6WrvJbtO1wdQ0nylvPLcsPoYu+cAlz1krU4lFHcYw==} - engines: {node: '>=18'} - peerDependencies: - svelte: ^3.0.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - svelte: - optional: true - - '@ai-sdk/ui-utils@0.0.50': - resolution: {integrity: sha512-Z5QYJVW+5XpSaJ4jYCCAVG7zIAuKOOdikhgpksneNmKvx61ACFaf98pmOd+xnjahl0pIlc/QIe6O4yVaJ1sEaw==} + '@ai-sdk/ui-utils@1.0.10': + resolution: {integrity: sha512-wZfZNH2IloTx5b1O8CU7/R/icm8EsmURElPckYwNYj2YZrKk9X5XeYSDBF/1/J83obzsn0i7VKkIf40qhRzVVA==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -97,36 +66,6 @@ packages: zod: optional: true - '@ai-sdk/vue@0.0.59': - resolution: {integrity: sha512-+ofYlnqdc8c4F6tM0IKF0+7NagZRAiqBJpGDJ+6EYhDW8FHLUP/JFBgu32SjxSxC6IKFZxEnl68ZoP/Z38EMlw==} - engines: {node: '>=18'} - peerDependencies: - vue: ^3.3.4 - peerDependenciesMeta: - vue: - optional: true - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.26.3': - resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/types@7.26.3': - resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} - engines: {node: '>=6.9.0'} - '@cloudflare/workers-types@4.20241230.0': resolution: {integrity: sha512-dtLD4jY35Lb750cCVyO1i/eIfdZJg2Z0i+B1RYX6BVeRPlgaHx/H18ImKAkYmy0g09Ow8R2jZy3hIxMgXun0WQ==} @@ -195,24 +134,6 @@ packages: resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} engines: {node: '>=18'} - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@langchain/core@0.2.36': resolution: {integrity: sha512-qHLvScqERDeH7y2cLuJaSAlMwg3f/3Oc9nayRSXRU2UuaK/SOhI42cxiPLj1FnuHJSmN0rBQFkrLx02gI4mcVg==} engines: {node: '>=18'} @@ -232,9 +153,6 @@ packages: '@types/diff-match-patch@1.0.36': resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/mute-stream@0.0.4': resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} @@ -256,71 +174,23 @@ packages: '@types/wrap-ansi@3.0.0': resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} - '@vue/compiler-core@3.5.13': - resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} - - '@vue/compiler-dom@3.5.13': - resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} - - '@vue/compiler-sfc@3.5.13': - resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} - - '@vue/compiler-ssr@3.5.13': - resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} - - '@vue/reactivity@3.5.13': - resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} - - '@vue/runtime-core@3.5.13': - resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} - - '@vue/runtime-dom@3.5.13': - resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} - - '@vue/server-renderer@3.5.13': - resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} - peerDependencies: - vue: 3.5.13 - - '@vue/shared@3.5.13': - resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - acorn-typescript@1.4.13: - resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} - peerDependencies: - acorn: '>=8.9.0' - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - agentkeepalive@4.6.0: resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} - ai@3.4.33: - resolution: {integrity: sha512-plBlrVZKwPoRTmM8+D1sJac9Bq8eaa2jiZlHLZIWekKWI1yMWYZvCCEezY9ASPwRhULYDJB2VhKOBUUeg3S5JQ==} + ai@4.0.38: + resolution: {integrity: sha512-Lqo39GY8YlfUHgQdYb8qzaz+vfAu/8c8eIDck7NNKrdmwOAr8f4SuDgPVbISn1/4F9gR6WEXnD2f552ZEVT31Q==} engines: {node: '>=18'} peerDependencies: - openai: ^4.42.0 react: ^18 || ^19 || ^19.0.0-rc - sswr: ^2.1.0 - svelte: ^3.0.0 || ^4.0.0 || ^5.0.0 zod: ^3.0.0 peerDependenciesMeta: - openai: - optional: true react: optional: true - sswr: - optional: true - svelte: - optional: true zod: optional: true @@ -343,20 +213,12 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} axios@1.7.9: resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -425,9 +287,6 @@ packages: langchain: ^0.2.11 openai: ^4.50.0 - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} @@ -450,19 +309,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - - esm-env@1.2.1: - resolution: {integrity: sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==} - - esrap@1.3.2: - resolution: {integrity: sha512-C4PXusxYhFT98GjLSmb20k9PREuUdporer50dhzGuJu9IJXktbMddVCMLAERl5dAHyAi73GWWCE4FVHGP1794g==} - - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -470,9 +316,9 @@ packages: eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - eventsource-parser@1.1.2: - resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} - engines: {node: '>=14.18'} + eventsource-parser@3.0.0: + resolution: {integrity: sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==} + engines: {node: '>=18.0.0'} external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} @@ -522,9 +368,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-reference@3.0.3: - resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} - is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} @@ -739,16 +582,10 @@ packages: openai: optional: true - locate-character@3.0.0: - resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} - loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -768,16 +605,6 @@ packages: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - nanoid@3.3.8: resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -836,13 +663,6 @@ packages: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} engines: {node: '>=8'} - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} - engines: {node: ^10 || ^12 || >=14} - proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -879,15 +699,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - sswr@2.1.0: - resolution: {integrity: sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ==} - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -900,23 +711,11 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - svelte@5.2.7: - resolution: {integrity: sha512-cEhPGuLHiH2+Z8B1FwQgiZJgA39uUmJR4516TKrM5zrp0/cuwJkfhUfcTxhAkznanAF5fXUKzvYR4o+Ksx3ZCQ==} - engines: {node: '>=18'} - swr@2.2.5: resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==} peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 - swrev@4.0.0: - resolution: {integrity: sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==} - - swrv@1.0.4: - resolution: {integrity: sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==} - peerDependencies: - vue: '>=3.2.26 < 4' - throttleit@2.1.0: resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} engines: {node: '>=18'} @@ -938,11 +737,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - typescript@5.6.3: - resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} - engines: {node: '>=14.17'} - hasBin: true - undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -962,14 +756,6 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true - vue@3.5.13: - resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - web-streams-polyfill@4.0.0-beta.3: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} @@ -1005,14 +791,6 @@ packages: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} - zimmerframe@1.1.2: - resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} - - zod-to-json-schema@3.23.5: - resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==} - peerDependencies: - zod: ^3.23.3 - zod-to-json-schema@3.24.1: resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==} peerDependencies: @@ -1026,103 +804,43 @@ packages: snapshots: - '@ai-sdk/openai@0.0.36(zod@3.23.8)': - dependencies: - '@ai-sdk/provider': 0.0.12 - '@ai-sdk/provider-utils': 1.0.2(zod@3.23.8) - zod: 3.23.8 - - '@ai-sdk/provider-utils@1.0.2(zod@3.23.8)': + '@ai-sdk/openai@1.0.19(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 0.0.12 - eventsource-parser: 1.1.2 - nanoid: 3.3.6 - secure-json-parse: 2.7.0 - optionalDependencies: + '@ai-sdk/provider': 1.0.4 + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) zod: 3.23.8 - '@ai-sdk/provider-utils@1.0.22(zod@3.23.8)': + '@ai-sdk/provider-utils@2.0.7(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 0.0.26 - eventsource-parser: 1.1.2 - nanoid: 3.3.7 + '@ai-sdk/provider': 1.0.4 + eventsource-parser: 3.0.0 + nanoid: 3.3.8 secure-json-parse: 2.7.0 optionalDependencies: zod: 3.23.8 - '@ai-sdk/provider@0.0.12': - dependencies: - json-schema: 0.4.0 - - '@ai-sdk/provider@0.0.26': + '@ai-sdk/provider@1.0.4': dependencies: json-schema: 0.4.0 - '@ai-sdk/react@0.0.70(react@18.3.1)(zod@3.23.8)': + '@ai-sdk/react@1.0.11(react@18.3.1)(zod@3.23.8)': dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + '@ai-sdk/ui-utils': 1.0.10(zod@3.23.8) swr: 2.2.5(react@18.3.1) throttleit: 2.1.0 optionalDependencies: react: 18.3.1 zod: 3.23.8 - '@ai-sdk/solid@0.0.54(zod@3.23.8)': - dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - transitivePeerDependencies: - - zod - - '@ai-sdk/svelte@0.0.57(svelte@5.2.7)(zod@3.23.8)': - dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - sswr: 2.1.0(svelte@5.2.7) - optionalDependencies: - svelte: 5.2.7 - transitivePeerDependencies: - - zod - - '@ai-sdk/ui-utils@0.0.50(zod@3.23.8)': + '@ai-sdk/ui-utils@1.0.10(zod@3.23.8)': dependencies: - '@ai-sdk/provider': 0.0.26 - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - json-schema: 0.4.0 - secure-json-parse: 2.7.0 - zod-to-json-schema: 3.23.5(zod@3.23.8) + '@ai-sdk/provider': 1.0.4 + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) optionalDependencies: zod: 3.23.8 - '@ai-sdk/vue@0.0.59(vue@3.5.13(typescript@5.6.3))(zod@3.23.8)': - dependencies: - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - swrv: 1.0.4(vue@3.5.13(typescript@5.6.3)) - optionalDependencies: - vue: 3.5.13(typescript@5.6.3) - transitivePeerDependencies: - - zod - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - - '@babel/helper-string-parser@7.25.9': {} - - '@babel/helper-validator-identifier@7.25.9': {} - - '@babel/parser@7.26.3': - dependencies: - '@babel/types': 7.26.3 - - '@babel/types@7.26.3': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@cloudflare/workers-types@4.20241230.0': {} '@hey-api/client-axios@0.2.12(axios@1.7.9)': @@ -1229,23 +947,6 @@ snapshots: dependencies: mute-stream: 1.0.0 - '@jridgewell/gen-mapping@0.3.8': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - '@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8))': dependencies: ansi-styles: 5.2.0 @@ -1283,15 +984,13 @@ snapshots: '@types/diff-match-patch@1.0.36': {} - '@types/estree@1.0.6': {} - '@types/mute-stream@0.0.4': dependencies: '@types/node': 22.10.5 '@types/node-fetch@2.6.12': dependencies: - '@types/node': 18.19.70 + '@types/node': 22.10.5 form-data: 4.0.1 '@types/node@18.19.70': @@ -1308,98 +1007,25 @@ snapshots: '@types/wrap-ansi@3.0.0': {} - '@vue/compiler-core@3.5.13': - dependencies: - '@babel/parser': 7.26.3 - '@vue/shared': 3.5.13 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.1 - - '@vue/compiler-dom@3.5.13': - dependencies: - '@vue/compiler-core': 3.5.13 - '@vue/shared': 3.5.13 - - '@vue/compiler-sfc@3.5.13': - dependencies: - '@babel/parser': 7.26.3 - '@vue/compiler-core': 3.5.13 - '@vue/compiler-dom': 3.5.13 - '@vue/compiler-ssr': 3.5.13 - '@vue/shared': 3.5.13 - estree-walker: 2.0.2 - magic-string: 0.30.17 - postcss: 8.4.49 - source-map-js: 1.2.1 - - '@vue/compiler-ssr@3.5.13': - dependencies: - '@vue/compiler-dom': 3.5.13 - '@vue/shared': 3.5.13 - - '@vue/reactivity@3.5.13': - dependencies: - '@vue/shared': 3.5.13 - - '@vue/runtime-core@3.5.13': - dependencies: - '@vue/reactivity': 3.5.13 - '@vue/shared': 3.5.13 - - '@vue/runtime-dom@3.5.13': - dependencies: - '@vue/reactivity': 3.5.13 - '@vue/runtime-core': 3.5.13 - '@vue/shared': 3.5.13 - csstype: 3.1.3 - - '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.6.3))': - dependencies: - '@vue/compiler-ssr': 3.5.13 - '@vue/shared': 3.5.13 - vue: 3.5.13(typescript@5.6.3) - - '@vue/shared@3.5.13': {} - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 - acorn-typescript@1.4.13(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - agentkeepalive@4.6.0: dependencies: humanize-ms: 1.2.1 - ai@3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8): + ai@4.0.38(react@18.3.1)(zod@3.23.8): dependencies: - '@ai-sdk/provider': 0.0.26 - '@ai-sdk/provider-utils': 1.0.22(zod@3.23.8) - '@ai-sdk/react': 0.0.70(react@18.3.1)(zod@3.23.8) - '@ai-sdk/solid': 0.0.54(zod@3.23.8) - '@ai-sdk/svelte': 0.0.57(svelte@5.2.7)(zod@3.23.8) - '@ai-sdk/ui-utils': 0.0.50(zod@3.23.8) - '@ai-sdk/vue': 0.0.59(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) + '@ai-sdk/provider': 1.0.4 + '@ai-sdk/provider-utils': 2.0.7(zod@3.23.8) + '@ai-sdk/react': 1.0.11(react@18.3.1)(zod@3.23.8) + '@ai-sdk/ui-utils': 1.0.10(zod@3.23.8) '@opentelemetry/api': 1.9.0 - eventsource-parser: 1.1.2 - json-schema: 0.4.0 jsondiffpatch: 0.6.0 - secure-json-parse: 2.7.0 - zod-to-json-schema: 3.23.5(zod@3.23.8) optionalDependencies: - openai: 4.73.0(zod@3.23.8) react: 18.3.1 - sswr: 2.1.0(svelte@5.2.7) - svelte: 5.2.7 zod: 3.23.8 - transitivePeerDependencies: - - solid-js - - vue ansi-escapes@4.3.2: dependencies: @@ -1415,8 +1041,6 @@ snapshots: argparse@2.0.1: {} - aria-query@5.3.2: {} - asynckit@0.4.0: {} axios@1.7.9: @@ -1427,8 +1051,6 @@ snapshots: transitivePeerDependencies: - debug - axobject-query@4.1.0: {} - base64-js@1.5.1: {} binary-extensions@2.3.0: {} @@ -1471,14 +1093,14 @@ snapshots: commander@12.1.0: {} - composio-core@0.5.3(@ai-sdk/openai@0.0.36(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8))(langchain@0.2.20(axios@1.7.9)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)): + composio-core@0.5.3(@ai-sdk/openai@1.0.19(zod@3.23.8))(@cloudflare/workers-types@4.20241230.0)(@langchain/core@0.2.36(openai@4.73.0(zod@3.23.8)))(@langchain/openai@0.2.11)(ai@4.0.38(react@18.3.1)(zod@3.23.8))(langchain@0.2.20(axios@1.7.9)(openai@4.73.0(zod@3.23.8))(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)))(openai@4.73.0(zod@3.23.8)): dependencies: - '@ai-sdk/openai': 0.0.36(zod@3.23.8) + '@ai-sdk/openai': 1.0.19(zod@3.23.8) '@cloudflare/workers-types': 4.20241230.0 '@hey-api/client-axios': 0.2.12(axios@1.7.9) '@langchain/core': 0.2.36(openai@4.73.0(zod@3.23.8)) '@langchain/openai': 0.2.11 - ai: 3.4.33(openai@4.73.0(zod@3.23.8))(react@18.3.1)(sswr@2.1.0(svelte@5.2.7))(svelte@5.2.7)(vue@3.5.13(typescript@5.6.3))(zod@3.23.8) + ai: 4.0.38(react@18.3.1)(zod@3.23.8) axios: 1.7.9 chalk: 4.1.2 cli-progress: 3.12.0 @@ -1494,8 +1116,6 @@ snapshots: transitivePeerDependencies: - debug - csstype@3.1.3: {} - decamelize@1.2.0: {} define-lazy-prop@2.0.0: {} @@ -1508,21 +1128,11 @@ snapshots: emoji-regex@8.0.0: {} - entities@4.5.0: {} - - esm-env@1.2.1: {} - - esrap@1.3.2: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - estree-walker@2.0.2: {} - event-target-shim@5.0.1: {} eventemitter3@4.0.7: {} - eventsource-parser@1.1.2: {} + eventsource-parser@3.0.0: {} external-editor@3.1.0: dependencies: @@ -1570,10 +1180,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-reference@3.0.3: - dependencies: - '@types/estree': 1.0.6 - is-wsl@2.2.0: dependencies: is-docker: 2.2.1 @@ -1632,16 +1238,10 @@ snapshots: optionalDependencies: openai: 4.73.0(zod@3.23.8) - locate-character@3.0.0: {} - loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 - magic-string@0.30.17: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - mime-db@1.52.0: {} mime-types@2.1.35: @@ -1654,10 +1254,6 @@ snapshots: mute-stream@1.0.0: {} - nanoid@3.3.6: {} - - nanoid@3.3.7: {} - nanoid@3.3.8: {} node-domexception@1.0.0: {} @@ -1723,14 +1319,6 @@ snapshots: dependencies: p-finally: 1.0.0 - picocolors@1.1.1: {} - - postcss@8.4.49: - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - proxy-from-env@1.1.0: {} pusher-js@8.4.0-rc2: @@ -1757,13 +1345,6 @@ snapshots: signal-exit@4.1.0: {} - source-map-js@1.2.1: {} - - sswr@2.1.0(svelte@5.2.7): - dependencies: - svelte: 5.2.7 - swrev: 4.0.0 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -1778,34 +1359,12 @@ snapshots: dependencies: has-flag: 4.0.0 - svelte@5.2.7: - dependencies: - '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - acorn: 8.14.0 - acorn-typescript: 1.4.13(acorn@8.14.0) - aria-query: 5.3.2 - axobject-query: 4.1.0 - esm-env: 1.2.1 - esrap: 1.3.2 - is-reference: 3.0.3 - locate-character: 3.0.0 - magic-string: 0.30.17 - zimmerframe: 1.1.2 - swr@2.2.5(react@18.3.1): dependencies: client-only: 0.0.1 react: 18.3.1 use-sync-external-store: 1.2.2(react@18.3.1) - swrev@4.0.0: {} - - swrv@1.0.4(vue@3.5.13(typescript@5.6.3)): - dependencies: - vue: 3.5.13(typescript@5.6.3) - throttleit@2.1.0: {} tmp@0.0.33: @@ -1820,9 +1379,6 @@ snapshots: type-fest@0.21.3: {} - typescript@5.6.3: - optional: true - undici-types@5.26.5: {} undici-types@6.20.0: {} @@ -1838,16 +1394,6 @@ snapshots: uuid@10.0.0: {} - vue@3.5.13(typescript@5.6.3): - dependencies: - '@vue/compiler-dom': 3.5.13 - '@vue/compiler-sfc': 3.5.13 - '@vue/runtime-dom': 3.5.13 - '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.6.3)) - '@vue/shared': 3.5.13 - optionalDependencies: - typescript: 5.6.3 - web-streams-polyfill@4.0.0-beta.3: {} webidl-conversions@3.0.1: {} @@ -1873,12 +1419,6 @@ snapshots: yoctocolors-cjs@2.1.2: {} - zimmerframe@1.1.2: {} - - zod-to-json-schema@3.23.5(zod@3.23.8): - dependencies: - zod: 3.23.8 - zod-to-json-schema@3.24.1(zod@3.23.8): dependencies: zod: 3.23.8 diff --git a/js/examples/utils.mjs b/js/examples/utils.mjs new file mode 100644 index 00000000000..b41a036b011 --- /dev/null +++ b/js/examples/utils.mjs @@ -0,0 +1,13 @@ +import { createOpenAI } from "@ai-sdk/openai"; + +export const heliconeParams = { + baseURL: "https://oai.helicone.ai/v1", + headers: { + "Helicone-Auth": `Bearer ${process.env.HELICONE_API_KEY}`, + "Helicone-Cache-Enabled": "true", + "Helicone-User-Id": "GitHub-CI-Example-Tests", + }, +}; +export const openai = createOpenAI({ + ...heliconeParams, +}); From 864723706a586c08e35523d46d917fead09b97f2 Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Thu, 16 Jan 2025 18:49:33 +0530 Subject: [PATCH 27/34] fix: enforce specific NodeJS version (#943) Co-authored-by: Himanshu Dixit --- js/package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/package.json b/js/package.json index 2bb05840cd0..d6fee91e280 100644 --- a/js/package.json +++ b/js/package.json @@ -102,5 +102,9 @@ "publishConfig": { "access": "public" }, + "engineStrict": true, + "engines": { + "node": ">=18.0.0" + }, "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" } From ee56d22d712e585acdf7babc8f985d4cd1ce4885 Mon Sep 17 00:00:00 2001 From: Prathit <67639393+Prat011@users.noreply.github.com> Date: Fri, 17 Jan 2025 17:42:34 +0530 Subject: [PATCH 28/34] feat: crypto kit agents added (#1205) --- docs/cryptokit/coinbase_agent.mdx | 139 ++ docs/cryptokit/community_reward_agent.mdx | 262 +++ .../github_contributor_reward_agent.mdx | 253 +++ docs/cryptokit/tools.mdx | 1647 +++++++++++++++++ docs/mint.json | 9 + .../cryptokit/coinbase/.env.example | 2 + .../cryptokit/coinbase/README.md | 35 + .../cryptokit/coinbase/main.py | 54 + .../cryptokit/coinbase/requirements.txt | 2 + .../cryptokit/coinbase/setup.sh | 33 + .../cryptokit/solana/.env.example | 4 + .../cryptokit/solana/README.md | 56 + .../cryptokit/solana/coder_reward_agent.py | 49 + .../solana/community_reward_agent.py | 53 + .../cryptokit/solana/crypto_assistant.py | 46 + .../advanced_agents/cryptokit/solana/setup.sh | 37 + .../cryptokit/solana/solana_kit.py | 143 ++ 17 files changed, 2824 insertions(+) create mode 100644 docs/cryptokit/coinbase_agent.mdx create mode 100644 docs/cryptokit/community_reward_agent.mdx create mode 100644 docs/cryptokit/github_contributor_reward_agent.mdx create mode 100644 docs/cryptokit/tools.mdx create mode 100644 python/examples/advanced_agents/cryptokit/coinbase/.env.example create mode 100644 python/examples/advanced_agents/cryptokit/coinbase/README.md create mode 100644 python/examples/advanced_agents/cryptokit/coinbase/main.py create mode 100644 python/examples/advanced_agents/cryptokit/coinbase/requirements.txt create mode 100644 python/examples/advanced_agents/cryptokit/coinbase/setup.sh create mode 100644 python/examples/advanced_agents/cryptokit/solana/.env.example create mode 100644 python/examples/advanced_agents/cryptokit/solana/README.md create mode 100644 python/examples/advanced_agents/cryptokit/solana/coder_reward_agent.py create mode 100644 python/examples/advanced_agents/cryptokit/solana/community_reward_agent.py create mode 100644 python/examples/advanced_agents/cryptokit/solana/crypto_assistant.py create mode 100644 python/examples/advanced_agents/cryptokit/solana/setup.sh create mode 100644 python/examples/advanced_agents/cryptokit/solana/solana_kit.py diff --git a/docs/cryptokit/coinbase_agent.mdx b/docs/cryptokit/coinbase_agent.mdx new file mode 100644 index 00000000000..9f1fc1ff514 --- /dev/null +++ b/docs/cryptokit/coinbase_agent.mdx @@ -0,0 +1,139 @@ +--- +title: "Coinbase Wallet Manager Agent" +sidebarTitle: "Coinbase Wallet Manager Agent" +description: "This project demonstrates how to use Composio to create a Coinbase Wallet Manager Agent." +--- + +## Overview + +The Coinbase Wallet Manager Agent is an AI Agent that allows your agent to create wallets, send tokens, check balances, and more using Coinbase. + +## Getting Started + + + + + +```bash install dependencies +pip install composio-llamaindex python-dotenv +``` + + + +```bash connect to required tools +composio add coinbase + +export OPENAI_API_KEY="" +``` + + + +```python import required libraries +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from dotenv import load_dotenv +import json +import os + +``` + + + +```python initialize toolset and llm +toolset = ComposioToolSet(api_key="") +tools = toolset.get_tools(actions=[ + Action.COINBASE_CREATE_WALLET, + Action.COINBASE_LIST_WALLETS, + Action.COINBASE_GET_WALLET_INFO, + Action.COINBASE_SEND_TOKENS, + Action.COINBASE_CHECK_TRANSFER, + Action.COINBASE_COINBASE_FAUCET, + Action.FILETOOL_CREATE_FILE, + Action.FILETOOL_WRITE +]) + + +llm = OpenAI(model="gpt-4o") +``` + + + +```python setup function calling worker +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a coinbase agent that can execute coinbase actions" + ), + ) +] + +agent = FunctionCallingAgentWorker( + tools=tools, + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() +``` + + + +```python run the agent +agent.chat("Create a coinbase wallet, write the wallet address, seed and wallet id in a file called wallet.txt and get its balance") +``` + + + +```python final code +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from dotenv import load_dotenv + +load_dotenv() + +toolset = ComposioToolSet(api_key="") +tools = toolset.get_tools(actions=[ + Action.COINBASE_CREATE_WALLET, + Action.COINBASE_LIST_WALLETS, + Action.COINBASE_GET_WALLET_INFO, + Action.COINBASE_SEND_TOKENS, + Action.COINBASE_CHECK_TRANSFER, + Action.COINBASE_COINBASE_FAUCET, + Action.FILETOOL_CREATE_FILE, + Action.FILETOOL_WRITE +]) + +llm = OpenAI(model="gpt-4o") + +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a coinbase agent that can execute actions on Coinbase" + ), + ) +] + +agent = FunctionCallingAgentWorker( + tools=tools, + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() + + +response = agent.chat("Create a coinbase wallet, write the wallet address, seed and wallet id in a file called wallet.txt and get its balance") +print(response) +``` + + + + \ No newline at end of file diff --git a/docs/cryptokit/community_reward_agent.mdx b/docs/cryptokit/community_reward_agent.mdx new file mode 100644 index 00000000000..f489e58e806 --- /dev/null +++ b/docs/cryptokit/community_reward_agent.mdx @@ -0,0 +1,262 @@ +--- +title: "Community Reward Agent" +sidebarTitle: "Community Reward Agent" +description: "This project demonstrates how to use Composio to create a Community Reward Agent." +--- + +## Overview + +The Community Reward Agent is an AI Agent that rewards community members with SOL based on their engagement. + +## Getting Started + + + + + +```bash install dependencies +pip install composio-llamaindex python-dotenv +``` + + + +```bash connect to required tools +composio add github + +export OPENAI_API_KEY="" +``` + + + +```python import required libraries +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from solana_kit import get_balance, send_sol, get_transaction_status, request_airdrop +from dotenv import load_dotenv +import json +import os +import datetime + +date = datetime.datetime.now().strftime("%Y-%m-%d") +``` + + + +```python create solana transfer action +from solders.keypair import Keypair +from solders.pubkey import Pubkey +from solana.rpc.api import Client +from solders.system_program import TransferParams, transfer +from solders.transaction import Transaction +from solders.message import Message +from composio import action +import base58 +from solders.signature import Signature + +@action(toolname='solanakit', requires=['solana','solders']) +def send_sol(sender_private_key: str, receiver_public_key: str, amount: str, network: str = "devnet") -> str: + """ + Send SOL to a wallet + :param sender_private_key: private key of the sender + :param receiver_public_key: address of the wallet to send SOL to + :param amount: amount of SOL to send, should be in lamports + :param network: network to send the transaction on + :return transaction_hash: transaction hash + """ + try: + # Create keypair for sender + # Use a valid Base58-encoded private key for the sender + sender_keypair = Keypair.from_base58_string(sender_private_key) + sender_public_key = sender_keypair.pubkey() + + # Define receiver's public key + receiver_public_key_ = Pubkey.from_string(receiver_public_key) + + # Build the transfer instruction + ixns = [ + transfer( + TransferParams( + from_pubkey=sender_public_key, + to_pubkey=receiver_public_key_, + lamports=int(amount) + ) + ) + ] + + # Create a message with the transaction + msg = Message(ixns, sender_public_key) + + # Connect to a Solana client + client = Client(f"https://api.{network}.solana.com") # Using Devnet RPC endpoint + + # Fetch the latest blockhash + latest_blockhash = client.get_latest_blockhash().value.blockhash + + # Create the transaction + transaction = Transaction([sender_keypair], msg, latest_blockhash) + + # Send the transaction + response = client.send_transaction(transaction) + print("Transaction response:", response) + return "Transaction sent successfully: "+str(response) + except ValueError as e: + return f"Error: Invalid key format - {str(e)}" + except Exception as e: + return f"Error sending transaction: {str(e)}" + +``` + + + +```python initialize toolset and llm +toolset = ComposioToolSet(api_key="") +tools = toolset.get_tools(actions=[send_sol, Action.SLACK_FETCH_CONVERSATION_HISTORY, Action.SLACK_LIST_ALL_SLACK_TEAM_CHANNELS_WITH_VARIOUS_FILTERS, Action.SLACK_LIST_ALL_SLACK_TEAM_USERS_WITH_PAGINATION, Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL]) + +llm = OpenAI(model="gpt-4o") +``` + + + +```python setup function calling worker +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a solana agent that can execute actions with Solana Kit" + "You also have access to Slack and can fetch conversation history and get channel id based on the channel name. You can also get username based on the user id by fetching all users in the slack team. Your job is to find out the most active community member and reward them with 1 SOL" + ), + ) +] + +agent = FunctionCallingAgentWorker( + tools=tools, + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() +``` + + + +```python run the agent +community_channel_name = input("Enter the name of the slack channel: ") +response = agent.chat(f"""Find only the most active community member this week from the slack channel {community_channel_name} and then print their slack name. The date today is {date}""") +print(response) +wallet_address = input("Enter the wallet address of the most active community member: ") +private_key = os.getenv('SOLANA_PRIVATE_KEY') +my_wallet_address = os.getenv('SOLANA_WALLET_ADDRESS') +agent.chat(f"""send 1 SOL from my wallet {my_wallet_address}, my private key is {private_key} to {wallet_address} on devnet using send sol action and then check transaction status twice/thrice after 5 seconds of the transaction using get transaction status action. After the the transaction is confirmed, send a message to the slack channel {community_channel_name} with the username of the most active community member announcing that they are the most active community member this week and congratulate them and tell them they have been rewarded with 1 SOL""") +``` + + + +```python final code +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from dotenv import load_dotenv +from solders.keypair import Keypair +from solders.pubkey import Pubkey +from solana.rpc.api import Client +from solders.system_program import TransferParams, transfer +from solders.transaction import Transaction +from solders.message import Message +from composio import action +import base58 +from solders.signature import Signature + +load_dotenv() + +@action(toolname='solanakit', requires=['solana','solders']) +def send_sol(sender_private_key: str, receiver_public_key: str, amount: str, network: str = "devnet") -> str: + """ + Send SOL to a wallet + :param sender_private_key: private key of the sender + :param receiver_public_key: address of the wallet to send SOL to + :param amount: amount of SOL to send, should be in lamports + :param network: network to send the transaction on + :return transaction_hash: transaction hash + """ + try: + # Create keypair for sender + # Use a valid Base58-encoded private key for the sender + sender_keypair = Keypair.from_base58_string(sender_private_key) + sender_public_key = sender_keypair.pubkey() + + # Define receiver's public key + receiver_public_key_ = Pubkey.from_string(receiver_public_key) + + # Build the transfer instruction + ixns = [ + transfer( + TransferParams( + from_pubkey=sender_public_key, + to_pubkey=receiver_public_key_, + lamports=int(amount) + ) + ) + ] + + # Create a message with the transaction + msg = Message(ixns, sender_public_key) + + # Connect to a Solana client + client = Client(f"https://api.{network}.solana.com") # Using Devnet RPC endpoint + + # Fetch the latest blockhash + latest_blockhash = client.get_latest_blockhash().value.blockhash + + # Create the transaction + transaction = Transaction([sender_keypair], msg, latest_blockhash) + + # Send the transaction + response = client.send_transaction(transaction) + print("Transaction response:", response) + return "Transaction sent successfully: "+str(response) + except ValueError as e: + return f"Error: Invalid key format - {str(e)}" + except Exception as e: + return f"Error sending transaction: {str(e)}" + +toolset = ComposioToolSet(api_key="") +tools = toolset.get_tools(actions=[send_sol, Action.GITHUB_LIST_REPOSITORY_CONTRIBUTORS]) + +llm = OpenAI(model="gpt-4o") + +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a solana agent that can execute actions with Solana Kit" + "You have access to Github and can list repository contributors" + ), + ) +] + +agent = FunctionCallingAgentWorker( + tools=tools, + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() + + +community_channel_name = input("Enter the name of the slack channel: ") +response = agent.chat(f"""Find only the most active community member this week from the slack channel {community_channel_name} and then print their slack name. The date today is {date}""") +print(response) +wallet_address = input("Enter the wallet address of the most active community member: ") +private_key = os.getenv('SOLANA_PRIVATE_KEY') +my_wallet_address = os.getenv('SOLANA_WALLET_ADDRESS') +agent.chat(f"""send 1 SOL from my wallet {my_wallet_address}, my private key is {private_key} to {wallet_address} on devnet using send sol action and then check transaction status twice/thrice after 5 seconds of the transaction using get transaction status action. After the the transaction is confirmed, send a message to the slack channel {community_channel_name} with the username of the most active community member announcing that they are the most active community member this week and congratulate them and tell them they have been rewarded with 1 SOL""") +``` + + + + \ No newline at end of file diff --git a/docs/cryptokit/github_contributor_reward_agent.mdx b/docs/cryptokit/github_contributor_reward_agent.mdx new file mode 100644 index 00000000000..78758d1e408 --- /dev/null +++ b/docs/cryptokit/github_contributor_reward_agent.mdx @@ -0,0 +1,253 @@ +--- +title: "Github Contributor Reward Agent" +sidebarTitle: "Github Reward Agent" +description: "This project demonstrates how to use Composio to create a Github Contributor Reward Agent." +--- + +## Overview + +The Github Contributor Reward Agent is an AI Agent that rewards Github Contributors with SOL based on their contributions. + +## Getting Started + + + + + +```bash install dependencies +pip install composio-llamaindex python-dotenv +``` + + + +```bash connect to required tools +composio add github + +export OPENAI_API_KEY="" +``` + + + +```python import required libraries +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from dotenv import load_dotenv + +load_dotenv() +``` + + + +```python create solana transfer action +from solders.keypair import Keypair +from solders.pubkey import Pubkey +from solana.rpc.api import Client +from solders.system_program import TransferParams, transfer +from solders.transaction import Transaction +from solders.message import Message +from composio import action +import base58 +from solders.signature import Signature + +@action(toolname='solanakit', requires=['solana','solders']) +def send_sol(sender_private_key: str, receiver_public_key: str, amount: str, network: str = "devnet") -> str: + """ + Send SOL to a wallet + :param sender_private_key: private key of the sender + :param receiver_public_key: address of the wallet to send SOL to + :param amount: amount of SOL to send, should be in lamports + :param network: network to send the transaction on + :return transaction_hash: transaction hash + """ + try: + # Create keypair for sender + # Use a valid Base58-encoded private key for the sender + sender_keypair = Keypair.from_base58_string(sender_private_key) + sender_public_key = sender_keypair.pubkey() + + # Define receiver's public key + receiver_public_key_ = Pubkey.from_string(receiver_public_key) + + # Build the transfer instruction + ixns = [ + transfer( + TransferParams( + from_pubkey=sender_public_key, + to_pubkey=receiver_public_key_, + lamports=int(amount) + ) + ) + ] + + # Create a message with the transaction + msg = Message(ixns, sender_public_key) + + # Connect to a Solana client + client = Client(f"https://api.{network}.solana.com") # Using Devnet RPC endpoint + + # Fetch the latest blockhash + latest_blockhash = client.get_latest_blockhash().value.blockhash + + # Create the transaction + transaction = Transaction([sender_keypair], msg, latest_blockhash) + + # Send the transaction + response = client.send_transaction(transaction) + print("Transaction response:", response) + return "Transaction sent successfully: "+str(response) + except ValueError as e: + return f"Error: Invalid key format - {str(e)}" + except Exception as e: + return f"Error sending transaction: {str(e)}" + +``` + + + +```python initialize toolset and llm +toolset = ComposioToolSet(api_key="") +tools = toolset.get_tools(actions=[send_sol, Action.GITHUB_LIST_REPOSITORY_CONTRIBUTORS]) + +llm = OpenAI(model="gpt-4o") +``` + + + +```python setup function calling worker +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a solana agent that can execute actions with Solana Kit" + "You have access to Github and can list repository contributors" + ), + ) +] + +agent = FunctionCallingAgentWorker( + tools=tools, + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() +``` + + + +```python run the agent +agent.chat("Find the most active contributor to the composiohq/composio repository and print their username.") +wallet_address = input("Enter the wallet address of the most active contributor: ") +private_key = os.getenv('SOLANA_PRIVATE_KEY') +my_wallet_address = os.getenv('SOLANA_WALLET_ADDRESS') +agent.chat(f"""send 1 SOL from my wallet {my_wallet_address}, my private key is {private_key} to {wallet_address} on devnet using send sol action""") +``` + + + +```python final code +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from dotenv import load_dotenv +from solders.keypair import Keypair +from solders.pubkey import Pubkey +from solana.rpc.api import Client +from solders.system_program import TransferParams, transfer +from solders.transaction import Transaction +from solders.message import Message +from composio import action +import base58 +from solders.signature import Signature + +load_dotenv() + +@action(toolname='solanakit', requires=['solana','solders']) +def send_sol(sender_private_key: str, receiver_public_key: str, amount: str, network: str = "devnet") -> str: + """ + Send SOL to a wallet + :param sender_private_key: private key of the sender + :param receiver_public_key: address of the wallet to send SOL to + :param amount: amount of SOL to send, should be in lamports + :param network: network to send the transaction on + :return transaction_hash: transaction hash + """ + try: + # Create keypair for sender + # Use a valid Base58-encoded private key for the sender + sender_keypair = Keypair.from_base58_string(sender_private_key) + sender_public_key = sender_keypair.pubkey() + + # Define receiver's public key + receiver_public_key_ = Pubkey.from_string(receiver_public_key) + + # Build the transfer instruction + ixns = [ + transfer( + TransferParams( + from_pubkey=sender_public_key, + to_pubkey=receiver_public_key_, + lamports=int(amount) + ) + ) + ] + + # Create a message with the transaction + msg = Message(ixns, sender_public_key) + + # Connect to a Solana client + client = Client(f"https://api.{network}.solana.com") # Using Devnet RPC endpoint + + # Fetch the latest blockhash + latest_blockhash = client.get_latest_blockhash().value.blockhash + + # Create the transaction + transaction = Transaction([sender_keypair], msg, latest_blockhash) + + # Send the transaction + response = client.send_transaction(transaction) + print("Transaction response:", response) + return "Transaction sent successfully: "+str(response) + except ValueError as e: + return f"Error: Invalid key format - {str(e)}" + except Exception as e: + return f"Error sending transaction: {str(e)}" + +toolset = ComposioToolSet(api_key="") +tools = toolset.get_tools(actions=[send_sol, Action.GITHUB_LIST_REPOSITORY_CONTRIBUTORS]) + +llm = OpenAI(model="gpt-4o") + +prefix_messages = [ + ChatMessage( + role="system", + content=( + "You are a solana agent that can execute actions with Solana Kit" + "You have access to Github and can list repository contributors" + ), + ) +] + +agent = FunctionCallingAgentWorker( + tools=tools, + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=10, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() + +agent.chat("Find the most active contributor to the composiohq/composio repository and print their username.") +wallet_address = input("Enter the wallet address of the most active contributor: ") +private_key = os.getenv('SOLANA_PRIVATE_KEY') +my_wallet_address = os.getenv('SOLANA_WALLET_ADDRESS') +agent.chat(f"""send 1 SOL from my wallet {my_wallet_address}, my private key is {private_key} to {wallet_address} on devnet using send sol action""") +``` + + + + \ No newline at end of file diff --git a/docs/cryptokit/tools.mdx b/docs/cryptokit/tools.mdx new file mode 100644 index 00000000000..c3607a6f0b8 --- /dev/null +++ b/docs/cryptokit/tools.mdx @@ -0,0 +1,1647 @@ +--- +title: "Tools For AI SDR Kit" +sidebarTitle: "Tools" +description: "List of tools you can use for your AI SDR Development, compatible with agentic frameworks like CrewAI, LangChain, and LlamaIndex etc. These utilities enable file system operations, command execution, and other core development tasks" +--- + +## Centralized Exchanges + + +Coinbase is a centralized exchange (CEX) protocol that allows users to trade cryptocurrencies with the need for intermediaries. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.COINBASE]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["COINBASE"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Binance is a centralized exchange (CEX) protocol that allows users to trade cryptocurrencies with the need for intermediaries. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.BINANCE]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["BINANCE"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + + +## Decentralized Exchanges + + +Uniswap is a decentralized exchange (DEX) protocol that allows users to trade cryptocurrencies without the need for intermediaries. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.UNISWAP]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["UNISWAP"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +SushiSwap is a decentralized exchange (DEX) protocol that allows users to trade cryptocurrencies without the need for intermediaries. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.SUSHISWAP]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["SUSHISWAP"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Jupiter is a decentralized exchange (DEX) protocol that allows users to trade cryptocurrencies without the need for intermediaries. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.JUPITER]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["JUPITER"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +dYdX is a decentralized exchange (DEX) protocol that allows users to trade cryptocurrencies without the need for intermediaries. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.DYDX]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["DYDX"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## Analytics and Research + + +CoinGecko is a platform that provides information about prices and market cap of cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.COINGECKO]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["COINGECKO"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +Glassnode is a platform that provides on chain analytics and research tools for cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.GLASSNODE]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["GLASSNODE"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +Nansen is a platform that provides on chain analytics and research tools for cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.NANSEN]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["NANSEN"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Dune Analytics is a platform that provides on chain analytics and research tools for cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.DUNE]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["DUNE"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## DeFi Lending/Borrowing + + +Aave is a decentralized lending protocol that allows users to lend and borrow cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.AAVE]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["AAVE"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Compound is a decentralized lending protocol that allows users to lend and borrow cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.COMPOUND]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["COMPOUND"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +MakerDAO is a decentralized lending protocol that allows users to lend and borrow cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.MAKERDAO]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["MAKERDAO"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +YearnFinance is a decentralized lending protocol that allows users to lend and borrow cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.YEARN]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["YEARN"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Beefy Finance is a decentralized lending protocol that allows users to lend and borrow cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.BEEFY]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["BEEFY"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## Staking platforms + + +Lido Finance is a decentralized staking protocol that allows users to stake their cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.LIDO]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["LIDO"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Rocket Pool is a decentralized staking protocol that allows users to stake their cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.ROCKETPOOL]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["ROCKETPOOL"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Stader is a decentralized staking protocol that allows users to stake their cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.STADER]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["STADER"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Ankr is a decentralized staking protocol that allows users to stake their cryptocurrencies. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.ANKR]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["ANKR"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## NFT Marketplaces + + +Opensea is a decentralized NFT marketplace that allows users to buy and sell NFTs. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.OPENSEA]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["OPENSEA"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Blur is a decentralized NFT marketplace that allows users to buy and sell NFTs. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.BLUR]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["BLUR"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Magic Eden is a decentralized NFT marketplace that allows users to buy and sell NFTs. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.MAGICEDEN]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["MAGICEDEN"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +NFTGo is a decentralized NFT marketplace that allows users to buy and sell NFTs. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.NFTGO]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["NFTGO"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Manifold is a decentralized NFT marketplace that allows users to buy and sell NFTs. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.MANIFOLD]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["MANIFOLD"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Zora is a decentralized NFT marketplace that allows users to buy and sell NFTs. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.ZORA]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["ZORA"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## Security and Compliance + + +Chainlysis is a platform that helps ensure crypto compliance. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.OPENSEA]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["OPENSEA"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Elliptic is a platform that helps ensure crypto compliance. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.ELLIPTIC]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["ELLIPTIC"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Chainlysis is a platform that helps ensure crypto compliance. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.OPENSEA]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["OPENSEA"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## Payments and Infrastructure + + +BitPay is a payment processor that allows users to pay for goods and services. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.BITPAY]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["BITPAY"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +MoonPay is a payment processor that allows users to pay for goods and services. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.MOONPAY]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["MOONPAY"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## Oracles + + +Chainlink is a platform that provides oracle services for blockchain networks. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.CHAINLINK]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["CHAINLINK"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + +Band Protocol is a platform that provides oracle services for blockchain networks. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.BAND_PROTOCOL]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["BAND_PROTOCOL"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +## Community Engagement + + +Discord is a platform that allows users to communicate with each other. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.DISCORD]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["DISCORD"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + + +Telegram is a platform that allows users to communicate with each other. + + ```python Python + from langchain.agents import create_openai_functions_agent, AgentExecutor + from langchain import hub + from langchain_openai import ChatOpenAI + from composio_langchain import ComposioToolSet, Action, App + + llm = ChatOpenAI() + prompt = hub.pull("hwchase17/openai-functions-agent") + + composio_toolset = ComposioToolSet() + tools = composio_toolset.get_tools(apps=[App.TELEGRAM]) + + agent = create_openai_functions_agent(llm, tools, prompt) + agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + + task = "your task description here" + result = agent_executor.invoke({"input": task}) + print(result) + ``` + ```javascript JS + import { ChatOpenAI } from "@langchain/openai"; + import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; + import { LangchainToolSet } from "composio-core"; + import { pull } from "langchain/hub"; + + const llm = new ChatOpenAI({ + model: "gpt-4-turbo", + temperature: 0, + }); + + const prompt = await pull("hwchase17/openai-functions-agent"); + + const toolset = new LangchainToolSet({ apiKey: "" }); + const tools = await toolset.getTools({ apps: ["TELEGRAM"] }); + + const agent = await createOpenAIFunctionsAgent({llm, tools, prompt}); + + const agentExecutor = new AgentExecutor({ agent, tools, verbose: true }); + + const response = await agentExecutor.invoke({ input: "your task description here" }); + console.log(response); + ``` + + + \ No newline at end of file diff --git a/docs/mint.json b/docs/mint.json index f236f3cbbd1..f5ae46714d6 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -181,6 +181,15 @@ "sdrkit/ai-market-research-agent", "sdrkit/ai-scheduling-agent" ] + }, + { + "group": "Crypto Kit", + "pages": [ + "cryptokit/tools", + "cryptokit/community_reward_agent", + "cryptokit/github_contributor_reward_agent", + "cryptokit/coinbase_agent" + ] } ] }, diff --git a/python/examples/advanced_agents/cryptokit/coinbase/.env.example b/python/examples/advanced_agents/cryptokit/coinbase/.env.example new file mode 100644 index 00000000000..cc53370124a --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/coinbase/.env.example @@ -0,0 +1,2 @@ +OPENAI_API_KEY=KEY +COMPOSIO_API_KEY=KEY diff --git a/python/examples/advanced_agents/cryptokit/coinbase/README.md b/python/examples/advanced_agents/cryptokit/coinbase/README.md new file mode 100644 index 00000000000..219f56e11df --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/coinbase/README.md @@ -0,0 +1,35 @@ +# Coinbase Crypto Kit Agent + +A powerful toolkit for building AI agents that can create wallets, send tokens, check balances, and more using Coinbase. + +## Prerequisites + +- Python 3.8 or higher + + +## Installation + +1. **Clone the Repository** + ```sh + git clone + cd path/to/project/directory + ``` + +2. **Set Up Environment** + ```sh + chmod +x setup.sh + ./setup.sh + ``` + +3. **Configure Environment Variables** + Create a `.env` file with the following variables: + ```env + OPENAI_API_KEY= + COMPOSIO_API_KEY= + ``` + +Allows your agent to create wallets, send tokens, check balances, and more using Coinbase. + +```sh +python cookbook/python-examples/advanced_agents/cryptokit/coinbase/main.py +``` diff --git a/python/examples/advanced_agents/cryptokit/coinbase/main.py b/python/examples/advanced_agents/cryptokit/coinbase/main.py new file mode 100644 index 00000000000..56c50d29ceb --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/coinbase/main.py @@ -0,0 +1,54 @@ +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from dotenv import load_dotenv +from composio import action +import json +import os + +# Load environment variables +load_dotenv() + +# Initialize toolset and LLM +toolset = ComposioToolSet() + +tools = toolset.get_tools(actions=[ + Action.COINBASE_CREATE_WALLET, + Action.COINBASE_LIST_WALLETS, + Action.COINBASE_GET_WALLET_INFO, + Action.COINBASE_SEND_TOKENS, + Action.COINBASE_CHECK_TRANSFER, + Action.COINBASE_COINBASE_FAUCET, + Action.FILETOOL_CREATE_FILE, + Action.FILETOOL_WRITE +]) + +llm = OpenAI(model="gpt-4o") + +# Setup chatbot-style prefix messages +def create_prefix_message(): + return [ + ChatMessage( + role="system", + content=( + "You are a coinbase agent that can execute coinbase actions" + ), + ) + ] + +prefix_messages = create_prefix_message() + +# Initialize the agent +agent = FunctionCallingAgentWorker( + tools=tools, # type: ignore + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=20, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() + +response = agent.chat(f"""Create a wallet on Coinbase, save the wallet address, seed and wallet id in a file called wallet.txt and get its balance""") + +print(response) \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/coinbase/requirements.txt b/python/examples/advanced_agents/cryptokit/coinbase/requirements.txt new file mode 100644 index 00000000000..afafa3214f2 --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/coinbase/requirements.txt @@ -0,0 +1,2 @@ +composio-llamaindex +python-dotenv \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/coinbase/setup.sh b/python/examples/advanced_agents/cryptokit/coinbase/setup.sh new file mode 100644 index 00000000000..291860d7d0a --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/coinbase/setup.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Create a virtual environment +echo "Creating virtual environment..." +python3 -m venv ~/.venvs/cryptokit + +# Activate the virtual environment +echo "Activating virtual environment..." +source ~/.venvs/cryptokit/bin/activate + +# Install libraries from requirements.txt +echo "Installing libraries from requirements.txt..." +pip install -r requirements.txt + +# Login to your account +echo "Login to your Composio acount" +composio login + +composio add coinbase + +# Copy env backup to .env file +if [ -f ".env.example" ]; then + echo "Copying .env.example to .env..." + cp .env.example .env +else + echo "No .env.example file found. Creating a new .env file..." + touch .env +fi + +# Prompt user to fill the .env file +echo "Please fill in the .env file with the necessary environment variables." + +echo "Setup completed successfully!" \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/solana/.env.example b/python/examples/advanced_agents/cryptokit/solana/.env.example new file mode 100644 index 00000000000..8809a302f2e --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/solana/.env.example @@ -0,0 +1,4 @@ +OPENAI_API_KEY= +COMPOSIO_API_KEY= +SOLANA_PRIVATE_KEY= +SOLANA_WALLET_ADDRESS= diff --git a/python/examples/advanced_agents/cryptokit/solana/README.md b/python/examples/advanced_agents/cryptokit/solana/README.md new file mode 100644 index 00000000000..f4d9bf12c33 --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/solana/README.md @@ -0,0 +1,56 @@ +# Solana Crypto Kit Agents + +A powerful toolkit for building automated blockchain agents that interact with the Solana ecosystem using Composio. These agents can handle various operations including token transfers, balance checks, transaction monitoring, and automated rewards distribution. + +## Features + +- 🔄 SOL token transfers and management +- 💰 Wallet balance monitoring +- 🔍 Transaction status tracking +- 🪂 SOL airdrop requests +- 🤝 Community reward distribution +- 👨‍💻 Coder reward automation +- 🔗 Integration with Github, Discord, and Slack and more + +## Prerequisites + +- Python 3.8 or higher + +## Installation + +1. **Clone the Repository** + ```sh + git clone + cd path/to/project/directory + ``` + +2. **Set Up Environment** + ```sh + chmod +x setup.sh + ./setup.sh + ``` + +3. **Configure Environment Variables** + Create a `.env` file with the following variables: + ```env + OPENAI_API_KEY= + COMPOSIO_API_KEY= + SOLANA_PRIVATE_KEY= + SOLANA_WALLET_ADDRESS= + ``` + +## Available Agents + +### Community Reward Agent +Automates the distribution of SOL tokens to community members based on their contributions. + +```sh +python cookbook/python-examples/advanced_agents/cryptokit/solana/community_reward_agent.py +``` + +### Coder Reward Agent +Manages automated payments to developers based on code contributions and milestones. + +```sh +python cookbook/python-examples/advanced_agents/cryptokit/solana/coder_reward_agent.py +``` \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/solana/coder_reward_agent.py b/python/examples/advanced_agents/cryptokit/solana/coder_reward_agent.py new file mode 100644 index 00000000000..a1ff9c7ca23 --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/solana/coder_reward_agent.py @@ -0,0 +1,49 @@ +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from solana_kit import get_balance, send_sol, get_transaction_status, request_airdrop +from dotenv import load_dotenv +import json +import os + +# Load environment variables +load_dotenv() + +# Initialize toolset and LLM +toolset = ComposioToolSet() + +tools = toolset.get_tools(actions=[get_balance, send_sol, get_transaction_status, request_airdrop, Action.GITHUB_LIST_REPOSITORY_CONTRIBUTORS]) + +llm = OpenAI(model="gpt-4o") + +# Setup chatbot-style prefix messages +def create_prefix_message(): + return [ + ChatMessage( + role="system", + content=( + "You are a solana agent that can execute actions with Solana Kit" + "You have access to Github and can list repository contributors" + "You can also get the github username of the contributor based on the github user id" + ), + ) + ] + +prefix_messages = create_prefix_message() + +# Initialize the agent +agent = FunctionCallingAgentWorker( + tools=tools, # type: ignore + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=20, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() + +agent.chat("Find the most active contributor to the composiohq/composio repository and print their username.") +wallet_address = input("Enter the wallet address of the most active contributor: ") +private_key = os.getenv('SOLANA_PRIVATE_KEY') +my_wallet_address = os.getenv('SOLANA_WALLET_ADDRESS') +agent.chat(f"""send 1 SOL from my wallet {my_wallet_address}, my private key is {private_key} to {wallet_address} on devnet using send sol action""") \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/solana/community_reward_agent.py b/python/examples/advanced_agents/cryptokit/solana/community_reward_agent.py new file mode 100644 index 00000000000..1da14c67f10 --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/solana/community_reward_agent.py @@ -0,0 +1,53 @@ +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from solana_kit import get_balance, send_sol, get_transaction_status, request_airdrop +from dotenv import load_dotenv +import json +import os +import datetime + +date = datetime.datetime.now().strftime("%Y-%m-%d") + +# Load environment variables +load_dotenv() + +# Initialize toolset and LLM +toolset = ComposioToolSet() + +tools = toolset.get_tools(actions=[get_balance, send_sol, get_transaction_status, request_airdrop, Action.SLACK_FETCH_CONVERSATION_HISTORY, Action.SLACK_LIST_ALL_SLACK_TEAM_CHANNELS_WITH_VARIOUS_FILTERS, Action.SLACK_LIST_ALL_SLACK_TEAM_USERS_WITH_PAGINATION, Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL]) + +llm = OpenAI(model="gpt-4o") + +# Setup chatbot-style prefix messages +def create_prefix_message(): + return [ + ChatMessage( + role="system", + content=( + "You are a solana agent that can execute actions with Solana Kit" + "You also have access to Slack and can fetch conversation history and get channel id based on the channel name. You can also get username based on the user id by fetching all users in the slack team. Your job is to find out the most active community member and reward them with 1 SOL" + ), + ) + ] + +prefix_messages = create_prefix_message() + +# Initialize the agent +agent = FunctionCallingAgentWorker( + tools=tools, # type: ignore + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=20, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() + +community_channel_name = input("Enter the name of the slack channel: ") +response = agent.chat(f"""Find only the most active community member this week from the slack channel {community_channel_name} and then print their slack name. The date today is {date}""") +print(response) +wallet_address = input("Enter the wallet address of the most active community member: ") +private_key = os.getenv('SOLANA_PRIVATE_KEY') +my_wallet_address = os.getenv('SOLANA_WALLET_ADDRESS') +agent.chat(f"""send 1 SOL from my wallet {my_wallet_address}, my private key is {private_key} to {wallet_address} on devnet using send sol action and then check transaction status twice/thrice after 5 seconds of the transaction using get transaction status action. After the the transaction is confirmed, send a message to the slack channel {community_channel_name} with the username of the most active community member announcing that they are the most active community member this week and congratulate them and tell them they have been rewarded with 1 SOL""") \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/solana/crypto_assistant.py b/python/examples/advanced_agents/cryptokit/solana/crypto_assistant.py new file mode 100644 index 00000000000..f4f8e135b61 --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/solana/crypto_assistant.py @@ -0,0 +1,46 @@ +from composio_llamaindex import ComposioToolSet, App, Action +from llama_index.core.agent import FunctionCallingAgentWorker +from llama_index.core.llms import ChatMessage +from llama_index.llms.openai import OpenAI +from solana_kit import get_balance, send_sol, get_transaction_status, request_airdrop +from dotenv import load_dotenv +import json +import os + +# Load environment variables +load_dotenv() + +# Initialize toolset and LLM +toolset = ComposioToolSet() + +tools = toolset.get_tools(actions=[get_balance, send_sol, get_transaction_status, request_airdrop]) + +llm = OpenAI(model="gpt-4o") + +# Setup chatbot-style prefix messages +def create_prefix_message(): + return [ + ChatMessage( + role="system", + content=( + "You are a solana agent" + ), + ) + ] + +prefix_messages = create_prefix_message() + +# Initialize the agent +agent = FunctionCallingAgentWorker( + tools=tools, # type: ignore + llm=llm, + prefix_messages=prefix_messages, + max_function_calls=20, + allow_parallel_tool_calls=False, + verbose=True, +).as_agent() + +my_wallet_address = os.getenv('SOLANA_WALLET_ADDRESS') +response = agent.chat(f"""Get the balance of my wallet {my_wallet_address}""") + +print(response) \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/solana/setup.sh b/python/examples/advanced_agents/cryptokit/solana/setup.sh new file mode 100644 index 00000000000..a82b226856c --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/solana/setup.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Create a virtual environment +echo "Creating virtual environment..." +python3 -m venv ~/.venvs/cryptokit + +# Activate the virtual environment +echo "Activating virtual environment..." +source ~/.venvs/cryptokit/bin/activate + +# Install libraries from requirements.txt +echo "Installing libraries from requirements.txt..." +pip install -r requirements.txt + +# Login to your account +echo "Login to your Composio acount" +composio login + + + +echo "Add slack tool. Finish the flow" +composio add slack +composio add github + +# Copy env backup to .env file +if [ -f ".env.example" ]; then + echo "Copying .env.example to .env..." + cp .env.example .env +else + echo "No .env.example file found. Creating a new .env file..." + touch .env +fi + +# Prompt user to fill the .env file +echo "Please fill in the .env file with the necessary environment variables." + +echo "Setup completed successfully!" \ No newline at end of file diff --git a/python/examples/advanced_agents/cryptokit/solana/solana_kit.py b/python/examples/advanced_agents/cryptokit/solana/solana_kit.py new file mode 100644 index 00000000000..18195d77b7e --- /dev/null +++ b/python/examples/advanced_agents/cryptokit/solana/solana_kit.py @@ -0,0 +1,143 @@ +from solders.keypair import Keypair +from solders.pubkey import Pubkey +from solana.rpc.api import Client +from solders.system_program import TransferParams, transfer +from solders.message import Message +from solders.transaction import Transaction +from composio import action +import base58 +from solders.keypair import Keypair +from solders.signature import Signature +import csv + + + +@action(toolname='solanakit', requires=['solana','solders']) +def get_balance(wallet_address: str, network: str = "devnet") -> str: + """ + Get the SOL balance of your wallet + :param wallet_address: address of your wallet + :param network: network to get the balance on + :return wallet_balance: balance of wallet + """ + try: + from solders.pubkey import Pubkey # type: ignore + from solana.rpc.api import Client + http_client = Client(f"https://api.{network}.solana.com") + res = http_client.get_balance(pubkey=Pubkey.from_string(wallet_address)) + return str(res.value/ 1_000_000_000)+" SOL" + except ValueError as e: + return f"Error: Invalid wallet address - {str(e)}" + except Exception as e: + return f"Error getting balance: {str(e)}" + + +@action(toolname='solanakit', requires=['solana','solders']) +def create_wallet() -> str: + """ + Create a new wallet + :return wallet_balance: balance of wallet + """ + try: + WALLETS_AMOUNT = 1 + + with open("wallets.csv", 'w', newline='') as csvfile: + csv_writer = csv.writer(csvfile) + csv_writer.writerow(["WALLET", "PRIVATE KEY"]) + + for x in range(WALLETS_AMOUNT): + account = Keypair() + privateKey = base58.b58encode(account.secret() + base58.b58decode(str(account.pubkey()))).decode('utf-8') + + csv_writer.writerow([account.pubkey(), privateKey]) + return "Wallet created successfully, public key and private key saved in wallets.csv" + except PermissionError: + return "Error: Unable to write to wallets.csv - Permission denied" + except Exception as e: + return f"Error creating wallet: {str(e)}" + +@action(toolname='solanakit', requires=['solana','solders']) +def send_sol(sender_private_key: str, receiver_public_key: str, amount: str, network: str = "devnet") -> str: + """ + Send SOL to a wallet + :param sender_private_key: private key of the sender + :param receiver_public_key: address of the wallet to send SOL to + :param amount: amount of SOL to send, should be in lamports + :param network: network to send the transaction on + :return transaction_hash: transaction hash + """ + try: + # Create keypair for sender + # Use a valid Base58-encoded private key for the sender + sender_keypair = Keypair.from_base58_string(sender_private_key) + sender_public_key = sender_keypair.pubkey() + + # Define receiver's public key + receiver_public_key_ = Pubkey.from_string(receiver_public_key) + + # Build the transfer instruction + ixns = [ + transfer( + TransferParams( + from_pubkey=sender_public_key, + to_pubkey=receiver_public_key_, + lamports=int(amount) + ) + ) + ] + + # Create a message with the transaction + msg = Message(ixns, sender_public_key) + + # Connect to a Solana client + client = Client(f"https://api.{network}.solana.com") # Using Devnet RPC endpoint + + # Fetch the latest blockhash + latest_blockhash = client.get_latest_blockhash().value.blockhash + + # Create the transaction + transaction = Transaction([sender_keypair], msg, latest_blockhash) + + # Send the transaction + response = client.send_transaction(transaction) + print("Transaction response:", response) + return "Transaction sent successfully: "+str(response) + except ValueError as e: + return f"Error: Invalid key format - {str(e)}" + except Exception as e: + return f"Error sending transaction: {str(e)}" + +@action(toolname='solanakit', requires=['solana','solders']) +def get_transaction_status(transaction_hash: str, network: str = "devnet") -> str: + """ + Get the status of a transaction + :param transaction_hash: hash of the transaction + :param network: network to get the transaction status on + :return transaction_status: status of the transaction + """ + try: + client = Client(f"https://api.{network}.solana.com") # Using Devnet RPC endpoint + res = client.get_transaction(tx_sig=Signature.from_string(transaction_hash)) + return str(res) + except ValueError as e: + return f"Error: Invalid transaction hash - {str(e)}" + except Exception as e: + return f"Error getting transaction status: {str(e)}" + +@action(toolname='solanakit', requires=['solana','solders']) +def request_airdrop(wallet_address: str, amount: str, network: str = "devnet") -> str: + """ + Request an airdrop of SOL to a wallet + :param wallet_address: address of the wallet to request an airdrop to + :param amount: amount of SOL to request, should be in lamports + :param network: network to request the airdrop on + :return airdrop_status: status of the airdrop + """ + try: + http_client = Client(f"https://api.{network}.solana.com") + res = http_client.request_airdrop(Pubkey.from_string(wallet_address),lamports=int(amount)) + return str(res) + except ValueError as e: + return f"Error: Invalid wallet address or amount - {str(e)}" + except Exception as e: + return f"Error requesting airdrop: {str(e)}" \ No newline at end of file From 9b5db7f132ec97b4bd6a49bc5c927245bcec6fd7 Mon Sep 17 00:00:00 2001 From: Himanshu Dixit Date: Sat, 18 Jan 2025 13:10:44 +0530 Subject: [PATCH 29/34] =?UTF-8?q?feat:=20triggerId=20->=20triggerName,=20t?= =?UTF-8?q?riggerInstanceId,=20add=20methods=20for=20co=E2=80=A6=20(#1207)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/src/cli/add.ts | 4 +- js/src/sdk/base.toolset.ts | 2 +- js/src/sdk/models/Entity.ts | 2 +- js/src/sdk/models/connectedAccounts.spec.ts | 4 +- js/src/sdk/models/connectedAccounts.ts | 134 +++++++++++++++----- js/src/sdk/models/integrations.spec.ts | 7 +- js/src/sdk/models/integrations.ts | 92 ++++++++++---- js/src/sdk/models/triggers.spec.ts | 4 +- js/src/sdk/models/triggers.ts | 123 ++++++++++++------ js/src/sdk/types/connectedAccount.ts | 1 + js/src/sdk/types/integration.ts | 4 +- js/src/sdk/types/trigger.ts | 15 ++- js/src/sdk/utils/config.ts | 1 + 13 files changed, 282 insertions(+), 111 deletions(-) diff --git a/js/src/cli/add.ts b/js/src/cli/add.ts index 3b96b39cc8c..1586930b153 100644 --- a/js/src/cli/add.ts +++ b/js/src/cli/add.ts @@ -193,9 +193,9 @@ export default class AddCommand { config.scopes = (options.scope as string[]).join(","); } - const connectionData = await composioClient.connectedAccounts.create({ + const connectionData = await composioClient.connectedAccounts.initiate({ integrationId, - data: config, + connectionParams: config, labels: options.label as string[], }); diff --git a/js/src/sdk/base.toolset.ts b/js/src/sdk/base.toolset.ts index 08b20f4021d..92e08df3674 100644 --- a/js/src/sdk/base.toolset.ts +++ b/js/src/sdk/base.toolset.ts @@ -33,7 +33,7 @@ import { } from "./utils/processor/file"; export type ExecuteActionParams = z.infer & { - // @deprecated + /** @deprecated use actionName field instead */ action?: string; actionName?: string; }; diff --git a/js/src/sdk/models/Entity.ts b/js/src/sdk/models/Entity.ts index 1a8b37287c7..b83acda1ec3 100644 --- a/js/src/sdk/models/Entity.ts +++ b/js/src/sdk/models/Entity.ts @@ -29,7 +29,7 @@ const LABELS = { // Types from zod schemas export type TriggerSubscribeParam = z.infer; export type ConnectionParams = z.infer & { - // @deprecated + /** @deprecated use appName field instead */ app?: string; appName?: string; }; diff --git a/js/src/sdk/models/connectedAccounts.spec.ts b/js/src/sdk/models/connectedAccounts.spec.ts index 5a73a52e5b3..1b1fd16d6a0 100644 --- a/js/src/sdk/models/connectedAccounts.spec.ts +++ b/js/src/sdk/models/connectedAccounts.spec.ts @@ -33,7 +33,9 @@ describe("ConnectedAccounts class tests", () => { const connectionsData: TConnectionData = { appNames: "github", }; - const connectionsList = await connectedAccounts.list(connectionsData); + const connectionsList = await connectedAccounts.list({ + appUniqueKeys: ["gmail"], + }); const connectionId = connectionsList.items[0].id; diff --git a/js/src/sdk/models/connectedAccounts.ts b/js/src/sdk/models/connectedAccounts.ts index d3ce30b5915..4dbad32b225 100644 --- a/js/src/sdk/models/connectedAccounts.ts +++ b/js/src/sdk/models/connectedAccounts.ts @@ -8,7 +8,6 @@ import { import { default as apiClient } from "../client/client"; import { ZInitiateConnectionDataReq, - ZInitiateConnectionPayloadDto, ZListConnectionsData, ZReinitiateConnectionPayloadDto, ZSaveUserAccessDataParam, @@ -20,12 +19,17 @@ import { TELEMETRY_LOGGER } from "../utils/telemetry"; import { TELEMETRY_EVENTS } from "../utils/telemetry/events"; import { BackendClient } from "./backendClient"; -// Schema type from conectedAccount.ts -type ConnectedAccountsListData = z.infer; +type ConnectedAccountsListData = z.infer & { + /** @deprecated use appUniqueKeys field instead */ + appNames?: string; +}; + type InitiateConnectionDataReq = z.infer; + type SingleConnectionParam = z.infer; + type SaveUserAccessDataParam = z.infer; -type InitiateConnectionPayload = z.infer; + type ReinitiateConnectionPayload = z.infer< typeof ZReinitiateConnectionPayloadDto >; @@ -33,16 +37,33 @@ type ReinitiateConnectionPayload = z.infer< export type ConnectedAccountListResponse = GetConnectionsResponseDto; export type SingleConnectedAccountResponse = ConnectedAccountResponseDTO; export type SingleDeleteResponse = DeleteRowAPIDTO; + +export type ConnectionChangeResponse = { + status: "success"; + connectedAccountId: string; +}; export type ConnectionItem = ConnectionParams; +/** + * Class representing connected accounts in the system. + */ export class ConnectedAccounts { private backendClient: BackendClient; private fileName: string = "js/src/sdk/models/connectedAccounts.ts"; + /** + * Initializes a new instance of the ConnectedAccounts class. + * @param {BackendClient} backendClient - The backend client instance. + */ constructor(backendClient: BackendClient) { this.backendClient = backendClient; } + /** + * List all connected accounts + * @param {ConnectedAccountsListData} data - The data for the connected accounts list + * @returns {Promise} - A promise that resolves to a list of connected accounts + */ async list( data: ConnectedAccountsListData ): Promise { @@ -52,90 +73,129 @@ export class ConnectedAccounts { params: { data }, }); try { - const res = await apiClient.connections.listConnections({ query: data }); + const { appNames, appUniqueKeys } = ZListConnectionsData.parse(data); + const finalAppNames = appNames || appUniqueKeys?.join(","); + const res = await apiClient.connections.listConnections({ + query: { + ...data, + appNames: finalAppNames, + }, + }); return res.data!; } catch (error) { throw CEG.handleAllError(error); } } - async create(data: InitiateConnectionPayload): Promise { + /** + * Get a single connected account + * @param {SingleConnectionParam} data - The data for the single connection + * @returns {Promise} - A promise that resolves to a single connected account + */ + async get( + data: SingleConnectionParam + ): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { - method: "create", + method: "get", file: this.fileName, params: { data }, }); try { - const { data: res } = await apiClient.connections.initiateConnection({ - body: data, + ZSingleConnectionParams.parse(data); + const res = await apiClient.connections.getConnection({ + path: data, throwOnError: true, }); - - return new ConnectionRequest({ - connectionStatus: res.connectionStatus, - connectedAccountId: res.connectedAccountId, - redirectUri: res.redirectUrl ?? null, - }); + return res.data; } catch (error) { throw CEG.handleAllError(error); } } - async get( - data: SingleConnectionParam - ): Promise { + /** + * Delete a single connected account + * @param {SingleConnectionParam} data - The data for the single connection + * @returns {Promise} - A promise that resolves when the connected account is deleted + */ + async delete(data: SingleConnectionParam): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { - method: "get", + method: "delete", file: this.fileName, params: { data }, }); try { ZSingleConnectionParams.parse(data); - const res = await apiClient.connections.getConnection({ + const res = await apiClient.connections.deleteConnection({ path: data, throwOnError: true, }); - return res.data; + return res.data!; } catch (error) { throw CEG.handleAllError(error); } } - async getAuthParams(data: { connectedAccountId: string }) { + /** + * Disable a single connected account + * @param {SingleConnectionParam} data - The data for the single connection + * @returns {Promise} - A promise that resolves when the connected account is disabled + */ + async disable( + data: SingleConnectionParam + ): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { - method: "getAuthParams", + method: "disable", file: this.fileName, params: { data }, }); try { - const res = await apiClient.connections.getConnection({ - path: { connectedAccountId: data.connectedAccountId }, + ZSingleConnectionParams.parse(data); + const res = await apiClient.connections.disableConnection({ + path: data, + throwOnError: true, }); - return res.data; + return { + status: "success", + connectedAccountId: data.connectedAccountId, + }; } catch (error) { throw CEG.handleAllError(error); } } - async delete(data: SingleConnectionParam): Promise { + /** + * Enable a single connected account + * @param {SingleConnectionParam} data - The data for the single connection + * @returns {Promise} - A promise that resolves when the connected account is enabled + */ + async enable(data: SingleConnectionParam): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { - method: "delete", + method: "enable", file: this.fileName, params: { data }, }); try { ZSingleConnectionParams.parse(data); - const res = await apiClient.connections.deleteConnection({ - path: data, + await apiClient.connections.enableConnection({ + path: { + connectedAccountId: data.connectedAccountId, + }, throwOnError: true, }); - return res.data!; + return { + status: "success", + connectedAccountId: data.connectedAccountId, + }; } catch (error) { throw CEG.handleAllError(error); } } - // Should we deprecate this or change the signature? + /** + * Initiate a connection + * @param {InitiateConnectionDataReq} payload - The payload for the connection initiation + * @returns {Promise} - A promise that resolves to a connection request + */ async initiate( payload: InitiateConnectionDataReq ): Promise { @@ -181,6 +241,11 @@ export class ConnectedAccounts { } } + /** + * Reinitiate a connection + * @param {ReinitiateConnectionPayload} data - The payload for the connection reinitialization + * @returns {Promise} - A promise that resolves to a connection request + */ async reinitiateConnection(data: ReinitiateConnectionPayload) { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { method: "reinitiateConnection", @@ -254,6 +319,11 @@ export class ConnectionRequest { } } + /** + * Wait until the connection becomes active + * @param {number} timeout - The timeout for the connection to become active + * @returns {Promise} - A promise that resolves to the connection + */ async waitUntilActive(timeout = 60) { try { const startTime = Date.now(); diff --git a/js/src/sdk/models/integrations.spec.ts b/js/src/sdk/models/integrations.spec.ts index 1b35033a7e2..1bdcdb1c01e 100644 --- a/js/src/sdk/models/integrations.spec.ts +++ b/js/src/sdk/models/integrations.spec.ts @@ -50,13 +50,14 @@ describe("Integrations class tests", () => { }); it("should get the required params for the created integration", async () => { - const requiredParams = - await integrations.getRequiredParams(createdIntegrationId); + const requiredParams = await integrations.getRequiredParams({ + integrationId: createdIntegrationId, + }); expect(requiredParams).toBeDefined(); }); it("should delete the created integration", async () => { if (!createdIntegrationId) return; - await integrations.delete(createdIntegrationId); + await integrations.delete({ integrationId: createdIntegrationId }); }); }); diff --git a/js/src/sdk/models/integrations.ts b/js/src/sdk/models/integrations.ts index ce05a156887..9bfff996a23 100644 --- a/js/src/sdk/models/integrations.ts +++ b/js/src/sdk/models/integrations.ts @@ -1,4 +1,5 @@ import { z } from "zod"; + import { DeleteRowAPIDTO, ExpectedInputFieldsDTO, @@ -13,16 +14,28 @@ import { ZSingleIntegrationParams, } from "../types/integration"; import { CEG } from "../utils/error"; +import { COMPOSIO_SDK_ERROR_CODES } from "../utils/errors/src/constants"; import { TELEMETRY_LOGGER } from "../utils/telemetry"; import { TELEMETRY_EVENTS } from "../utils/telemetry/events"; import { Apps } from "./apps"; import { BackendClient } from "./backendClient"; // Types generated from zod schemas -export type IntegrationListParam = z.infer; -export type IntegrationGetParam = z.infer; -export type IntegrationListData = string; -type IntegrationCreateParams = z.infer; + +export type IntegrationGetRequiredParam = z.infer< + typeof ZSingleIntegrationParams +>; +export type IntegrationCreateParams = z.infer< + typeof ZCreateIntegrationParams +> & { + /** @deprecated use appUniqueKey field instead */ + appId?: string; +}; +export type IntegrationListParam = z.infer & { + /** @deprecated use appUniqueKeys field instead */ + appName?: string; +}; +type IntegrationDeleteParam = z.infer; // API response types export type IntegrationCreateData = { @@ -33,6 +46,7 @@ export type IntegrationListRes = GetConnectorListResDTO; export type IntegrationGetRes = GetConnectorInfoResDTO; export type IntegrationRequiredParamsRes = ExpectedInputFieldsDTO[]; export type IntegrationDeleteRes = DeleteRowAPIDTO; + export class Integrations { private backendClient: BackendClient; private fileName: string = "js/src/sdk/models/integrations.ts"; @@ -58,8 +72,12 @@ export class Integrations { params: { data }, }); try { + const { appName, appUniqueKey, ...rest } = + ZListIntegrationsParams.parse(data); + const finalAppName = + appName && appName.length > 0 ? appName : appUniqueKey; const response = await apiClient.appConnector.listAllConnectors({ - query: data, + query: { ...rest, appName: finalAppName }, throwOnError: true, }); @@ -78,7 +96,7 @@ export class Integrations { * @returns {Promise} A promise that resolves to the details of the integration. * @throws {ComposioError} If the request fails. */ - async get(data: IntegrationGetParam): Promise { + async get(data: IntegrationGetRequiredParam): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { method: "get", file: this.fileName, @@ -100,25 +118,23 @@ export class Integrations { * * This method is used to get the necessary input fields for a specific integration's authentication scheme. * - * @param {IntegrationListData} data The data for the request. + * @param {IntegrationGetParam} data The data for the request. * @returns {Promise} A promise that resolves to the required parameters for the integration's authentication scheme. * @throws {ComposioError} If the request fails. */ async getRequiredParams( - integrationId: IntegrationListData + data: IntegrationGetRequiredParam ): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { method: "getRequiredParams", file: this.fileName, - params: { integrationId }, + params: { data }, }); try { - ZSingleIntegrationParams.parse({ - integrationId, - }); + ZSingleIntegrationParams.parse(data); const response = await apiClient.appConnector.getConnectorInfo({ path: { - integrationId, + integrationId: data.integrationId, }, throwOnError: true, }); @@ -146,13 +162,27 @@ export class Integrations { try { ZCreateIntegrationParams.parse(data); - const apps = await apiClient.apps.getApps(); - const app = apps.data?.items.find((app) => app.appId === data.appId); + let uniqueKey = data.appUniqueKey; + + if (!uniqueKey) { + const apps = await apiClient.apps.getApps(); + const app = apps.data?.items.find((app) => app.appId === data.appId); + uniqueKey = app!.key; + if (!uniqueKey) { + throw CEG.getCustomError( + COMPOSIO_SDK_ERROR_CODES.COMMON.INVALID_PARAMS_PASSED, + { + message: `No app was found with the provided appId`, + description: `Please provide an app unique key`, + } + ); + } + } const response = await apiClient.appConnectorV2.createConnectorV2({ body: { app: { - uniqueKey: app!.key || "", + uniqueKey: uniqueKey, }, config: { useComposioAuth: data.useComposioAuth, @@ -183,13 +213,25 @@ export class Integrations { try { ZCreateIntegrationParams.parse(data); - const apps = await apiClient.apps.getApps(); - const app = apps.data?.items.find((app) => app.appId === data.appId); + let uniqueKey = data.appUniqueKey; + + if (!uniqueKey) { + const apps = await apiClient.apps.getApps(); + const app = apps.data?.items.find((app) => app.appId === data.appId); + uniqueKey = app!.key; + throw CEG.getCustomError( + COMPOSIO_SDK_ERROR_CODES.COMMON.INVALID_PARAMS_PASSED, + { + message: `No app was found with the provided appId`, + description: `Please provide an app unique key`, + } + ); + } const response = await apiClient.appConnectorV2.getOrCreateConnector({ body: { app: { - uniqueKey: app!.key, + uniqueKey, }, config: { useComposioAuth: data.useComposioAuth, @@ -217,21 +259,17 @@ export class Integrations { * @returns {Promise} A promise that resolves to the deleted integration model. * @throws {ComposioError} If the request fails. */ - async delete( - integrationId: IntegrationListData - ): Promise { + async delete(data: IntegrationDeleteParam): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { method: "delete", file: this.fileName, - params: { integrationId }, + params: { data }, }); try { - ZSingleIntegrationParams.parse({ - integrationId, - }); + ZSingleIntegrationParams.parse(data); const response = await apiClient.appConnector.deleteConnector({ path: { - integrationId, + integrationId: data.integrationId, }, throwOnError: true, }); diff --git a/js/src/sdk/models/triggers.spec.ts b/js/src/sdk/models/triggers.spec.ts index 3edff00f50b..3f8bbb9b108 100644 --- a/js/src/sdk/models/triggers.spec.ts +++ b/js/src/sdk/models/triggers.spec.ts @@ -101,8 +101,8 @@ describe("Apps class tests subscribe", () => { }); it("should get the payload of a trigger", async () => { - const res = await triggers.getTriggerInfo({ - triggerId: "GMAIL_NEW_GMAIL_MESSAGE", + const res = await triggers.get({ + triggerName: "GMAIL_NEW_GMAIL_MESSAGE", }); expect(res.displayName).toBe("New Gmail Message Received Trigger"); }); diff --git a/js/src/sdk/models/triggers.ts b/js/src/sdk/models/triggers.ts index 4995f2f515a..50d48e5c6c2 100644 --- a/js/src/sdk/models/triggers.ts +++ b/js/src/sdk/models/triggers.ts @@ -15,6 +15,7 @@ import { ZSingleTriggerParam, ZSingleTriggerRes, ZTriggerInstanceItems, + ZTriggerInstanceParam, ZTriggerQuery, ZTriggerSetupParam, ZTriggerSubscribeParam, @@ -22,7 +23,10 @@ import { import { COMPOSIO_SDK_ERROR_CODES } from "../utils/errors/src/constants"; // Types inferred from zod schemas -export type TriggerListParam = z.infer; +export type TriggerListParam = z.infer & { + /** @deprecated use appUniqueKeys field instead */ + appNames?: string[]; +}; export type TriggerSetupParam = z.infer; export type TriggerInstanceItems = z.infer; export type TriggerSubscribeParam = z.infer; @@ -32,11 +36,23 @@ export type TriggerSingleConfig = Pick; // API response types export type TriggerListResponse = ListTriggersResponse; + export type TriggerSetupResponse = { status: string; + + /** @deprecated use triggerId field instead */ triggerInstanceId: string; - /* Deprecated */ + triggerId: string; + + triggerName: string; +}; + +export type SingleInstanceTriggerParam = z.infer< + typeof ZTriggerInstanceParam +> & { + /** @deprecated use triggerId */ + triggerInstanceId?: string; }; export class Triggers { @@ -71,13 +87,17 @@ export class Triggers { integrationIds, showEnabledOnly, triggerInstanceIds, + appUniqueKeys, } = ZTriggerQuery.parse(data); const finalTriggerInstanceIds = triggerIds && triggerIds.length > 0 ? triggerIds : triggerInstanceIds; + + const finalAppNames = + appNames && appNames.length > 0 ? appNames : appUniqueKeys; const { data: response } = await apiClient.triggers.listTriggers({ query: { - appNames: appNames?.join(","), + appNames: finalAppNames?.join(","), triggerIds: finalTriggerInstanceIds?.join(","), connectedAccountIds: connectedAccountIds?.join(","), integrationIds: integrationIds?.join(","), @@ -99,67 +119,103 @@ export class Triggers { } /** - * Retrieves information about a single trigger. + * Retrieves the configuration of a single trigger. * * @param {TriggerSingleParam} data The data for the request. - * @returns {Promise} A promise that resolves to the trigger information. + * @returns {Promise} A promise that resolves to the trigger configuration. * @throws {ComposioError} If the request fails. */ - async getTriggerInfo(data: TriggerSingleParam): Promise { + async get(data: TriggerSingleParam): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { - method: "getTriggerInfo", + method: "get", + file: this.fileName, + params: { data }, + }); + return this.getTriggerInfo(data); + } + + /** + * @deprecated use trigger.get instead + * Retrieves the configuration of a single trigger. + * + * @param {TriggerSingleParam} data The data for the request. + * @returns {Promise} A promise that resolves to the trigger configuration. + * @throws {ComposioError} If the request fails. + */ + async getTriggerConfig( + data: TriggerSingleParam + ): Promise { + TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { + method: "getSingleTriggerConfig", file: this.fileName, params: { data }, }); try { const parsedData = ZSingleTriggerParam.parse(data); + + if (!parsedData.triggerName && !parsedData.triggerId) { + throw CEG.getCustomError( + COMPOSIO_SDK_ERROR_CODES.COMMON.INVALID_PARAMS_PASSED, + { + message: "Trigger name or trigger id is required", + description: "Trigger name or trigger id is required", + possibleFix: "Pass either triggerName or triggerId", + } + ); + } const res = await apiClient.triggers.getTriggerInfoV2({ - path: { triggerName: parsedData.triggerId }, + path: { + triggerName: parsedData.triggerName || parsedData.triggerId || "", + }, }); // Bad type inference - const trigger = res.data as unknown as SingleTriggerRes; - if (!trigger) { + const triggerInfo = res.data as unknown as SingleTriggerRes; + + if (!triggerInfo) { throw CEG.getCustomError(COMPOSIO_SDK_ERROR_CODES.BACKEND.NOT_FOUND, { message: "Trigger info not found", description: "Trigger info not found", possibleFix: "Pass a check if trigger exists", }); } - return trigger; + return { config: triggerInfo.config } as TriggerSingleConfig; } catch (error) { throw CEG.handleAllError(error); } } /** - * Retrieves the configuration of a single trigger. + * Retrieves information about a single trigger. * * @param {TriggerSingleParam} data The data for the request. - * @returns {Promise} A promise that resolves to the trigger configuration. + * @returns {Promise} A promise that resolves to the trigger information. * @throws {ComposioError} If the request fails. */ - async getTriggerConfig( - data: TriggerSingleParam - ): Promise { + async getTriggerInfo(data: TriggerSingleParam): Promise { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { - method: "getSingleTriggerConfig", + method: "getTriggerInfo", file: this.fileName, params: { data }, }); try { const parsedData = ZSingleTriggerParam.parse(data); + const res = await apiClient.triggers.getTriggerInfoV2({ + path: { + triggerName: parsedData.triggerName || parsedData.triggerId || "", + }, + }); - const triggerInfo = await this.getTriggerInfo(parsedData); - - if (!triggerInfo) { + // Bad type inference + const trigger = res.data as unknown as SingleTriggerRes; + if (!trigger) { throw CEG.getCustomError(COMPOSIO_SDK_ERROR_CODES.BACKEND.NOT_FOUND, { message: "Trigger info not found", description: "Trigger info not found", possibleFix: "Pass a check if trigger exists", }); } - return { config: triggerInfo.config } as TriggerSingleConfig; + return trigger; } catch (error) { throw CEG.handleAllError(error); } @@ -193,6 +249,7 @@ export class Triggers { const { triggerId, status } = response.data; return { triggerId: triggerId!, + triggerName: parsedData.triggerName, status, triggerInstanceId: triggerId!, }; @@ -208,20 +265,14 @@ export class Triggers { * @returns {Promise} A promise that resolves to the response of the enable request. * @throws {ComposioError} If the request fails. */ - async enable({ - triggerId, - triggerInstanceId, - }: { - triggerId?: string; - triggerInstanceId?: string; - }) { + async enable(data: SingleInstanceTriggerParam) { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { method: "enable", file: this.fileName, - params: { triggerId }, + params: { data }, }); try { - const finalTriggerId = triggerId || triggerInstanceId; + const finalTriggerId = data.triggerId || data.triggerInstanceId; if (!finalTriggerId) { throw CEG.getCustomError( COMPOSIO_SDK_ERROR_CODES.COMMON.INVALID_PARAMS_PASSED, @@ -255,20 +306,14 @@ export class Triggers { * @returns {Promise} A promise that resolves to the response of the disable request. * @throws {ComposioError} If the request fails. */ - async disable({ - triggerId, - triggerInstanceId, - }: { - triggerId?: string; - triggerInstanceId?: string; - }) { + async disable(data: SingleInstanceTriggerParam) { TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, { method: "disable", file: this.fileName, - params: { triggerId, triggerInstanceId }, + params: { data }, }); try { - const finalTriggerId = triggerId || triggerInstanceId; + const finalTriggerId = data.triggerId || data.triggerInstanceId; if (!finalTriggerId) { throw CEG.getCustomError( COMPOSIO_SDK_ERROR_CODES.COMMON.INVALID_PARAMS_PASSED, diff --git a/js/src/sdk/types/connectedAccount.ts b/js/src/sdk/types/connectedAccount.ts index 5ada388db17..334588562f3 100644 --- a/js/src/sdk/types/connectedAccount.ts +++ b/js/src/sdk/types/connectedAccount.ts @@ -5,6 +5,7 @@ export const ZConnectionStatus = z.enum(["INITIATED", "ACTIVE", "FAILED"]); export const ZListConnectionsData = z.object({ appNames: z.string().optional(), + appUniqueKeys: z.string().array().optional(), connectionId: z.string().optional(), entityId: z.string().optional(), integrationId: z.string().optional(), diff --git a/js/src/sdk/types/integration.ts b/js/src/sdk/types/integration.ts index ac7df5dfacb..7cec7674dc6 100644 --- a/js/src/sdk/types/integration.ts +++ b/js/src/sdk/types/integration.ts @@ -16,7 +16,8 @@ export const ZAuthMode = z.enum([ export const ZCreateIntegrationParams = z.object({ name: z.string(), authScheme: ZAuthMode.optional(), - appId: z.string(), + appUniqueKey: z.string().optional(), + appId: z.string().optional(), forceNewIntegration: z.boolean().optional(), authConfig: z .union([ @@ -42,5 +43,6 @@ export const ZListIntegrationsParams = z.object({ page: z.number().optional(), pageSize: z.number().optional(), appName: z.string().optional(), + appUniqueKey: z.string().optional(), showDisabled: z.boolean().optional(), }); diff --git a/js/src/sdk/types/trigger.ts b/js/src/sdk/types/trigger.ts index 8d6cfb5b522..86bd8f308d2 100644 --- a/js/src/sdk/types/trigger.ts +++ b/js/src/sdk/types/trigger.ts @@ -7,6 +7,7 @@ export const ZTriggerQuery = z.object({ .optional() .describe("Trigger Instance IDs"), appNames: z.array(z.string()).optional().describe("App Names in lowercase"), + appUniqueKeys: z.array(z.string()).optional().describe("App Unique Keys"), connectedAccountIds: z .array(z.string()) .optional() @@ -42,10 +43,20 @@ export const ZTriggerSubscribeParam = z.object({ }); export const ZSingleTriggerParam = z.object({ - triggerId: z.string(), + triggerId: z.string().optional(), + triggerName: z.string().optional(), +}); + +export const ZTriggerInstanceParam = z.object({ + triggerInstanceId: z.string().optional(), + triggerId: z.string().optional(), }); -export type TriggerSingleParam = z.infer; +export type TriggerSingleParam = z.infer & { + triggerName?: string; + /** @deprecated use triggerName field instead */ + triggerId?: string; +}; export const ZSingleTriggerRes = z.object({ name: z.string(), diff --git a/js/src/sdk/utils/config.ts b/js/src/sdk/utils/config.ts index 485590ee5b9..33b42775048 100644 --- a/js/src/sdk/utils/config.ts +++ b/js/src/sdk/utils/config.ts @@ -52,6 +52,7 @@ export const setAxiosClientConfig = (axiosClientInstance: AxiosInstance) => { `API Req [${request.method?.toUpperCase()}] ${request.url}, x-request-id: ${request.headers["x-request-id"]}`, { ...(body && { body }), + query: request.params, } ); request.metadata = { startTime: Date.now() }; From bd7906e22f6f30324d5d3eaa8c4cd471e5cc7bcf Mon Sep 17 00:00:00 2001 From: Karan Vaidya Date: Mon, 20 Jan 2025 12:24:13 +0530 Subject: [PATCH 30/34] fix: allow auto reconnection in pusher client (#1199) --- python/composio/client/collections.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/composio/client/collections.py b/python/composio/client/collections.py index 37cab4c7f0e..5f0c7db907f 100644 --- a/python/composio/client/collections.py +++ b/python/composio/client/collections.py @@ -831,6 +831,7 @@ def connect(self, timeout: float = 15.0) -> TriggerSubscription: "x-api-key": self.api_key, "x-request-id": generate_request_id(), }, + auto_sub=True, ) # Patch pusher logger From 058121e542d720e7a9a5260f8659f8bf36a2ba6f Mon Sep 17 00:00:00 2001 From: Karan Vaidya Date: Mon, 20 Jan 2025 12:25:34 +0530 Subject: [PATCH 31/34] fix: filter connections by entity [ENG-2523] (#1200) --- python/composio/tools/toolset.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/composio/tools/toolset.py b/python/composio/tools/toolset.py index 6ed7b1f929d..326f403898e 100644 --- a/python/composio/tools/toolset.py +++ b/python/composio/tools/toolset.py @@ -1360,7 +1360,9 @@ def get_connected_account(self, id: str) -> ConnectedAccountModel: return self.client.connected_accounts.get(connection_id=id) def get_connected_accounts(self) -> t.List[ConnectedAccountModel]: - return self.client.connected_accounts.get() + return self.client.connected_accounts.get( + entity_ids=[self.entity_id] if self.entity_id else None + ) def get_entity(self, id: t.Optional[str] = None) -> Entity: """Get entity object for given ID.""" From b08fcd1e978a7a5841d0469b556e1c97e4e4eb71 Mon Sep 17 00:00:00 2001 From: Viraj <35092918+angrybayblade@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:09:05 +0530 Subject: [PATCH 32/34] fix: session ID delegation (#1212) --- python/composio/client/collections.py | 3 +++ python/composio/client/http.py | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/python/composio/client/collections.py b/python/composio/client/collections.py index 5f0c7db907f..e3ab3dd9b81 100644 --- a/python/composio/client/collections.py +++ b/python/composio/client/collections.py @@ -1320,6 +1320,9 @@ def execute( "input": modified_params, "text": text, "authConfig": self._serialize_auth(auth=auth), + "sessionInfo": { + "sessionId": session_id, + }, }, ) ).json() diff --git a/python/composio/client/http.py b/python/composio/client/http.py index 08d34b0f4ab..d1d18a762a6 100644 --- a/python/composio/client/http.py +++ b/python/composio/client/http.py @@ -53,8 +53,9 @@ def _wrap(self, method: t.Callable) -> t.Callable: def request(url: str, **kwargs: t.Any) -> t.Any: """Perform HTTP request.""" + rid = generate_request_id() self._logger.debug( - f"{method.__name__.upper()} {self.base_url}{url} - {kwargs}" + f"[{rid}] {method.__name__.upper()} {self.base_url}{url} - {kwargs}" ) retries = 0 while retries < 3: @@ -64,7 +65,7 @@ def request(url: str, **kwargs: t.Any) -> t.Any: timeout=self.timeout, headers={ **kwargs.pop("headers", {}), - "x-request-id": generate_request_id(), + "x-request-id": rid, }, **kwargs, ) From a08dfe4309f906c277380d4ace844edcab5a068f Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Mon, 3 Feb 2025 15:22:07 +0530 Subject: [PATCH 33/34] fix: replaced hardcoded acc id to dynamic in llamaindex.spec.ts --- js/src/frameworks/llamaindex.spec.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/js/src/frameworks/llamaindex.spec.ts b/js/src/frameworks/llamaindex.spec.ts index 6fa3c8bf32c..ac3df39b479 100644 --- a/js/src/frameworks/llamaindex.spec.ts +++ b/js/src/frameworks/llamaindex.spec.ts @@ -60,6 +60,12 @@ describe("Apps class tests", () => { }); await expect(tools.length).toBe(1); + + const connectedAccount = await llamaindexToolSet.connectedAccounts.list({ + appNames: "github", + showActiveOnly: true, + }); + const actionOuput = await llamaindexToolSet.executeAction({ action: "starRepositoryCustomAction", params: { @@ -67,7 +73,7 @@ describe("Apps class tests", () => { repo: "composio", }, entityId: "default", - connectedAccountId: "9442cab3-d54f-4903-976c-ee67ef506c9b", + connectedAccountId: connectedAccount.items[0].id, }); expect(actionOuput).toHaveProperty("successful", true); From 45efb712ce6be47dc878b165ccf443f62424ce3b Mon Sep 17 00:00:00 2001 From: abhishekpatil4 Date: Mon, 3 Feb 2025 15:45:39 +0530 Subject: [PATCH 34/34] fix: add llamaindex/core --- js/package.json | 9 ++++++--- js/pnpm-lock.yaml | 14 +++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/js/package.json b/js/package.json index 1f60ff4c60e..df93544a0b7 100644 --- a/js/package.json +++ b/js/package.json @@ -38,6 +38,7 @@ "@cloudflare/workers-types": "^4.20240718.0", "@langchain/core": "^0.2.18", "@langchain/openai": "^0.2.5", + "@llamaindex/core": "^0.4.20", "ai": "^3.2.22", "langchain": "^0.2.11", "llamaindex": "^0.8.31", @@ -51,11 +52,11 @@ "inquirer": "^10.2.2", "open": "^8.4.0", "pusher-js": "8.4.0-rc2", + "resolve-package-path": "^4.0.0", "rollup-plugin-visualizer": "^5.13.1", "uuid": "^10.0.0", "zod": "^3.23.8", - "zod-to-json-schema": "^3.23.2", - "resolve-package-path": "^4.0.0" + "zod-to-json-schema": "^3.23.2" }, "devDependencies": { "@eslint/js": "^9.16.0", @@ -63,6 +64,7 @@ "@hey-api/client-axios": "^0.2.3", "@hey-api/openapi-ts": "^0.52.4", "@jest/globals": "^29.7.0", + "@llamaindex/core": "^0.4.20", "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", @@ -105,5 +107,6 @@ "engineStrict": true, "engines": { "node": ">=18.0.0" - } + }, + "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" } diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 7cb38b9cd9a..14ec91d164a 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: '@jest/globals': specifier: ^29.7.0 version: 29.7.0 + '@llamaindex/core': + specifier: ^0.4.20 + version: 0.4.20(@aws-crypto/sha256-js@5.2.0)(@huggingface/transformers@3.3.1)(gpt-tokenizer@2.8.1)(js-tiktoken@1.0.16)(pathe@1.1.2) '@rollup/plugin-commonjs': specifier: ^25.0.8 version: 25.0.8(rollup@4.28.1) @@ -4070,10 +4073,6 @@ packages: encoding: optional: true - node-gyp-build@4.8.1: - resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} - hasBin: true - node-gyp-build@4.8.4: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true @@ -8362,7 +8361,7 @@ snapshots: bufferutil@4.0.8: dependencies: - node-gyp-build: 4.8.1 + node-gyp-build: 4.8.4 optional: true c12@1.11.1: @@ -10264,9 +10263,6 @@ snapshots: dependencies: whatwg-url: 5.0.0 - node-gyp-build@4.8.1: - optional: true - node-gyp-build@4.8.4: {} node-int64@0.4.0: {} @@ -11414,7 +11410,7 @@ snapshots: utf-8-validate@6.0.4: dependencies: - node-gyp-build: 4.8.1 + node-gyp-build: 4.8.4 optional: true util-deprecate@1.0.2: {}