@customclaw/composio 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ComposioConfig, ToolSearchResult, ToolExecutionResult, MultiExecutionItem, MultiExecutionResult, ConnectionStatus } from "./types.js";
1
+ import type { ComposioConfig, ToolSearchResult, ToolExecutionResult, ConnectionStatus } from "./types.js";
2
2
  /**
3
3
  * Composio client wrapper using Tool Router pattern
4
4
  */
@@ -35,10 +35,6 @@ export declare class ComposioClient {
35
35
  * Execute a single tool using COMPOSIO_MULTI_EXECUTE_TOOL
36
36
  */
37
37
  executeTool(toolSlug: string, args: Record<string, unknown>, userId?: string): Promise<ToolExecutionResult>;
38
- /**
39
- * Execute multiple tools in parallel using COMPOSIO_MULTI_EXECUTE_TOOL
40
- */
41
- multiExecute(executions: MultiExecutionItem[], userId?: string): Promise<MultiExecutionResult>;
42
38
  /**
43
39
  * Get connection status for toolkits using session.toolkits()
44
40
  */
@@ -62,31 +58,6 @@ export declare class ComposioClient {
62
58
  success: boolean;
63
59
  error?: string;
64
60
  }>;
65
- /**
66
- * Get the assistive prompt for the agent
67
- */
68
- getAssistivePrompt(userId?: string): Promise<string>;
69
- /**
70
- * Execute Python code in the remote workbench using COMPOSIO_REMOTE_WORKBENCH
71
- */
72
- executeWorkbench(code: string, options?: {
73
- thought?: string;
74
- currentStep?: string;
75
- currentStepMetric?: string;
76
- userId?: string;
77
- }): Promise<{
78
- success: boolean;
79
- output?: unknown;
80
- error?: string;
81
- }>;
82
- /**
83
- * Execute bash commands in the remote sandbox using COMPOSIO_REMOTE_BASH_TOOL
84
- */
85
- executeBash(command: string, userId?: string): Promise<{
86
- success: boolean;
87
- output?: unknown;
88
- error?: string;
89
- }>;
90
61
  }
91
62
  /**
92
63
  * Create a Composio client instance
package/dist/client.js CHANGED
@@ -150,60 +150,6 @@ export class ComposioClient {
150
150
  };
151
151
  }
152
152
  }
153
- /**
154
- * Execute multiple tools in parallel using COMPOSIO_MULTI_EXECUTE_TOOL
155
- */
156
- async multiExecute(executions, userId) {
157
- const uid = this.getUserId(userId);
158
- const session = await this.getSession(uid);
159
- // Filter out blocked toolkits and limit to 50
160
- const allowedExecutions = executions
161
- .filter(exec => {
162
- const toolkit = exec.tool_slug.split("_")[0]?.toLowerCase() || "";
163
- return this.isToolkitAllowed(toolkit);
164
- })
165
- .slice(0, 50);
166
- if (allowedExecutions.length === 0) {
167
- return { results: [] };
168
- }
169
- try {
170
- const response = await this.executeMetaTool("COMPOSIO_MULTI_EXECUTE_TOOL", {
171
- tools: allowedExecutions.map(exec => ({
172
- tool_slug: exec.tool_slug,
173
- arguments: exec.arguments,
174
- })),
175
- session: { id: session.sessionId },
176
- sync_response_to_workbench: false,
177
- });
178
- if (!response.successful) {
179
- return {
180
- results: allowedExecutions.map(exec => ({
181
- tool_slug: exec.tool_slug,
182
- success: false,
183
- error: response.error || "Execution failed",
184
- })),
185
- };
186
- }
187
- const apiResults = response.data?.results || [];
188
- return {
189
- results: apiResults.map(r => ({
190
- tool_slug: r.tool_slug,
191
- success: r.response.successful,
192
- data: r.response.data,
193
- error: r.response.error ?? undefined,
194
- })),
195
- };
196
- }
197
- catch (err) {
198
- return {
199
- results: allowedExecutions.map(exec => ({
200
- tool_slug: exec.tool_slug,
201
- success: false,
202
- error: err instanceof Error ? err.message : String(err),
203
- })),
204
- };
205
- }
206
- }
207
153
  /**
208
154
  * Get connection status for toolkits using session.toolkits()
209
155
  */
@@ -314,69 +260,6 @@ export class ComposioClient {
314
260
  };
315
261
  }
316
262
  }
317
- /**
318
- * Get the assistive prompt for the agent
319
- */
320
- async getAssistivePrompt(userId) {
321
- const uid = this.getUserId(userId);
322
- const session = await this.getSession(uid);
323
- return session.experimental.assistivePrompt;
324
- }
325
- /**
326
- * Execute Python code in the remote workbench using COMPOSIO_REMOTE_WORKBENCH
327
- */
328
- async executeWorkbench(code, options) {
329
- const uid = this.getUserId(options?.userId);
330
- const session = await this.getSession(uid);
331
- try {
332
- const response = await this.executeMetaTool("COMPOSIO_REMOTE_WORKBENCH", {
333
- code_to_execute: code,
334
- session_id: session.sessionId,
335
- ...(options?.thought ? { thought: options.thought } : {}),
336
- ...(options?.currentStep ? { current_step: options.currentStep } : {}),
337
- ...(options?.currentStepMetric ? { current_step_metric: options.currentStepMetric } : {}),
338
- });
339
- if (!response.successful) {
340
- return { success: false, error: response.error || "Workbench execution failed" };
341
- }
342
- return {
343
- success: true,
344
- output: response.data,
345
- };
346
- }
347
- catch (err) {
348
- return {
349
- success: false,
350
- error: err instanceof Error ? err.message : String(err),
351
- };
352
- }
353
- }
354
- /**
355
- * Execute bash commands in the remote sandbox using COMPOSIO_REMOTE_BASH_TOOL
356
- */
357
- async executeBash(command, userId) {
358
- const uid = this.getUserId(userId);
359
- const session = await this.getSession(uid);
360
- try {
361
- const response = await this.executeMetaTool("COMPOSIO_REMOTE_BASH_TOOL", {
362
- command,
363
- session_id: session.sessionId,
364
- });
365
- if (!response.successful) {
366
- return { success: false, error: response.error || "Bash execution failed" };
367
- }
368
- return {
369
- success: true,
370
- output: response.data,
371
- };
372
- }
373
- catch (err) {
374
- return {
375
- success: false,
376
- error: err instanceof Error ? err.message : String(err),
377
- };
378
- }
379
- }
380
263
  }
381
264
  /**
382
265
  * Create a Composio client instance
@@ -2,6 +2,7 @@ import { describe, it, expect, vi } from "vitest";
2
2
  import { ComposioClient } from "./client.js";
3
3
  import { parseComposioConfig } from "./config.js";
4
4
  import { createComposioExecuteTool } from "./tools/execute.js";
5
+ import { createComposioConnectionsTool } from "./tools/connections.js";
5
6
  // Mock the Composio SDK
6
7
  vi.mock("@composio/core", () => ({
7
8
  Composio: vi.fn().mockImplementation(() => ({
@@ -15,6 +16,7 @@ vi.mock("@composio/core", () => ({
15
16
  { slug: "gmail", name: "Gmail", connection: { isActive: true } },
16
17
  { slug: "sentry", name: "Sentry", connection: { isActive: false } },
17
18
  { slug: "github", name: "GitHub", connection: { isActive: true } },
19
+ { slug: "affinity", name: "Affinity", connection: { isActive: false } },
18
20
  ],
19
21
  }),
20
22
  experimental: { assistivePrompt: "" },
@@ -182,3 +184,43 @@ describe("execute tool string arguments (GLM-5 workaround)", () => {
182
184
  expect(result.details).toHaveProperty("success", true);
183
185
  });
184
186
  });
187
+ describe("connections tool", () => {
188
+ function makeConnectionsTool() {
189
+ const client = makeClient();
190
+ const config = parseComposioConfig({ config: { apiKey: "test-key" } });
191
+ return createComposioConnectionsTool(client, config);
192
+ }
193
+ it("list action passes user_id to client", async () => {
194
+ const tool = makeConnectionsTool();
195
+ const result = await tool.execute("test", { action: "list", user_id: "custom-user" });
196
+ const details = result.details;
197
+ expect(details).toHaveProperty("action", "list");
198
+ expect(details.toolkits).toBeInstanceOf(Array);
199
+ });
200
+ it("status probes API-key toolkit and flips to connected on success", async () => {
201
+ const tool = makeConnectionsTool();
202
+ const result = await tool.execute("test", { action: "status", toolkit: "affinity" });
203
+ const details = result.details;
204
+ const conn = details.connections.find((c) => c.toolkit === "affinity");
205
+ expect(conn.connected).toBe(true);
206
+ });
207
+ it("status does not probe toolkits without a defined probe", async () => {
208
+ const tool = makeConnectionsTool();
209
+ const result = await tool.execute("test", { action: "status", toolkit: "sentry" });
210
+ const details = result.details;
211
+ const conn = details.connections.find((c) => c.toolkit === "sentry");
212
+ expect(conn.connected).toBe(false);
213
+ });
214
+ it("status keeps disconnected when probe fails", async () => {
215
+ const tool = makeConnectionsTool();
216
+ // Get the latest Composio instance (the one this tool's client is using)
217
+ const { Composio } = await import("@composio/core");
218
+ const mockResults = Composio.mock.results;
219
+ const instance = mockResults[mockResults.length - 1].value;
220
+ instance.client.tools.execute.mockRejectedValueOnce(new Error("probe failed"));
221
+ const result = await tool.execute("test", { action: "status", toolkit: "affinity" });
222
+ const details = result.details;
223
+ const conn = details.connections.find((c) => c.toolkit === "affinity");
224
+ expect(conn.connected).toBe(false);
225
+ });
226
+ });
package/dist/index.js CHANGED
@@ -73,22 +73,6 @@ const composioPlugin = {
73
73
  config,
74
74
  logger: api.logger,
75
75
  }), { commands: ["composio"] });
76
- // Inject agent instructions via before_agent_start hook
77
- api.on("before_agent_start", () => {
78
- return {
79
- prependContext: `<composio-tools>
80
- You have access to Composio tools for third-party integrations (Gmail, Sentry, etc.).
81
-
82
- ## Usage
83
- 1. Use \`composio_search_tools\` to find tools and their parameter schemas.
84
- 2. Use \`composio_manage_connections\` with action="status" to check if a toolkit is connected. Use action="create" to generate an auth URL if needed.
85
- 3. Use \`composio_execute_tool\` with the tool_slug and arguments from search results.
86
-
87
- Always search first to get the correct parameter schema before executing a tool.
88
- Tool slugs are uppercase. If a tool fails with auth errors, prompt the user to connect the toolkit.
89
- </composio-tools>`,
90
- };
91
- });
92
76
  api.logger.info("[composio] Plugin registered with 3 tools and CLI commands");
93
77
  },
94
78
  };
@@ -1,4 +1,10 @@
1
1
  import { Type } from "@sinclair/typebox";
2
+ const CONNECTION_PROBES = {
3
+ affinity: {
4
+ toolSlug: "AFFINITY_GET_METADATA_ON_ALL_LISTS",
5
+ args: { limit: 1 },
6
+ },
7
+ };
2
8
  /**
3
9
  * Tool parameters for composio_manage_connections
4
10
  */
@@ -23,8 +29,9 @@ export function createComposioConnectionsTool(client, _config) {
23
29
  return {
24
30
  name: "composio_manage_connections",
25
31
  label: "Composio Manage Connections",
26
- description: "Manage Composio toolkit connections. Check connection status, create new auth links, " +
27
- "or list available toolkits. Use this before executing tools to ensure authentication.",
32
+ description: "Manage Composio toolkit connections. Use action='status' to check if a toolkit is connected, " +
33
+ "action='create' to generate an auth URL when disconnected, or action='list' to see available toolkits. " +
34
+ "Check connection status before executing tools with composio_execute_tool.",
28
35
  parameters: ComposioManageConnectionsToolSchema,
29
36
  async execute(_toolCallId, params) {
30
37
  const action = String(params.action || "status");
@@ -32,7 +39,7 @@ export function createComposioConnectionsTool(client, _config) {
32
39
  try {
33
40
  switch (action) {
34
41
  case "list": {
35
- const toolkits = await client.listToolkits();
42
+ const toolkits = await client.listToolkits(userId);
36
43
  const response = {
37
44
  action: "list",
38
45
  count: toolkits.length,
@@ -82,6 +89,25 @@ export function createComposioConnectionsTool(client, _config) {
82
89
  toolkitsToCheck = params.toolkits.filter((t) => typeof t === "string" && t.trim() !== "");
83
90
  }
84
91
  const statuses = await client.getConnectionStatus(toolkitsToCheck, userId);
92
+ // Fallback probe for API-key style integrations where
93
+ // connection.isActive can be false despite successful tool execution
94
+ if (toolkitsToCheck && toolkitsToCheck.length > 0) {
95
+ for (const status of statuses) {
96
+ if (status.connected)
97
+ continue;
98
+ const probe = CONNECTION_PROBES[String(status.toolkit || "").toLowerCase()];
99
+ if (!probe)
100
+ continue;
101
+ try {
102
+ const probeResult = await client.executeTool(probe.toolSlug, probe.args, userId);
103
+ if (probeResult?.success)
104
+ status.connected = true;
105
+ }
106
+ catch {
107
+ // keep false if probe fails
108
+ }
109
+ }
110
+ }
85
111
  const response = {
86
112
  action: "status",
87
113
  count: statuses.length,
@@ -20,8 +20,9 @@ export function createComposioExecuteTool(client, _config) {
20
20
  return {
21
21
  name: "composio_execute_tool",
22
22
  label: "Composio Execute Tool",
23
- description: "Execute a single Composio tool. Use composio_search_tools first to find the tool slug " +
24
- "and parameter schema. The tool must be connected (use composio_manage_connections to check).",
23
+ description: "Execute a single Composio tool. Use composio_search_tools first to find the UPPERCASE tool slug " +
24
+ "and parameter schema. The toolkit must be connected use composio_manage_connections to check " +
25
+ "status or create an auth link. If execution fails with auth errors, prompt the user to reconnect.",
25
26
  parameters: ComposioExecuteToolSchema,
26
27
  async execute(_toolCallId, params) {
27
28
  const toolSlug = String(params.tool_slug || "").trim();
@@ -23,8 +23,9 @@ export function createComposioSearchTool(client, _config) {
23
23
  return {
24
24
  name: "composio_search_tools",
25
25
  label: "Composio Search Tools",
26
- description: "Search for tools across 1000+ integrations (Gmail, Slack, GitHub, Notion, etc.) " +
27
- "by describing what you want to accomplish. Returns matching tools with their schemas.",
26
+ description: "Search for Composio tools across 1000+ integrations (Gmail, Slack, GitHub, Notion, etc.) " +
27
+ "by describing what you want to accomplish. Returns matching tools with their UPPERCASE slugs and parameter schemas. " +
28
+ "Always search first before executing a tool with composio_execute_tool.",
28
29
  parameters: ComposioSearchToolSchema,
29
30
  async execute(_toolCallId, params) {
30
31
  const query = String(params.query || "").trim();
package/dist/types.d.ts CHANGED
@@ -20,27 +20,9 @@ export interface ToolExecutionResult {
20
20
  data?: unknown;
21
21
  error?: string;
22
22
  }
23
- export interface MultiExecutionItem {
24
- tool_slug: string;
25
- arguments: Record<string, unknown>;
26
- }
27
- export interface MultiExecutionResult {
28
- results: Array<{
29
- tool_slug: string;
30
- success: boolean;
31
- data?: unknown;
32
- error?: string;
33
- }>;
34
- }
35
23
  export interface ConnectionStatus {
36
24
  toolkit: string;
37
25
  connected: boolean;
38
26
  userId?: string;
39
27
  authUrl?: string;
40
28
  }
41
- export interface ComposioClientOptions {
42
- apiKey: string;
43
- defaultUserId?: string;
44
- allowedToolkits?: string[];
45
- blockedToolkits?: string[];
46
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@customclaw/composio",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "type": "module",
5
5
  "description": "Composio Tool Router plugin for OpenClaw — access 1000+ third-party integrations",
6
6
  "main": "dist/index.js",
@@ -1,42 +0,0 @@
1
- import type { ComposioClient } from "../client.js";
2
- import type { ComposioConfig } from "../types.js";
3
- /**
4
- * Tool parameters for composio_bash
5
- */
6
- export declare const CompositoBashSchema: import("@sinclair/typebox").TObject<{
7
- command: import("@sinclair/typebox").TString;
8
- user_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
9
- }>;
10
- /**
11
- * Create the composio_bash tool
12
- */
13
- export declare function createCompositoBashTool(client: ComposioClient, _config: ComposioConfig): {
14
- name: string;
15
- label: string;
16
- description: string;
17
- parameters: import("@sinclair/typebox").TObject<{
18
- command: import("@sinclair/typebox").TString;
19
- user_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
20
- }>;
21
- execute(_toolCallId: string, params: Record<string, unknown>): Promise<{
22
- content: {
23
- type: string;
24
- text: string;
25
- }[];
26
- details: {
27
- error: string;
28
- };
29
- } | {
30
- content: {
31
- type: string;
32
- text: string;
33
- }[];
34
- details: {
35
- output: unknown;
36
- success: boolean;
37
- } | {
38
- error: string | undefined;
39
- success: boolean;
40
- };
41
- }>;
42
- };
@@ -1,59 +0,0 @@
1
- import { Type } from "@sinclair/typebox";
2
- /**
3
- * Tool parameters for composio_bash
4
- */
5
- export const CompositoBashSchema = Type.Object({
6
- command: Type.String({
7
- description: "Bash command to execute in the remote sandbox. " +
8
- "Use for file operations, data processing with jq/awk/sed/grep, " +
9
- "or handling large tool responses saved to remote files. " +
10
- "Commands run from /home/user directory by default.",
11
- }),
12
- user_id: Type.Optional(Type.String({
13
- description: "User ID for session scoping (uses default if not provided)",
14
- })),
15
- });
16
- /**
17
- * Create the composio_bash tool
18
- */
19
- export function createCompositoBashTool(client, _config) {
20
- return {
21
- name: "composio_bash",
22
- label: "Composio Remote Bash",
23
- description: "Execute bash commands in a remote sandbox for file operations, data processing, " +
24
- "and system tasks. Essential for handling large tool responses saved to remote files. " +
25
- "Use shell tools like jq, awk, sed, grep for data extraction.",
26
- parameters: CompositoBashSchema,
27
- async execute(_toolCallId, params) {
28
- const command = String(params.command || "").trim();
29
- if (!command) {
30
- return {
31
- content: [{ type: "text", text: JSON.stringify({ error: "command is required" }, null, 2) }],
32
- details: { error: "command is required" },
33
- };
34
- }
35
- const userId = typeof params.user_id === "string" ? params.user_id : undefined;
36
- try {
37
- const result = await client.executeBash(command, userId);
38
- const response = {
39
- success: result.success,
40
- ...(result.success ? { output: result.output } : { error: result.error }),
41
- };
42
- return {
43
- content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
44
- details: response,
45
- };
46
- }
47
- catch (err) {
48
- const errorResponse = {
49
- success: false,
50
- error: err instanceof Error ? err.message : String(err),
51
- };
52
- return {
53
- content: [{ type: "text", text: JSON.stringify(errorResponse, null, 2) }],
54
- details: errorResponse,
55
- };
56
- }
57
- },
58
- };
59
- }
@@ -1,52 +0,0 @@
1
- import type { ComposioClient } from "../client.js";
2
- import type { ComposioConfig } from "../types.js";
3
- /**
4
- * Tool parameters for composio_multi_execute
5
- */
6
- export declare const ComposioMultiExecuteToolSchema: import("@sinclair/typebox").TObject<{
7
- executions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
8
- tool_slug: import("@sinclair/typebox").TString;
9
- arguments: import("@sinclair/typebox").TUnknown;
10
- }>>;
11
- user_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
12
- }>;
13
- /**
14
- * Create the composio_multi_execute tool
15
- */
16
- export declare function createComposioMultiExecuteTool(client: ComposioClient, _config: ComposioConfig): {
17
- name: string;
18
- label: string;
19
- description: string;
20
- parameters: import("@sinclair/typebox").TObject<{
21
- executions: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
22
- tool_slug: import("@sinclair/typebox").TString;
23
- arguments: import("@sinclair/typebox").TUnknown;
24
- }>>;
25
- user_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
26
- }>;
27
- execute(_toolCallId: string, params: Record<string, unknown>): Promise<{
28
- content: {
29
- type: string;
30
- text: string;
31
- }[];
32
- details: {
33
- error: string;
34
- };
35
- } | {
36
- content: {
37
- type: string;
38
- text: string;
39
- }[];
40
- details: {
41
- total: number;
42
- succeeded: number;
43
- failed: number;
44
- results: {
45
- tool_slug: string;
46
- success: boolean;
47
- data?: unknown;
48
- error?: string;
49
- }[];
50
- };
51
- }>;
52
- };
@@ -1,87 +0,0 @@
1
- import { Type } from "@sinclair/typebox";
2
- /**
3
- * Tool parameters for composio_multi_execute
4
- */
5
- export const ComposioMultiExecuteToolSchema = Type.Object({
6
- executions: Type.Array(Type.Object({
7
- tool_slug: Type.String({
8
- description: "Tool slug from composio_search_tools results",
9
- }),
10
- arguments: Type.Unknown({
11
- description: "Tool arguments matching the tool's parameter schema",
12
- }),
13
- }), {
14
- description: "Array of tool executions to run in parallel (max 50)",
15
- maxItems: 50,
16
- }),
17
- user_id: Type.Optional(Type.String({
18
- description: "User ID for session scoping (uses default if not provided)",
19
- })),
20
- });
21
- /**
22
- * Create the composio_multi_execute tool
23
- */
24
- export function createComposioMultiExecuteTool(client, _config) {
25
- return {
26
- name: "composio_multi_execute",
27
- label: "Composio Multi Execute",
28
- description: "Execute multiple Composio tools in parallel (up to 50). Use composio_search_tools first " +
29
- "to find tool slugs and parameter schemas. All tools must be connected.",
30
- parameters: ComposioMultiExecuteToolSchema,
31
- async execute(_toolCallId, params) {
32
- const executions = Array.isArray(params.executions) ? params.executions : [];
33
- if (executions.length === 0) {
34
- return {
35
- content: [
36
- { type: "text", text: JSON.stringify({ error: "executions array is required and cannot be empty" }, null, 2) },
37
- ],
38
- details: { error: "executions array is required and cannot be empty" },
39
- };
40
- }
41
- // Validate and normalize executions
42
- const normalizedExecutions = executions
43
- .slice(0, 50)
44
- .filter((exec) => exec &&
45
- typeof exec === "object" &&
46
- typeof exec.tool_slug === "string" &&
47
- exec.tool_slug.trim() !== "")
48
- .map((exec) => ({
49
- tool_slug: exec.tool_slug.trim(),
50
- arguments: exec.arguments && typeof exec.arguments === "object" && !Array.isArray(exec.arguments)
51
- ? exec.arguments
52
- : {},
53
- }));
54
- if (normalizedExecutions.length === 0) {
55
- return {
56
- content: [
57
- { type: "text", text: JSON.stringify({ error: "No valid executions provided" }, null, 2) },
58
- ],
59
- details: { error: "No valid executions provided" },
60
- };
61
- }
62
- const userId = typeof params.user_id === "string" ? params.user_id : undefined;
63
- try {
64
- const result = await client.multiExecute(normalizedExecutions, userId);
65
- const response = {
66
- total: normalizedExecutions.length,
67
- succeeded: result.results.filter((r) => r.success).length,
68
- failed: result.results.filter((r) => !r.success).length,
69
- results: result.results,
70
- };
71
- return {
72
- content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
73
- details: response,
74
- };
75
- }
76
- catch (err) {
77
- const errorResponse = {
78
- error: err instanceof Error ? err.message : String(err),
79
- };
80
- return {
81
- content: [{ type: "text", text: JSON.stringify(errorResponse, null, 2) }],
82
- details: errorResponse,
83
- };
84
- }
85
- },
86
- };
87
- }
@@ -1,48 +0,0 @@
1
- import type { ComposioClient } from "../client.js";
2
- import type { ComposioConfig } from "../types.js";
3
- /**
4
- * Tool parameters for composio_workbench
5
- */
6
- export declare const ComposioWorkbenchSchema: import("@sinclair/typebox").TObject<{
7
- code: import("@sinclair/typebox").TString;
8
- thought: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
9
- current_step: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
10
- current_step_metric: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
11
- user_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
12
- }>;
13
- /**
14
- * Create the composio_workbench tool
15
- */
16
- export declare function createComposioWorkbenchTool(client: ComposioClient, _config: ComposioConfig): {
17
- name: string;
18
- label: string;
19
- description: string;
20
- parameters: import("@sinclair/typebox").TObject<{
21
- code: import("@sinclair/typebox").TString;
22
- thought: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
23
- current_step: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
24
- current_step_metric: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
25
- user_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
26
- }>;
27
- execute(_toolCallId: string, params: Record<string, unknown>): Promise<{
28
- content: {
29
- type: string;
30
- text: string;
31
- }[];
32
- details: {
33
- error: string;
34
- };
35
- } | {
36
- content: {
37
- type: string;
38
- text: string;
39
- }[];
40
- details: {
41
- output: unknown;
42
- success: boolean;
43
- } | {
44
- error: string | undefined;
45
- success: boolean;
46
- };
47
- }>;
48
- };
@@ -1,76 +0,0 @@
1
- import { Type } from "@sinclair/typebox";
2
- /**
3
- * Tool parameters for composio_workbench
4
- */
5
- export const ComposioWorkbenchSchema = Type.Object({
6
- code: Type.String({
7
- description: "Python code to execute in the remote Jupyter sandbox. " +
8
- "Helper functions available: run_composio_tool(slug, args), invoke_llm(query), " +
9
- "upload_local_file(*paths), proxy_execute(method, endpoint, toolkit, ...), " +
10
- "web_search(query), smart_file_extract(path). State persists across executions.",
11
- }),
12
- thought: Type.Optional(Type.String({
13
- description: "Concise objective describing what the code should achieve",
14
- })),
15
- current_step: Type.Optional(Type.String({
16
- description: "Short enum for current workflow step (e.g., FETCHING_EMAILS, GENERATING_REPLIES)",
17
- })),
18
- current_step_metric: Type.Optional(Type.String({
19
- description: "Progress metrics for current step (e.g., '10/100 emails', '3/10 pages')",
20
- })),
21
- user_id: Type.Optional(Type.String({
22
- description: "User ID for session scoping (uses default if not provided)",
23
- })),
24
- });
25
- /**
26
- * Create the composio_workbench tool
27
- */
28
- export function createComposioWorkbenchTool(client, _config) {
29
- return {
30
- name: "composio_workbench",
31
- label: "Composio Remote Workbench",
32
- description: "Execute Python code in a remote Jupyter sandbox for processing large tool responses, " +
33
- "scripting bulk operations, or running data analysis. Use when data is stored in remote files " +
34
- "or when orchestrating multiple Composio tool calls. Has access to pandas, numpy, PIL, PyTorch, etc.",
35
- parameters: ComposioWorkbenchSchema,
36
- async execute(_toolCallId, params) {
37
- const code = String(params.code || "").trim();
38
- if (!code) {
39
- return {
40
- content: [{ type: "text", text: JSON.stringify({ error: "code is required" }, null, 2) }],
41
- details: { error: "code is required" },
42
- };
43
- }
44
- const thought = typeof params.thought === "string" ? params.thought : undefined;
45
- const currentStep = typeof params.current_step === "string" ? params.current_step : undefined;
46
- const currentStepMetric = typeof params.current_step_metric === "string" ? params.current_step_metric : undefined;
47
- const userId = typeof params.user_id === "string" ? params.user_id : undefined;
48
- try {
49
- const result = await client.executeWorkbench(code, {
50
- thought,
51
- currentStep,
52
- currentStepMetric,
53
- userId,
54
- });
55
- const response = {
56
- success: result.success,
57
- ...(result.success ? { output: result.output } : { error: result.error }),
58
- };
59
- return {
60
- content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
61
- details: response,
62
- };
63
- }
64
- catch (err) {
65
- const errorResponse = {
66
- success: false,
67
- error: err instanceof Error ? err.message : String(err),
68
- };
69
- return {
70
- content: [{ type: "text", text: JSON.stringify(errorResponse, null, 2) }],
71
- details: errorResponse,
72
- };
73
- }
74
- },
75
- };
76
- }