diff --git a/plugins/composio-direct/GUIDE.md b/plugins/composio-direct/GUIDE.md index 5e458dd..3ebf499 100644 --- a/plugins/composio-direct/GUIDE.md +++ b/plugins/composio-direct/GUIDE.md @@ -1,6 +1,6 @@ # Composio Direct Agent Guide -Use `composio-direct` when a user asks Teleton to work with an external app supported by Composio, such as GitHub, Gmail, Slack, Notion, Linear, Jira, Google Calendar, Google Drive, or a remote shell/workbench. The plugin talks directly to Composio v3 and exposes Composio tool slugs through Teleton tools. A returned Composio `tool_slug` is not a Teleton tool name; execute it through `composio_execute_tool` or `composio_multi_execute`. +Use `composio-direct` when a user asks Teleton to work with an external app supported by Composio, such as GitHub, Gmail, Slack, Notion, Linear, Jira, Google Calendar, Google Drive, or a remote shell/workbench. The plugin talks directly to Composio v3.1 and exposes Composio tool slugs through Teleton tools. A returned Composio `tool_slug` is not a Teleton tool name; execute it through `composio_execute_tool` or `composio_multi_execute`. ## Required Setup @@ -10,7 +10,7 @@ Default runtime settings: | Setting | Default | Use | |---|---:|---| -| `base_url` | `https://backend.composio.dev/api/v3` | Composio API endpoint | +| `base_url` | `https://backend.composio.dev/api/v3.1` | Composio API endpoint | | `timeout_ms` | `30000` | Default request timeout | | `max_parallel_executions` | `10` | Batch execution concurrency | | `tool_version` | `latest` | Tool execution/schema version | @@ -97,7 +97,7 @@ Rules for execution: - Use exact schema field names from `composio_get_tool_schemas`. - Include `connected_account_id` when the user has multiple accounts or when a connection lookup returned a clear match. - Use `timeout_override_ms` only for operations expected to exceed the plugin default. -- When a slug fails because a legacy `/api/v3.1` base URL reports an unknown tool, the plugin retries against current `/api/v3` automatically. +- When a slug fails because a legacy `/api/v3` base URL reports an unknown tool, the plugin retries against current `/api/v3.1` automatically. If an explicitly configured `/api/v3.1` route reports the same transitional error, the plugin also retries the paired `/api/v3` route. ## Batch Execution diff --git a/plugins/composio-direct/README.md b/plugins/composio-direct/README.md index ee0e51e..123bcca 100644 --- a/plugins/composio-direct/README.md +++ b/plugins/composio-direct/README.md @@ -7,7 +7,7 @@ Direct integration with **1000+ Composio automation tools** — no MCP transport - **27 focused tools** covering discovery, schema lookup, execution, batch execution, OAuth authorization, connection reuse, toolkits, files, triggers, webhooks, and meta-tools - **Retry logic** — 3 attempts with exponential backoff (1 s, 2 s, 4 s) for network and 5xx errors - **Auth error handling** — returns structured `connect_url` when a service needs authorization -- **Schema lookup** — retrieves exact input/output schemas from the v3 `tools/{tool_slug}` API +- **Schema lookup** — retrieves exact input/output schemas from the v3.1 `tools/{tool_slug}` API - **Connection management** — lists and fetches existing connected accounts so the agent can reuse them - **Toolkit discovery** — lists all Composio applications and fetches versioned toolkit metadata - **Files API** — lists registered files and requests presigned upload URLs for file-bearing tools @@ -31,7 +31,7 @@ For container and CI deployments, Teleton also resolves the secret from `COMPOSI # config.yaml example plugins: composio_direct: - base_url: "https://backend.composio.dev/api/v3" # optional + base_url: "https://backend.composio.dev/api/v3.1" # optional timeout_ms: 30000 # optional (default: 30s) max_parallel_executions: 10 # optional (default: 10) tool_version: "latest" # optional @@ -271,10 +271,10 @@ For normal reuse, prefer `composio_list_connections` first. Use this wrapper whe `composio_list_toolkits` lists available Composio toolkits/applications with auth schemes, categories, tool counts, and trigger counts. `composio_get_toolkit` fetches one toolkit by slug. -| Tool | Required parameters | v3 endpoint | +| Tool | Required parameters | v3.1 endpoint | |---|---|---| -| `composio_list_toolkits` | none | `GET /api/v3/toolkits` | -| `composio_get_toolkit` | `toolkit` | `GET /api/v3/toolkits/{slug}` | +| `composio_list_toolkits` | none | `GET /api/v3.1/toolkits` | +| `composio_get_toolkit` | `toolkit` | `GET /api/v3.1/toolkits/{slug}` | **Example:** ```json @@ -303,10 +303,10 @@ For normal reuse, prefer `composio_list_connections` first. Use this wrapper whe Use `composio_list_files` to inspect registered files and `composio_request_file_upload` to request a presigned upload URL before passing a file to a Composio tool. -| Tool | Required parameters | v3 endpoint | +| Tool | Required parameters | v3.1 endpoint | |---|---|---| -| `composio_list_files` | none | `GET /api/v3/files/list` | -| `composio_request_file_upload` | `toolkit`, `tool_slug`, `filename`, `mimetype`, `md5` | `POST /api/v3/files/upload/request` | +| `composio_list_files` | none | `GET /api/v3.1/files/list` | +| `composio_request_file_upload` | `toolkit`, `tool_slug`, `filename`, `mimetype`, `md5` | `POST /api/v3.1/files/upload/request` | **Upload request example:** ```json @@ -325,14 +325,14 @@ Use `composio_list_files` to inspect registered files and `composio_request_file Triggers let the Teleton Agent discover event schemas and manage user-scoped automation instances. -| Tool | Required parameters | v3 endpoint | +| Tool | Required parameters | v3.1 endpoint | |---|---|---| -| `composio_list_trigger_types` | none | `GET /api/v3/triggers_types` | -| `composio_get_trigger_type` | `trigger_slug` | `GET /api/v3/triggers_types/{slug}` | -| `composio_list_triggers` | none | `GET /api/v3/trigger_instances/active` | -| `composio_upsert_trigger` | `trigger_slug`, `connected_account_id`, `trigger_config` | `POST /api/v3/trigger_instances/{slug}/upsert` | -| `composio_set_trigger_status` | `trigger_id`, `status` or `enabled` | `PATCH /api/v3/trigger_instances/manage/{trigger_id}` | -| `composio_delete_trigger` | `trigger_id` | `DELETE /api/v3/trigger_instances/manage/{trigger_id}` | +| `composio_list_trigger_types` | none | `GET /api/v3.1/triggers_types` | +| `composio_get_trigger_type` | `trigger_slug` | `GET /api/v3.1/triggers_types/{slug}` | +| `composio_list_triggers` | none | `GET /api/v3.1/trigger_instances/active` | +| `composio_upsert_trigger` | `trigger_slug`, `connected_account_id`, `trigger_config` | `POST /api/v3.1/trigger_instances/{slug}/upsert` | +| `composio_set_trigger_status` | `trigger_id`, `status` or `enabled` | `PATCH /api/v3.1/trigger_instances/manage/{trigger_id}` | +| `composio_delete_trigger` | `trigger_id` | `DELETE /api/v3.1/trigger_instances/manage/{trigger_id}` | `composio_list_triggers` defaults to the current Teleton sender ID. Trigger `state` values are not returned; the response exposes only `state_keys`. @@ -342,15 +342,15 @@ Triggers let the Teleton Agent discover event schemas and manage user-scoped aut Webhooks configure Composio event delivery for triggers and other platform events. -| Tool | Required parameters | v3 endpoint | +| Tool | Required parameters | v3.1 endpoint | |---|---|---| -| `composio_list_webhook_events` | none | `GET /api/v3/webhook_subscriptions/event_types` | -| `composio_list_webhooks` | none | `GET /api/v3/webhook_subscriptions` | -| `composio_get_webhook` | `webhook_id` | `GET /api/v3/webhook_subscriptions/{id}` | -| `composio_create_webhook` | `webhook_url`, `enabled_events` | `POST /api/v3/webhook_subscriptions` | -| `composio_update_webhook` | `webhook_id` plus field to update | `PATCH /api/v3/webhook_subscriptions/{id}` | -| `composio_rotate_webhook_secret` | `webhook_id` | `POST /api/v3/webhook_subscriptions/{id}/rotate_secret` | -| `composio_delete_webhook` | `webhook_id` | `DELETE /api/v3/webhook_subscriptions/{id}` | +| `composio_list_webhook_events` | none | `GET /api/v3.1/webhook_subscriptions/event_types` | +| `composio_list_webhooks` | none | `GET /api/v3.1/webhook_subscriptions` | +| `composio_get_webhook` | `webhook_id` | `GET /api/v3.1/webhook_subscriptions/{id}` | +| `composio_create_webhook` | `webhook_url`, `enabled_events` | `POST /api/v3.1/webhook_subscriptions` | +| `composio_update_webhook` | `webhook_id` plus field to update | `PATCH /api/v3.1/webhook_subscriptions/{id}` | +| `composio_rotate_webhook_secret` | `webhook_id` | `POST /api/v3.1/webhook_subscriptions/{id}/rotate_secret` | +| `composio_delete_webhook` | `webhook_id` | `DELETE /api/v3.1/webhook_subscriptions/{id}` | Webhook signing secrets are redacted by default. Set `include_secret: true` only when the caller needs the newly generated or rotated secret value. @@ -358,7 +358,7 @@ Webhook signing secrets are redacted by default. Set `include_secret: true` only ### Remote meta-tools -`composio_remote_bash` and `composio_remote_workbench` are wrappers around documented Composio meta-tools and route through the same `POST /api/v3/tools/execute/{tool_slug}` path as normal tool execution. +`composio_remote_bash` and `composio_remote_workbench` are wrappers around documented Composio meta-tools and route through the same `POST /api/v3.1/tools/execute/{tool_slug}` path as normal tool execution. | Tool | Required parameters | Executed Composio slug | |---|---|---| @@ -372,7 +372,7 @@ Webhook signing secrets are redacted by default. Set `include_secret: true` only Get an OAuth authorization link for a service. -The tool creates a real Composio Connect Link through the v3 `auth_configs` +The tool creates a real Composio Connect Link through the v3.1 `auth_configs` and `connected_accounts/link` APIs. For toolkits without Composio-managed auth, create an auth config in Composio and pass its ID as `auth_config_id`. @@ -460,13 +460,13 @@ node --test plugins/composio-direct/test/unit/composio-direct.test.js \ - All Composio API calls use HTTPS - Side-effecting tools are scoped to `dm-only` to prevent accidental side-effects in group chats -## API v3 audit notes +## API v3.1 audit notes -- Existing compliant routes kept: `GET /api/v3/tools`, `POST /api/v3/tools/execute/{tool_slug}`, `GET/POST /api/v3/auth_configs`, and `POST /api/v3/connected_accounts/link`. -- Added missing schema access through `GET /api/v3/tools/{tool_slug}` so the agent can validate parameters before execution. -- Added missing connected account reads through `GET /api/v3/connected_accounts` and `GET /api/v3/connected_accounts/{nanoid}` so active connections can be reused instead of starting unnecessary auth flows. -- Added toolkit coverage through `GET /api/v3/toolkits` and `GET /api/v3/toolkits/{slug}` so the agent can discover all available applications from the Composio catalog. -- Added Files API coverage through `GET /api/v3/files/list` and `POST /api/v3/files/upload/request` for file-bearing tool workflows. +- Current compliant routes use `GET /api/v3.1/tools`, `POST /api/v3.1/tools/execute/{tool_slug}`, `GET/POST /api/v3.1/auth_configs`, and `POST /api/v3.1/connected_accounts/link`. +- Added missing schema access through `GET /api/v3.1/tools/{tool_slug}` so the agent can validate parameters before execution. +- Added missing connected account reads through `GET /api/v3.1/connected_accounts` and `GET /api/v3.1/connected_accounts/{nanoid}` so active connections can be reused instead of starting unnecessary auth flows. +- Added toolkit coverage through `GET /api/v3.1/toolkits` and `GET /api/v3.1/toolkits/{slug}` so the agent can discover all available applications from the Composio catalog. +- Added Files API coverage through `GET /api/v3.1/files/list` and `POST /api/v3.1/files/upload/request` for file-bearing tool workflows. - Added Triggers API coverage through trigger type discovery, active trigger listing, trigger upsert, enable/disable, and delete endpoints. - Added Webhooks API coverage through event type discovery and webhook subscription CRUD/secret rotation endpoints. - Meta-tool alignment: `composio_search_tools`, `composio_get_tool_schemas`, `composio_multi_execute`, connection/auth tools, `composio_manage_connections`, `composio_remote_bash`, and `composio_remote_workbench` cover the practical `search_tools`, `get_tool_schemas`, `multi_execute_tool`, `manage_connections`, `remote_bash_tool`, and `remote_workbench` flows for Teleton. diff --git a/plugins/composio-direct/index.js b/plugins/composio-direct/index.js index dd0954e..7ef3084 100644 --- a/plugins/composio-direct/index.js +++ b/plugins/composio-direct/index.js @@ -23,7 +23,7 @@ * - Set COMPOSIO_DIRECT_COMPOSIO_API_KEY, COMPOSIO_API_KEY, or use the secrets store * * Transport: - * - Talks directly to the Composio v3 REST API over HTTPS + * - Talks directly to the Composio v3.1 REST API over HTTPS * - Self-contained: no npm dependencies, so there is no install step to fail * * Security: @@ -38,13 +38,13 @@ */ // --------------------------------------------------------------------------- -// Composio v3 API constants. +// Composio v3.1 API constants. // This plugin talks to Composio over direct HTTPS calls (no npm dependency), // which keeps it self-contained and avoids any runtime install step that could // fail (for example "spawn npm ENOENT" when npm is not on PATH). // --------------------------------------------------------------------------- -const DEFAULT_BASE_URL = "https://backend.composio.dev/api/v3"; +const DEFAULT_BASE_URL = "https://backend.composio.dev/api/v3.1"; const DEFAULT_TOOL_VERSION = "latest"; const DEFAULT_TOOLKIT_VERSIONS = "latest"; const COMPOSIO_MANAGED_AUTH_UNAVAILABLE_PATTERN = @@ -64,10 +64,10 @@ const COMPOSIO_EXECUTION_GUIDANCE = { export const manifest = { name: "composio-direct", - version: "1.9.0", + version: "1.9.1", sdkVersion: ">=1.0.0", description: - "Direct access to 1000+ Composio automation tools plus v3 toolkits, files, triggers, webhooks, connection reuse, and meta-tools without MCP transport", + "Direct access to 1000+ Composio automation tools plus v3.1 toolkits, files, triggers, webhooks, connection reuse, and meta-tools without MCP transport", secrets: { composio_api_key: { required: true, @@ -725,12 +725,16 @@ function isUnknownToolError(response) { } /** - * Current Composio docs use /api/v3. Retry the current route when a user still - * has the old v3.1 base URL configured and that route reports an unknown tool. + * Composio currently documents /api/v3.1. Retry the paired route when an + * explicit /api/v3 or /api/v3.1 configuration reports an unknown tool, so + * older deployments keep working during API-version transitions. * @param {string} baseUrl * @returns {string | null} */ -function getCurrentV3FallbackBaseUrl(baseUrl) { +function getComposioApiFallbackBaseUrl(baseUrl) { + if (/\/api\/v3$/i.test(baseUrl)) { + return baseUrl.replace(/\/api\/v3$/i, "/api/v3.1"); + } if (/\/api\/v3\.1$/i.test(baseUrl)) { return baseUrl.replace(/\/api\/v3\.1$/i, "/api/v3"); } @@ -805,7 +809,7 @@ export const tools = (sdk) => { } /** - * Execute a Composio v3 HTTP request using the plugin defaults. + * Execute a Composio v3.1 HTTP request using the plugin defaults. * @param {object} opts * @param {string} opts.apiKey * @param {string} opts.path @@ -1275,10 +1279,10 @@ export const tools = (sdk) => { timeoutMs: effectiveTimeout, log: sdk.log, }); - const fallbackBaseUrl = getCurrentV3FallbackBaseUrl(baseUrl); + const fallbackBaseUrl = getComposioApiFallbackBaseUrl(baseUrl); if (fallbackBaseUrl && isUnknownToolError(response)) { url = `${fallbackBaseUrl}/tools/execute/${encodeURIComponent(normalizedSlug)}`; - sdk.log.debug(`composio_execute_tool: retrying ${normalizedSlug} on current v3 API`); + sdk.log.debug(`composio_execute_tool: retrying ${normalizedSlug} on paired Composio API route`); response = await fetchWithRetry({ url, method: "POST", @@ -1472,10 +1476,10 @@ export const tools = (sdk) => { timeoutMs: effectiveTimeout, log: sdk.log, }); - const fallbackBaseUrl = getCurrentV3FallbackBaseUrl(baseUrl); + const fallbackBaseUrl = getComposioApiFallbackBaseUrl(baseUrl); if (fallbackBaseUrl && isUnknownToolError(response)) { url = `${fallbackBaseUrl}/tools/execute/${encodeURIComponent(normalizedSlug)}`; - sdk.log.debug(`composio_multi_execute: retrying ${normalizedSlug} on current v3 API`); + sdk.log.debug(`composio_multi_execute: retrying ${normalizedSlug} on paired Composio API route`); response = await fetchWithRetry({ url, method: "POST", @@ -1940,7 +1944,7 @@ export const tools = (sdk) => { const composioListToolkits = { name: "composio_list_toolkits", description: - "List Composio v3 toolkits so the agent can discover available applications, auth modes, tool counts, trigger support, and categories.", + "List Composio v3.1 toolkits so the agent can discover available applications, auth modes, tool counts, trigger support, and categories.", category: "data-bearing", parameters: { @@ -2030,7 +2034,7 @@ export const tools = (sdk) => { const composioGetToolkit = { name: "composio_get_toolkit", description: - "Get detailed Composio v3 toolkit metadata by toolkit slug, including auth details and versioned capability metadata.", + "Get detailed Composio v3.1 toolkit metadata by toolkit slug, including auth details and versioned capability metadata.", category: "data-bearing", parameters: { @@ -2092,7 +2096,7 @@ export const tools = (sdk) => { const composioListFiles = { name: "composio_list_files", description: - "List files registered with Composio's v3 Files API for a toolkit/tool pair. Use before reusing uploaded files in tool parameters.", + "List files registered with Composio's v3.1 Files API for a toolkit/tool pair. Use before reusing uploaded files in tool parameters.", category: "data-bearing", parameters: { @@ -2157,7 +2161,7 @@ export const tools = (sdk) => { const composioRequestFileUpload = { name: "composio_request_file_upload", description: - "Request a Composio v3 Files API presigned upload URL for a file that will be passed to a Composio tool.", + "Request a Composio v3.1 Files API presigned upload URL for a file that will be passed to a Composio tool.", category: "action", scope: "dm-only", @@ -2249,7 +2253,7 @@ export const tools = (sdk) => { const composioListTriggerTypes = { name: "composio_list_trigger_types", description: - "List Composio v3 trigger type schemas by toolkit so the agent can configure automation triggers.", + "List Composio v3.1 trigger type schemas by toolkit so the agent can configure automation triggers.", category: "data-bearing", parameters: { @@ -2326,7 +2330,7 @@ export const tools = (sdk) => { const composioGetTriggerType = { name: "composio_get_trigger_type", description: - "Get one Composio v3 trigger type schema by trigger slug before creating or updating a trigger instance.", + "Get one Composio v3.1 trigger type schema by trigger slug before creating or updating a trigger instance.", category: "data-bearing", parameters: { @@ -2506,7 +2510,7 @@ export const tools = (sdk) => { const composioUpsertTrigger = { name: "composio_upsert_trigger", description: - "Create or update a Composio v3 trigger instance for a connected account using a trigger type slug and config.", + "Create or update a Composio v3.1 trigger instance for a connected account using a trigger type slug and config.", category: "action", scope: "dm-only", @@ -2586,7 +2590,7 @@ export const tools = (sdk) => { const composioSetTriggerStatus = { name: "composio_set_trigger_status", description: - "Enable or disable a Composio v3 trigger instance through the trigger manage endpoint.", + "Enable or disable a Composio v3.1 trigger instance through the trigger manage endpoint.", category: "action", scope: "dm-only", @@ -2655,7 +2659,7 @@ export const tools = (sdk) => { const composioDeleteTrigger = { name: "composio_delete_trigger", - description: "Delete a Composio v3 trigger instance by trigger ID.", + description: "Delete a Composio v3.1 trigger instance by trigger ID.", category: "action", scope: "dm-only", @@ -2708,7 +2712,7 @@ export const tools = (sdk) => { const composioListWebhookEvents = { name: "composio_list_webhook_events", description: - "List event types supported by Composio v3 webhook subscriptions.", + "List event types supported by Composio v3.1 webhook subscriptions.", category: "data-bearing", parameters: { @@ -2750,7 +2754,7 @@ export const tools = (sdk) => { const composioListWebhooks = { name: "composio_list_webhooks", description: - "List Composio v3 webhook subscriptions. Webhook signing secrets are redacted unless include_secret is true.", + "List Composio v3.1 webhook subscriptions. Webhook signing secrets are redacted unless include_secret is true.", category: "data-bearing", parameters: { @@ -2815,7 +2819,7 @@ export const tools = (sdk) => { const composioGetWebhook = { name: "composio_get_webhook", description: - "Get one Composio v3 webhook subscription by ID. Webhook signing secrets are redacted unless include_secret is true.", + "Get one Composio v3.1 webhook subscription by ID. Webhook signing secrets are redacted unless include_secret is true.", category: "data-bearing", parameters: { @@ -2868,7 +2872,7 @@ export const tools = (sdk) => { const composioCreateWebhook = { name: "composio_create_webhook", description: - "Create a Composio v3 webhook subscription for Teleton Agent automation callbacks.", + "Create a Composio v3.1 webhook subscription for Teleton Agent automation callbacks.", category: "action", scope: "dm-only", @@ -2944,7 +2948,7 @@ export const tools = (sdk) => { const composioUpdateWebhook = { name: "composio_update_webhook", description: - "Update a Composio v3 webhook subscription URL, enabled events, or version.", + "Update a Composio v3.1 webhook subscription URL, enabled events, or version.", category: "action", scope: "dm-only", @@ -3029,7 +3033,7 @@ export const tools = (sdk) => { const composioRotateWebhookSecret = { name: "composio_rotate_webhook_secret", description: - "Rotate a Composio v3 webhook subscription signing secret. The new secret is redacted unless include_secret is true.", + "Rotate a Composio v3.1 webhook subscription signing secret. The new secret is redacted unless include_secret is true.", category: "action", scope: "dm-only", @@ -3083,7 +3087,7 @@ export const tools = (sdk) => { const composioDeleteWebhook = { name: "composio_delete_webhook", - description: "Delete a Composio v3 webhook subscription by ID.", + description: "Delete a Composio v3.1 webhook subscription by ID.", category: "action", scope: "dm-only", diff --git a/plugins/composio-direct/manifest.json b/plugins/composio-direct/manifest.json index bc8fea6..456ddde 100644 --- a/plugins/composio-direct/manifest.json +++ b/plugins/composio-direct/manifest.json @@ -1,8 +1,8 @@ { "id": "composio-direct", "name": "Composio Direct", - "version": "1.9.0", - "description": "Direct access to 1000+ Composio automation tools plus v3 toolkits, files, triggers, webhooks, connection reuse, and meta-tools without MCP transport", + "version": "1.9.1", + "description": "Direct access to 1000+ Composio automation tools plus v3.1 toolkits, files, triggers, webhooks, connection reuse, and meta-tools without MCP transport", "author": { "name": "xlabtg", "url": "https://github.com/xlabtg" @@ -19,7 +19,7 @@ } }, "defaultConfig": { - "base_url": "https://backend.composio.dev/api/v3", + "base_url": "https://backend.composio.dev/api/v3.1", "timeout_ms": 30000, "max_parallel_executions": 10, "tool_version": "latest", diff --git a/plugins/composio-direct/package.json b/plugins/composio-direct/package.json index eaf2a20..5aa7242 100644 --- a/plugins/composio-direct/package.json +++ b/plugins/composio-direct/package.json @@ -1,7 +1,7 @@ { "name": "teleton-plugin-composio-direct", "type": "module", - "version": "1.9.0", + "version": "1.9.1", "private": true, "description": "Teleton plugin for direct Composio API access" } diff --git a/plugins/composio-direct/test/integration/composio-api.test.js b/plugins/composio-direct/test/integration/composio-api.test.js index c2d3573..62960f5 100644 --- a/plugins/composio-direct/test/integration/composio-api.test.js +++ b/plugins/composio-direct/test/integration/composio-api.test.js @@ -28,7 +28,7 @@ function makeSdk({ apiKey = "test-key", config = {} } = {}) { }, }, config: { - base_url: "https://backend.composio.dev/api/v3", + base_url: "https://backend.composio.dev/api/v3.1", timeout_ms: 3000, max_parallel_executions: 5, ...config, diff --git a/plugins/composio-direct/test/unit/composio-direct.test.js b/plugins/composio-direct/test/unit/composio-direct.test.js index a6a3b41..2e30075 100644 --- a/plugins/composio-direct/test/unit/composio-direct.test.js +++ b/plugins/composio-direct/test/unit/composio-direct.test.js @@ -29,7 +29,7 @@ function makeSdk({ apiKey = "test-api-key", config = {} } = {}) { }, }, config: { - base_url: "https://backend.composio.dev/api/v3", + base_url: "https://backend.composio.dev/api/v3.1", timeout_ms: 5000, max_parallel_executions: 10, ...config, @@ -149,13 +149,13 @@ describe("manifest", () => { assert.ok(manifest.name, "manifest.name is set"); assert.ok(manifest.version, "manifest.version is set"); assert.ok(manifest.secrets?.composio_api_key, "secret composio_api_key declared"); - assert.equal(manifest.version, "1.9.0"); - assert.equal(manifest.defaultConfig?.base_url, "https://backend.composio.dev/api/v3"); + assert.equal(manifest.version, "1.9.1"); + assert.equal(manifest.defaultConfig?.base_url, "https://backend.composio.dev/api/v3.1"); }); }); describe("tools factory", () => { - it("returns Composio v3 API domain, meta-tool, and execution tools when called with sdk", () => { + it("returns Composio v3.1 API domain, meta-tool, and execution tools when called with sdk", () => { const sdk = makeSdk(); const toolList = toolsFactory(sdk); const names = toolList.map((t) => t.name); diff --git a/plugins/composio-direct/tests/index.test.js b/plugins/composio-direct/tests/index.test.js index 72b0a98..fb168e3 100644 --- a/plugins/composio-direct/tests/index.test.js +++ b/plugins/composio-direct/tests/index.test.js @@ -46,7 +46,7 @@ function makeSdk({ apiKey = "test-api-key", pluginConfig = {} } = {}) { }, }, pluginConfig: { - base_url: "https://backend.composio.dev/api/v3", + base_url: "https://backend.composio.dev/api/v3.1", timeout_ms: 1000, max_parallel_executions: 5, tool_version: "latest", @@ -109,8 +109,8 @@ describe("composio-direct Teleton integration", () => { const sdk = makeSdk(); const toolList = toolsFactory(sdk); - assert.equal(manifest.version, "1.9.0"); - assert.equal(manifest.defaultConfig.base_url, "https://backend.composio.dev/api/v3"); + assert.equal(manifest.version, "1.9.1"); + assert.equal(manifest.defaultConfig.base_url, "https://backend.composio.dev/api/v3.1"); assert.deepEqual( toolList.map((tool) => tool.name).sort(), expectedToolNames @@ -207,7 +207,7 @@ describe("composio-direct Teleton integration", () => { assert.equal(result.data.log_id, "log_123"); const url = new URL(calls[0].url); - assert.equal(url.pathname, "/api/v3/tools/execute/GITHUB_LIST_REPOS"); + assert.equal(url.pathname, "/api/v3.1/tools/execute/GITHUB_LIST_REPOS"); assert.deepEqual(calls[0].body, { user_id: "user-42", arguments: { owner: "xlabtg" }, @@ -218,7 +218,7 @@ describe("composio-direct Teleton integration", () => { } }); - it("retries current v3 execute API when legacy v3.1 reports unknown tool", async () => { + it("retries paired v3 execute API when v3.1 reports unknown tool", async () => { const { calls, restore } = mockFetch((call, idx) => { if (idx === 1) { return { @@ -260,6 +260,48 @@ describe("composio-direct Teleton integration", () => { } }); + it("retries current v3.1 execute API when legacy v3 reports unknown tool", async () => { + const { calls, restore } = mockFetch((call, idx) => { + if (idx === 1) { + return { + status: 404, + data: { + error: { + message: "Unknown tool", + slug: "UNKNOWN_TOOL", + status: 404, + }, + }, + }; + } + return { + status: 200, + data: { + successful: true, + data: { ok: true }, + }, + }; + }); + + try { + const executeTool = toolsFactory( + makeSdk({ pluginConfig: { base_url: "https://backend.composio.dev/api/v3" } }) + ).find((tool) => tool.name === "composio_execute_tool"); + const result = await executeTool.execute( + { tool_slug: "github_list_repos", parameters: {} }, + makeContext() + ); + + assert.equal(result.success, true); + assert.equal(result.data.ok, true); + assert.equal(calls.length, 2); + assert.equal(new URL(calls[0].url).pathname, "/api/v3/tools/execute/GITHUB_LIST_REPOS"); + assert.equal(new URL(calls[1].url).pathname, "/api/v3.1/tools/execute/GITHUB_LIST_REPOS"); + } finally { + restore(); + } + }); + it("passes connected_account_id as a top-level execute field, not inside arguments", async () => { const { calls, restore } = mockFetch(() => ({ status: 200, @@ -283,7 +325,7 @@ describe("composio-direct Teleton integration", () => { assert.equal(result.success, true); assert.equal(calls[0].body.connected_account_id, "ca_lc9TestLuaI"); assert.equal(calls[0].body.user_id, "user-42"); - // connected_account_id is a top-level execute field per the Composio v3 API. + // connected_account_id is a top-level execute field per the Composio v3.1 API. // It must NOT pollute the tool arguments, or strict tool schemas // (additionalProperties: false) reject the call. assert.deepEqual(calls[0].body.arguments, { symbol: "BTC" }); @@ -494,7 +536,7 @@ describe("composio-direct Teleton integration", () => { it("fetches tool schemas through the current /tools/{tool_slug} API", async () => { const { calls, restore } = mockFetch((call) => { const url = new URL(call.url); - assert.equal(url.pathname, "/api/v3/tools/GITHUB_CREATE_ISSUE"); + assert.equal(url.pathname, "/api/v3.1/tools/GITHUB_CREATE_ISSUE"); assert.equal(url.searchParams.get("version"), "latest"); assert.equal(url.searchParams.get("toolkit_versions"), "latest"); return { @@ -539,7 +581,7 @@ describe("composio-direct Teleton integration", () => { it("lists current-user connected accounts with documented filters", async () => { const { calls, restore } = mockFetch((call) => { const url = new URL(call.url); - assert.equal(url.pathname, "/api/v3/connected_accounts"); + assert.equal(url.pathname, "/api/v3.1/connected_accounts"); assert.deepEqual(url.searchParams.getAll("toolkit_slugs"), ["github"]); assert.deepEqual(url.searchParams.getAll("statuses"), ["ACTIVE"]); assert.deepEqual(url.searchParams.getAll("user_ids"), ["user-42"]); @@ -590,7 +632,7 @@ describe("composio-direct Teleton integration", () => { it("gets a connected account without exposing state values", async () => { const { calls, restore } = mockFetch((call) => { const url = new URL(call.url); - assert.equal(url.pathname, "/api/v3/connected_accounts/ca_123"); + assert.equal(url.pathname, "/api/v3.1/connected_accounts/ca_123"); return { status: 200, data: { @@ -624,7 +666,7 @@ describe("composio-direct Teleton integration", () => { it("lists toolkits through the current /toolkits API", async () => { const { calls, restore } = mockFetch((call) => { const url = new URL(call.url); - assert.equal(url.pathname, "/api/v3/toolkits"); + assert.equal(url.pathname, "/api/v3.1/toolkits"); assert.equal(url.searchParams.get("search"), "github"); assert.equal(url.searchParams.get("category"), "developer-tools"); assert.equal(url.searchParams.get("managed_by"), "composio"); @@ -680,7 +722,7 @@ describe("composio-direct Teleton integration", () => { it("gets one toolkit through /toolkits/{slug}", async () => { const { calls, restore } = mockFetch((call) => { const url = new URL(call.url); - assert.equal(url.pathname, "/api/v3/toolkits/github"); + assert.equal(url.pathname, "/api/v3.1/toolkits/github"); assert.equal(url.searchParams.get("version"), "latest"); return { status: 200, @@ -712,7 +754,7 @@ describe("composio-direct Teleton integration", () => { const { calls, restore } = mockFetch((call, idx) => { const url = new URL(call.url); if (idx === 1) { - assert.equal(url.pathname, "/api/v3/files/list"); + assert.equal(url.pathname, "/api/v3.1/files/list"); assert.equal(url.searchParams.get("toolkit_slug"), "gmail"); assert.equal(url.searchParams.get("tool_slug"), "GMAIL_SEND_EMAIL"); assert.equal(url.searchParams.get("limit"), "25"); @@ -733,7 +775,7 @@ describe("composio-direct Teleton integration", () => { }; } - assert.equal(url.pathname, "/api/v3/files/upload/request"); + assert.equal(url.pathname, "/api/v3.1/files/upload/request"); assert.deepEqual(call.body, { toolkit_slug: "gmail", tool_slug: "GMAIL_SEND_EMAIL", @@ -783,11 +825,11 @@ describe("composio-direct Teleton integration", () => { } }); - it("lists trigger types, active triggers, and upserts trigger instances through v3 endpoints", async () => { + it("lists trigger types, active triggers, and upserts trigger instances through v3.1 endpoints", async () => { const { calls, restore } = mockFetch((call, idx) => { const url = new URL(call.url); if (idx === 1) { - assert.equal(url.pathname, "/api/v3/triggers_types"); + assert.equal(url.pathname, "/api/v3.1/triggers_types"); assert.deepEqual(url.searchParams.getAll("toolkit_slugs"), ["slack"]); assert.equal(url.searchParams.get("toolkit_versions"), "latest"); return { @@ -807,7 +849,7 @@ describe("composio-direct Teleton integration", () => { }; } if (idx === 2) { - assert.equal(url.pathname, "/api/v3/trigger_instances/active"); + assert.equal(url.pathname, "/api/v3.1/trigger_instances/active"); assert.deepEqual(url.searchParams.getAll("user_ids"), ["user-42"]); assert.deepEqual(url.searchParams.getAll("trigger_names"), ["SLACK_RECEIVE_MESSAGE"]); assert.equal(url.searchParams.get("show_disabled"), "true"); @@ -827,7 +869,7 @@ describe("composio-direct Teleton integration", () => { }; } - assert.equal(url.pathname, "/api/v3/trigger_instances/SLACK_RECEIVE_MESSAGE/upsert"); + assert.equal(url.pathname, "/api/v3.1/trigger_instances/SLACK_RECEIVE_MESSAGE/upsert"); assert.deepEqual(call.body, { connected_account_id: "ca_123", trigger_config: { channel_id: "C123" }, @@ -869,18 +911,18 @@ describe("composio-direct Teleton integration", () => { } }); - it("manages trigger status and deletion through v3 trigger manage endpoints", async () => { + it("manages trigger status and deletion through v3.1 trigger manage endpoints", async () => { const { calls, restore } = mockFetch((call, idx) => { const url = new URL(call.url); if (idx === 1) { assert.equal(call.method, "PATCH"); - assert.equal(url.pathname, "/api/v3/trigger_instances/manage/trig_123"); + assert.equal(url.pathname, "/api/v3.1/trigger_instances/manage/trig_123"); assert.deepEqual(call.body, { status: "disable" }); return { status: 200, data: { success: true } }; } assert.equal(call.method, "DELETE"); - assert.equal(url.pathname, "/api/v3/trigger_instances/manage/trig_123"); + assert.equal(url.pathname, "/api/v3.1/trigger_instances/manage/trig_123"); return { status: 200, data: { success: true } }; }); @@ -907,7 +949,7 @@ describe("composio-direct Teleton integration", () => { const { calls, restore } = mockFetch((call, idx) => { const url = new URL(call.url); if (idx === 1) { - assert.equal(url.pathname, "/api/v3/webhook_subscriptions/event_types"); + assert.equal(url.pathname, "/api/v3.1/webhook_subscriptions/event_types"); return { status: 200, data: { @@ -923,7 +965,7 @@ describe("composio-direct Teleton integration", () => { } if (idx === 2) { assert.equal(call.method, "POST"); - assert.equal(url.pathname, "/api/v3/webhook_subscriptions"); + assert.equal(url.pathname, "/api/v3.1/webhook_subscriptions"); assert.deepEqual(call.body, { webhook_url: "https://agent.example.test/composio", enabled_events: ["trigger.event_received"], @@ -942,7 +984,7 @@ describe("composio-direct Teleton integration", () => { } if (idx === 3) { assert.equal(call.method, "PATCH"); - assert.equal(url.pathname, "/api/v3/webhook_subscriptions/wh_123"); + assert.equal(url.pathname, "/api/v3.1/webhook_subscriptions/wh_123"); return { status: 200, data: { @@ -956,7 +998,7 @@ describe("composio-direct Teleton integration", () => { } assert.equal(call.method, "POST"); - assert.equal(url.pathname, "/api/v3/webhook_subscriptions/wh_123/rotate_secret"); + assert.equal(url.pathname, "/api/v3.1/webhook_subscriptions/wh_123/rotate_secret"); return { status: 200, data: { @@ -1010,7 +1052,7 @@ describe("composio-direct Teleton integration", () => { const { calls, restore } = mockFetch((call, idx) => { const url = new URL(call.url); if (idx === 1) { - assert.equal(url.pathname, "/api/v3/tools/execute/COMPOSIO_MANAGE_CONNECTIONS"); + assert.equal(url.pathname, "/api/v3.1/tools/execute/COMPOSIO_MANAGE_CONNECTIONS"); assert.deepEqual(call.body.arguments, { toolkits: ["github", "gmail"], reinitiate_all: true, @@ -1019,13 +1061,13 @@ describe("composio-direct Teleton integration", () => { return { status: 200, data: { successful: true, data: { connected: ["github"] } } }; } if (idx === 2) { - assert.equal(url.pathname, "/api/v3/tools/execute/COMPOSIO_REMOTE_BASH_TOOL"); + assert.equal(url.pathname, "/api/v3.1/tools/execute/COMPOSIO_REMOTE_BASH_TOOL"); assert.equal(call.body.arguments.command, "pwd"); assert.equal(call.body.arguments.session_id, "sess_123"); return { status: 200, data: { successful: true, data: { stdout: "/workspace" } } }; } - assert.equal(url.pathname, "/api/v3/tools/execute/COMPOSIO_REMOTE_WORKBENCH"); + assert.equal(url.pathname, "/api/v3.1/tools/execute/COMPOSIO_REMOTE_WORKBENCH"); assert.equal(call.body.arguments.code_to_execute, "print(1)"); assert.equal(call.body.arguments.current_step, "RUNNING_CODE"); return { status: 200, data: { successful: true, data: { result: 1 } } }; diff --git a/plugins/dedust/package-lock.json b/plugins/dedust/package-lock.json index 9cb0bb0..d38b448 100644 --- a/plugins/dedust/package-lock.json +++ b/plugins/dedust/package-lock.json @@ -291,17 +291,17 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -399,9 +399,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "peer": true, "dependencies": { diff --git a/plugins/evaa/package-lock.json b/plugins/evaa/package-lock.json index 8a665c8..eb22c52 100644 --- a/plugins/evaa/package-lock.json +++ b/plugins/evaa/package-lock.json @@ -377,16 +377,16 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -478,9 +478,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" diff --git a/plugins/stonfi/package-lock.json b/plugins/stonfi/package-lock.json index 6568bd5..de3292f 100644 --- a/plugins/stonfi/package-lock.json +++ b/plugins/stonfi/package-lock.json @@ -363,17 +363,17 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -471,9 +471,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "peer": true, "dependencies": { diff --git a/plugins/vk-full-admin/package-lock.json b/plugins/vk-full-admin/package-lock.json index 7ad2edc..9d5a916 100644 --- a/plugins/vk-full-admin/package-lock.json +++ b/plugins/vk-full-admin/package-lock.json @@ -527,9 +527,9 @@ } }, "node_modules/undici": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz", - "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", "license": "MIT", "engines": { "node": ">=20.18.1"