@customclaw/composio 0.0.7 → 0.0.9

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/README.md CHANGED
@@ -12,7 +12,13 @@ openclaw plugins install @customclaw/composio
12
12
 
13
13
  1. Get an API key from [platform.composio.dev/settings](https://platform.composio.dev/settings)
14
14
 
15
- 2. Add to `~/.openclaw/openclaw.json`:
15
+ 2. Run the guided setup:
16
+
17
+ ```bash
18
+ openclaw composio setup
19
+ ```
20
+
21
+ Or add manually to `~/.openclaw/openclaw.json`:
16
22
 
17
23
  ```json
18
24
  {
@@ -31,14 +37,24 @@ openclaw plugins install @customclaw/composio
31
37
  }
32
38
  ```
33
39
 
34
- Or set `COMPOSIO_API_KEY` as an environment variable.
40
+ You can also set `COMPOSIO_API_KEY` as an environment variable.
35
41
 
36
42
  3. Restart the gateway.
37
43
 
44
+ If you upgraded from an older config shape where keys like `defaultUserId` or `allowedToolkits`
45
+ were placed directly under `plugins.entries.composio`, rerun:
46
+
47
+ ```bash
48
+ openclaw composio setup
49
+ ```
50
+
51
+ Legacy mixed entry-level config keys are now rejected at runtime.
52
+
38
53
  ## What it does
39
54
 
40
- The plugin gives your agent two tools:
55
+ The plugin gives your agent three tools:
41
56
 
57
+ - `composio_search_tools` — discovers relevant Composio actions from natural-language intent
42
58
  - `composio_execute_tool` — runs a Composio action (e.g. `GMAIL_FETCH_EMAILS`, `SENTRY_LIST_ISSUES`)
43
59
  - `composio_manage_connections` — checks connection status and generates OAuth links when a toolkit isn't connected yet
44
60
 
@@ -49,6 +65,7 @@ The agent handles the rest. Ask it to "check my latest emails" and it will call
49
65
  ## CLI
50
66
 
51
67
  ```bash
68
+ openclaw composio setup # interactive setup for ~/.openclaw/openclaw.json
52
69
  openclaw composio list --user-id user-123 # list available toolkits for a user scope
53
70
  openclaw composio status [toolkit] --user-id user-123 # check connection status in a user scope
54
71
  openclaw composio accounts [toolkit] # inspect connected accounts (id/user_id/status)
@@ -65,6 +82,10 @@ openclaw composio search "send email" --user-id user-123
65
82
  | `defaultUserId` | Default Composio `user_id` scope when `--user-id` is not provided |
66
83
  | `allowedToolkits` | Only allow these toolkits (e.g. `["gmail", "sentry"]`) |
67
84
  | `blockedToolkits` | Block specific toolkits |
85
+ | `readOnlyMode` | Blocks likely-destructive actions by token matching (delete/update/create/send/etc.); use `allowedToolSlugs` to override safe exceptions |
86
+ | `sessionTags` | Optional Tool Router tags (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) |
87
+ | `allowedToolSlugs` | Optional explicit allowlist of UPPERCASE tool slugs |
88
+ | `blockedToolSlugs` | Explicit denylist of UPPERCASE tool slugs |
68
89
 
69
90
  ## User ID Scope (Important)
70
91
 
@@ -95,6 +116,24 @@ npm run build
95
116
  npm test
96
117
  ```
97
118
 
119
+ ### Live Integration Tests (Optional)
120
+
121
+ ```bash
122
+ COMPOSIO_LIVE_TEST=1 \
123
+ COMPOSIO_API_KEY=your_key \
124
+ npm run test:live
125
+ ```
126
+
127
+ Optional env vars for execution/disconnect paths:
128
+
129
+ - `COMPOSIO_LIVE_USER_ID`
130
+ - `COMPOSIO_LIVE_TOOLKIT` (default: `gmail`)
131
+ - `COMPOSIO_LIVE_TOOL_SLUG`
132
+ - `COMPOSIO_LIVE_TOOL_ARGS` (JSON)
133
+ - `COMPOSIO_LIVE_CONNECTED_ACCOUNT_ID`
134
+ - `COMPOSIO_LIVE_EXPECT_EXECUTE_SUCCESS=1`
135
+ - `COMPOSIO_LIVE_ALLOW_DISCONNECT=1` (destructive, opt-in)
136
+
98
137
  ## Acknowledgments
99
138
 
100
139
  Based on the Composio plugin from [openclaw-composio](https://github.com/ComposioHQ/openclaw-composio) by ComposioHQ. See [THIRD-PARTY-NOTICES](./THIRD-PARTY-NOTICES).
package/dist/cli.d.ts CHANGED
@@ -7,12 +7,12 @@ interface PluginLogger {
7
7
  }
8
8
  interface RegisterCliOptions {
9
9
  program: any;
10
- client: ComposioClient;
10
+ getClient?: () => ComposioClient;
11
11
  config: ComposioConfig;
12
12
  logger: PluginLogger;
13
13
  }
14
14
  /**
15
15
  * Register Composio CLI commands
16
16
  */
17
- export declare function registerComposioCli({ program, client, config, logger }: RegisterCliOptions): void;
17
+ export declare function registerComposioCli({ program, getClient, config, logger }: RegisterCliOptions): void;
18
18
  export {};
package/dist/cli.js CHANGED
@@ -1,20 +1,253 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
5
+ import { createInterface } from "node:readline/promises";
6
+ import { isRecord, normalizeToolkitList, normalizeToolkitSlug, stripLegacyFlatConfigKeys, } from "./utils.js";
7
+ const DEFAULT_OPENCLAW_CONFIG_PATH = path.join(os.homedir(), ".openclaw", "openclaw.json");
8
+ const COMPOSIO_PLUGIN_ID = "composio";
9
+ function parseCsvToolkits(value) {
10
+ if (!value)
11
+ return undefined;
12
+ return normalizeToolkitList(value.split(","));
13
+ }
14
+ function parseBooleanLike(value) {
15
+ const raw = value.trim().toLowerCase();
16
+ if (!raw)
17
+ return undefined;
18
+ if (["1", "true", "yes", "y"].includes(raw))
19
+ return true;
20
+ if (["0", "false", "no", "n"].includes(raw))
21
+ return false;
22
+ return undefined;
23
+ }
24
+ function normalizePluginIdList(value) {
25
+ if (!Array.isArray(value))
26
+ return undefined;
27
+ const normalized = value
28
+ .filter((item) => typeof item === "string")
29
+ .map((item) => item.trim())
30
+ .filter(Boolean);
31
+ return Array.from(new Set(normalized));
32
+ }
33
+ async function readOpenClawConfig(configPath) {
34
+ try {
35
+ const raw = await readFile(configPath, "utf8");
36
+ const parsed = JSON.parse(raw);
37
+ return isRecord(parsed) ? parsed : {};
38
+ }
39
+ catch (err) {
40
+ const nodeErr = err;
41
+ if (nodeErr?.code === "ENOENT")
42
+ return {};
43
+ throw err;
44
+ }
45
+ }
1
46
  /**
2
47
  * Register Composio CLI commands
3
48
  */
4
- export function registerComposioCli({ program, client, config, logger }) {
49
+ export function registerComposioCli({ program, getClient, config, logger }) {
5
50
  const composio = program.command("composio").description("Manage Composio Tool Router connections");
51
+ const requireClient = () => {
52
+ if (!config.enabled) {
53
+ logger.error("Composio plugin is disabled");
54
+ return null;
55
+ }
56
+ if (!getClient) {
57
+ logger.error("Composio API key is not configured. Run 'openclaw composio setup' first.");
58
+ return null;
59
+ }
60
+ try {
61
+ return getClient();
62
+ }
63
+ catch (err) {
64
+ logger.error(`Failed to initialize Composio client: ${err instanceof Error ? err.message : String(err)}`);
65
+ return null;
66
+ }
67
+ };
68
+ // openclaw composio setup
69
+ composio
70
+ .command("setup")
71
+ .description("Create or update Composio config in ~/.openclaw/openclaw.json")
72
+ .option("-c, --config-path <path>", "OpenClaw config file path", DEFAULT_OPENCLAW_CONFIG_PATH)
73
+ .option("--api-key <apiKey>", "Composio API key")
74
+ .option("--default-user-id <userId>", "Default user ID for Composio user scoping")
75
+ .option("--allowed-toolkits <toolkits>", "Comma-separated allowed toolkit slugs")
76
+ .option("--blocked-toolkits <toolkits>", "Comma-separated blocked toolkit slugs")
77
+ .option("--read-only <enabled>", "Enable read-only mode (true/false)")
78
+ .option("-y, --yes", "Skip prompts and use defaults/provided values")
79
+ .action(async (options) => {
80
+ const configPath = path.resolve(options.configPath || DEFAULT_OPENCLAW_CONFIG_PATH);
81
+ try {
82
+ const openClawConfig = await readOpenClawConfig(configPath);
83
+ const plugins = isRecord(openClawConfig.plugins) ? { ...openClawConfig.plugins } : {};
84
+ let updatedPluginSystemEnabled = false;
85
+ let addedToAllowlist = false;
86
+ let removedFromDenylist = false;
87
+ if (plugins.enabled === false) {
88
+ plugins.enabled = true;
89
+ updatedPluginSystemEnabled = true;
90
+ }
91
+ const allow = normalizePluginIdList(plugins.allow);
92
+ if (allow && allow.length > 0) {
93
+ const hasExactComposio = allow.includes(COMPOSIO_PLUGIN_ID);
94
+ const normalizedAllow = allow.filter((id) => id.toLowerCase() !== COMPOSIO_PLUGIN_ID);
95
+ normalizedAllow.push(COMPOSIO_PLUGIN_ID);
96
+ plugins.allow = Array.from(new Set(normalizedAllow));
97
+ if (!hasExactComposio) {
98
+ addedToAllowlist = true;
99
+ }
100
+ }
101
+ const deny = normalizePluginIdList(plugins.deny);
102
+ if (deny && deny.length > 0) {
103
+ const filteredDeny = deny.filter((id) => id.toLowerCase() !== COMPOSIO_PLUGIN_ID);
104
+ if (filteredDeny.length !== deny.length) {
105
+ removedFromDenylist = true;
106
+ }
107
+ if (filteredDeny.length > 0) {
108
+ plugins.deny = filteredDeny;
109
+ }
110
+ else {
111
+ delete plugins.deny;
112
+ }
113
+ }
114
+ const entries = isRecord(plugins.entries) ? { ...plugins.entries } : {};
115
+ const existingComposioEntry = isRecord(entries.composio) ? { ...entries.composio } : {};
116
+ const existingComposioConfig = isRecord(existingComposioEntry.config)
117
+ ? { ...existingComposioEntry.config }
118
+ : {};
119
+ let apiKey = String(options.apiKey || "").trim() ||
120
+ String(existingComposioConfig.apiKey || "").trim() ||
121
+ String(config.apiKey || "").trim() ||
122
+ String(process.env.COMPOSIO_API_KEY || "").trim();
123
+ let defaultUserId = String(options.defaultUserId || "").trim() ||
124
+ String(existingComposioConfig.defaultUserId || "").trim() ||
125
+ String(config.defaultUserId || "").trim();
126
+ let allowedToolkits = parseCsvToolkits(options.allowedToolkits) ||
127
+ (Array.isArray(existingComposioConfig.allowedToolkits)
128
+ ? normalizeToolkitList(existingComposioConfig.allowedToolkits)
129
+ : normalizeToolkitList(config.allowedToolkits));
130
+ let blockedToolkits = parseCsvToolkits(options.blockedToolkits) ||
131
+ (Array.isArray(existingComposioConfig.blockedToolkits)
132
+ ? normalizeToolkitList(existingComposioConfig.blockedToolkits)
133
+ : normalizeToolkitList(config.blockedToolkits));
134
+ let readOnlyMode = typeof existingComposioConfig.readOnlyMode === "boolean"
135
+ ? existingComposioConfig.readOnlyMode
136
+ : Boolean(config.readOnlyMode);
137
+ if (options.readOnly !== undefined) {
138
+ const parsedReadOnly = parseBooleanLike(options.readOnly);
139
+ if (parsedReadOnly === undefined) {
140
+ logger.error("Invalid value for --read-only. Expected one of: true/false/yes/no/1/0.");
141
+ return;
142
+ }
143
+ readOnlyMode = parsedReadOnly;
144
+ }
145
+ if (!options.yes) {
146
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
147
+ try {
148
+ const apiKeyPrompt = await rl.question(`Composio API key${apiKey ? " [configured]" : ""}: `);
149
+ if (apiKeyPrompt.trim())
150
+ apiKey = apiKeyPrompt.trim();
151
+ const defaultUserPrompt = await rl.question(`Default user ID${defaultUserId ? ` [${defaultUserId}]` : " (optional)"}: `);
152
+ if (defaultUserPrompt.trim())
153
+ defaultUserId = defaultUserPrompt.trim();
154
+ const allowedDefault = allowedToolkits && allowedToolkits.length > 0
155
+ ? ` [${allowedToolkits.join(",")}]`
156
+ : " (optional)";
157
+ const allowedPrompt = await rl.question(`Allowed toolkits${allowedDefault}: `);
158
+ if (allowedPrompt.trim()) {
159
+ allowedToolkits = parseCsvToolkits(allowedPrompt) || [];
160
+ }
161
+ const blockedDefault = blockedToolkits && blockedToolkits.length > 0
162
+ ? ` [${blockedToolkits.join(",")}]`
163
+ : " (optional)";
164
+ const blockedPrompt = await rl.question(`Blocked toolkits${blockedDefault}: `);
165
+ if (blockedPrompt.trim()) {
166
+ blockedToolkits = parseCsvToolkits(blockedPrompt) || [];
167
+ }
168
+ const readOnlyPrompt = await rl.question(`Enable read-only safety mode? (y/N) [${readOnlyMode ? "Y" : "N"}]: `);
169
+ const parsedReadOnlyPrompt = parseBooleanLike(readOnlyPrompt);
170
+ if (parsedReadOnlyPrompt !== undefined) {
171
+ readOnlyMode = parsedReadOnlyPrompt;
172
+ }
173
+ else if (readOnlyPrompt.trim()) {
174
+ logger.warn("Invalid read-only input. Keeping existing readOnlyMode value.");
175
+ }
176
+ }
177
+ finally {
178
+ rl.close();
179
+ }
180
+ }
181
+ if (!apiKey) {
182
+ logger.error("Composio API key is required. Provide --api-key or set COMPOSIO_API_KEY.");
183
+ return;
184
+ }
185
+ const mergedComposioConfig = {
186
+ ...existingComposioConfig,
187
+ apiKey,
188
+ readOnlyMode,
189
+ };
190
+ if (defaultUserId) {
191
+ mergedComposioConfig.defaultUserId = defaultUserId;
192
+ }
193
+ else {
194
+ delete mergedComposioConfig.defaultUserId;
195
+ }
196
+ if (allowedToolkits && allowedToolkits.length > 0) {
197
+ mergedComposioConfig.allowedToolkits = allowedToolkits;
198
+ }
199
+ else {
200
+ delete mergedComposioConfig.allowedToolkits;
201
+ }
202
+ if (blockedToolkits && blockedToolkits.length > 0) {
203
+ mergedComposioConfig.blockedToolkits = blockedToolkits;
204
+ }
205
+ else {
206
+ delete mergedComposioConfig.blockedToolkits;
207
+ }
208
+ entries.composio = {
209
+ ...stripLegacyFlatConfigKeys(existingComposioEntry),
210
+ enabled: true,
211
+ config: mergedComposioConfig,
212
+ };
213
+ plugins.entries = entries;
214
+ openClawConfig.plugins = plugins;
215
+ await mkdir(path.dirname(configPath), { recursive: true });
216
+ await writeFile(configPath, `${JSON.stringify(openClawConfig, null, 2)}\n`, "utf8");
217
+ console.log("\nComposio setup saved.");
218
+ console.log("─".repeat(40));
219
+ console.log(`Config: ${configPath}`);
220
+ console.log(`defaultUserId: ${defaultUserId || "default"}`);
221
+ console.log(`readOnlyMode: ${readOnlyMode ? "enabled" : "disabled"}`);
222
+ if (updatedPluginSystemEnabled) {
223
+ console.log("plugins.enabled: set to true");
224
+ }
225
+ if (addedToAllowlist) {
226
+ console.log("plugins.allow: added 'composio'");
227
+ }
228
+ if (removedFromDenylist) {
229
+ console.log("plugins.deny: removed 'composio'");
230
+ }
231
+ console.log("\nNext steps:");
232
+ console.log(" 1) openclaw gateway restart");
233
+ console.log(" 2) openclaw composio status --user-id <user-id>");
234
+ console.log();
235
+ }
236
+ catch (err) {
237
+ logger.error(`Failed to run setup: ${err instanceof Error ? err.message : String(err)}`);
238
+ }
239
+ });
6
240
  // openclaw composio list
7
241
  composio
8
242
  .command("list")
9
243
  .description("List available Composio toolkits")
10
244
  .option("-u, --user-id <userId>", "User ID for session scoping")
11
245
  .action(async (options) => {
12
- if (!config.enabled) {
13
- logger.error("Composio plugin is disabled");
246
+ const composioClient = requireClient();
247
+ if (!composioClient)
14
248
  return;
15
- }
16
249
  try {
17
- const toolkits = await client.listToolkits(options.userId);
250
+ const toolkits = await composioClient.listToolkits(options.userId);
18
251
  console.log("\nAvailable Composio Toolkits:");
19
252
  console.log("─".repeat(40));
20
253
  for (const toolkit of toolkits.sort()) {
@@ -32,13 +265,13 @@ export function registerComposioCli({ program, client, config, logger }) {
32
265
  .description("Check connection status for toolkits")
33
266
  .option("-u, --user-id <userId>", "User ID for session scoping")
34
267
  .action(async (toolkit, options) => {
35
- if (!config.enabled) {
36
- logger.error("Composio plugin is disabled");
268
+ const composioClient = requireClient();
269
+ if (!composioClient)
37
270
  return;
38
- }
39
271
  try {
40
- const toolkits = toolkit ? [toolkit] : undefined;
41
- const statuses = await client.getConnectionStatus(toolkits, options.userId);
272
+ const toolkitSlug = toolkit ? normalizeToolkitSlug(toolkit) : undefined;
273
+ const toolkits = toolkitSlug ? [toolkitSlug] : undefined;
274
+ const statuses = await composioClient.getConnectionStatus(toolkits, options.userId);
42
275
  console.log("\nComposio Connection Status:");
43
276
  console.log("─".repeat(40));
44
277
  if (statuses.length === 0) {
@@ -51,14 +284,14 @@ export function registerComposioCli({ program, client, config, logger }) {
51
284
  console.log(` ${icon} ${status.toolkit}: ${state}`);
52
285
  }
53
286
  }
54
- if (toolkit && statuses.length === 1 && !statuses[0]?.connected) {
287
+ if (toolkitSlug && statuses.length === 1 && !statuses[0]?.connected) {
55
288
  const currentUserId = options.userId || config.defaultUserId || "default";
56
- const activeUserIds = await client.findActiveUserIdsForToolkit(toolkit);
289
+ const activeUserIds = await composioClient.findActiveUserIdsForToolkit(toolkitSlug);
57
290
  const otherUserIds = activeUserIds.filter((uid) => uid !== currentUserId);
58
291
  if (otherUserIds.length > 0) {
59
- console.log(`\n Hint: '${toolkit}' is connected under other user_id(s): ${otherUserIds.join(", ")}`);
60
- console.log(` Try: openclaw composio status ${toolkit} --user-id <user-id>`);
61
- console.log(` Discover accounts: openclaw composio accounts ${toolkit}`);
292
+ console.log(`\n Hint: '${toolkitSlug}' is connected under other user_id(s): ${otherUserIds.join(", ")}`);
293
+ console.log(` Try: openclaw composio status ${toolkitSlug} --user-id <user-id>`);
294
+ console.log(` Discover accounts: openclaw composio accounts ${toolkitSlug}`);
62
295
  }
63
296
  }
64
297
  console.log();
@@ -74,17 +307,16 @@ export function registerComposioCli({ program, client, config, logger }) {
74
307
  .option("-u, --user-id <userId>", "Filter by user ID")
75
308
  .option("-s, --statuses <statuses>", "Comma-separated statuses (default: ACTIVE)", "ACTIVE")
76
309
  .action(async (toolkit, options) => {
77
- if (!config.enabled) {
78
- logger.error("Composio plugin is disabled");
310
+ const composioClient = requireClient();
311
+ if (!composioClient)
79
312
  return;
80
- }
81
313
  try {
82
314
  const statuses = String(options.statuses || "")
83
315
  .split(",")
84
316
  .map(s => s.trim())
85
317
  .filter(Boolean);
86
- const accounts = await client.listConnectedAccounts({
87
- toolkits: toolkit ? [toolkit] : undefined,
318
+ const accounts = await composioClient.listConnectedAccounts({
319
+ toolkits: toolkit ? [normalizeToolkitSlug(toolkit)] : undefined,
88
320
  userIds: options.userId ? [options.userId] : undefined,
89
321
  statuses: statuses.length > 0 ? statuses : ["ACTIVE"],
90
322
  });
@@ -110,15 +342,15 @@ export function registerComposioCli({ program, client, config, logger }) {
110
342
  .description("Connect to a Composio toolkit (opens auth URL)")
111
343
  .option("-u, --user-id <userId>", "User ID for session scoping")
112
344
  .action(async (toolkit, options) => {
113
- if (!config.enabled) {
114
- logger.error("Composio plugin is disabled");
345
+ const composioClient = requireClient();
346
+ if (!composioClient)
115
347
  return;
116
- }
117
348
  try {
349
+ const toolkitSlug = normalizeToolkitSlug(toolkit);
118
350
  const currentUserId = options.userId || config.defaultUserId || "default";
119
- console.log(`\nInitiating connection to ${toolkit}...`);
351
+ console.log(`\nInitiating connection to ${toolkitSlug}...`);
120
352
  console.log(`Using user_id: ${currentUserId}`);
121
- const result = await client.createConnection(toolkit, options.userId);
353
+ const result = await composioClient.createConnection(toolkitSlug, options.userId);
122
354
  if ("error" in result) {
123
355
  logger.error(`Failed to create connection: ${result.error}`);
124
356
  return;
@@ -127,7 +359,7 @@ export function registerComposioCli({ program, client, config, logger }) {
127
359
  console.log("─".repeat(40));
128
360
  console.log(result.authUrl);
129
361
  console.log("\nOpen this URL in your browser to authenticate.");
130
- console.log(`After authentication, run 'openclaw composio status ${toolkit} --user-id ${currentUserId}' to verify.\n`);
362
+ console.log(`After authentication, run 'openclaw composio status ${toolkitSlug} --user-id ${currentUserId}' to verify.\n`);
131
363
  // Try to open URL in browser
132
364
  try {
133
365
  const { exec } = await import("node:child_process");
@@ -153,15 +385,15 @@ export function registerComposioCli({ program, client, config, logger }) {
153
385
  .description("Disconnect from a Composio toolkit")
154
386
  .option("-u, --user-id <userId>", "User ID for session scoping")
155
387
  .action(async (toolkit, options) => {
156
- if (!config.enabled) {
157
- logger.error("Composio plugin is disabled");
388
+ const composioClient = requireClient();
389
+ if (!composioClient)
158
390
  return;
159
- }
160
391
  try {
161
- console.log(`\nDisconnecting from ${toolkit}...`);
162
- const result = await client.disconnectToolkit(toolkit, options.userId);
392
+ const toolkitSlug = normalizeToolkitSlug(toolkit);
393
+ console.log(`\nDisconnecting from ${toolkitSlug}...`);
394
+ const result = await composioClient.disconnectToolkit(toolkitSlug, options.userId);
163
395
  if (result.success) {
164
- console.log(`Successfully disconnected from ${toolkit}\n`);
396
+ console.log(`Successfully disconnected from ${toolkitSlug}\n`);
165
397
  }
166
398
  else {
167
399
  logger.error(`Failed to disconnect: ${result.error}`);
@@ -179,14 +411,13 @@ export function registerComposioCli({ program, client, config, logger }) {
179
411
  .option("-l, --limit <limit>", "Maximum results", "10")
180
412
  .option("-u, --user-id <userId>", "User ID for session scoping")
181
413
  .action(async (query, options) => {
182
- if (!config.enabled) {
183
- logger.error("Composio plugin is disabled");
414
+ const composioClient = requireClient();
415
+ if (!composioClient)
184
416
  return;
185
- }
186
417
  try {
187
418
  const limit = parseInt(options.limit, 10) || 10;
188
- const toolkits = options.toolkit ? [options.toolkit] : undefined;
189
- const results = await client.searchTools(query, {
419
+ const toolkits = options.toolkit ? [normalizeToolkitSlug(options.toolkit)] : undefined;
420
+ const results = await composioClient.searchTools(query, {
190
421
  toolkits,
191
422
  limit,
192
423
  userId: options.userId,
package/dist/client.d.ts CHANGED
@@ -15,12 +15,18 @@ export declare class ComposioClient {
15
15
  * Get or create a Tool Router session for a user
16
16
  */
17
17
  private makeSessionCacheKey;
18
+ private normalizeConnectedAccountsOverride;
19
+ private buildToolRouterBlockedToolsConfig;
20
+ private buildSessionConfig;
18
21
  private getSession;
22
+ private shouldRetrySessionWithoutToolkitFilters;
19
23
  private clearUserSessionCache;
20
24
  /**
21
25
  * Check if a toolkit is allowed based on config
22
26
  */
23
27
  private isToolkitAllowed;
28
+ private isLikelyDestructiveToolSlug;
29
+ private getToolSlugRestrictionError;
24
30
  /**
25
31
  * Execute a Tool Router meta-tool
26
32
  */