@customclaw/composio 0.0.8 → 0.0.10
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 +1 -1
- package/dist/cli.js +2 -1
- package/dist/client.js +29 -7
- package/dist/tools/connections.d.ts +7 -0
- package/dist/tools/connections.js +21 -1
- package/dist/tools/execute.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ may look disconnected.
|
|
|
96
96
|
Tips:
|
|
97
97
|
|
|
98
98
|
- Set `defaultUserId` in plugin config for your app's primary identity.
|
|
99
|
-
-
|
|
99
|
+
- Prefer passing `user_id`/`--user-id` explicitly when checking status, connecting, disconnecting, or executing tools.
|
|
100
100
|
- Use `openclaw composio accounts <toolkit>` to discover which `user_id` owns active connections.
|
|
101
101
|
|
|
102
102
|
## Updating
|
package/dist/cli.js
CHANGED
|
@@ -271,9 +271,11 @@ export function registerComposioCli({ program, getClient, config, logger }) {
|
|
|
271
271
|
try {
|
|
272
272
|
const toolkitSlug = toolkit ? normalizeToolkitSlug(toolkit) : undefined;
|
|
273
273
|
const toolkits = toolkitSlug ? [toolkitSlug] : undefined;
|
|
274
|
+
const currentUserId = options.userId || config.defaultUserId || "default";
|
|
274
275
|
const statuses = await composioClient.getConnectionStatus(toolkits, options.userId);
|
|
275
276
|
console.log("\nComposio Connection Status:");
|
|
276
277
|
console.log("─".repeat(40));
|
|
278
|
+
console.log(` Scope user_id: ${currentUserId}${options.userId ? " (explicit)" : " (default)"}`);
|
|
277
279
|
if (statuses.length === 0) {
|
|
278
280
|
console.log(" No connections found");
|
|
279
281
|
}
|
|
@@ -285,7 +287,6 @@ export function registerComposioCli({ program, getClient, config, logger }) {
|
|
|
285
287
|
}
|
|
286
288
|
}
|
|
287
289
|
if (toolkitSlug && statuses.length === 1 && !statuses[0]?.connected) {
|
|
288
|
-
const currentUserId = options.userId || config.defaultUserId || "default";
|
|
289
290
|
const activeUserIds = await composioClient.findActiveUserIdsForToolkit(toolkitSlug);
|
|
290
291
|
const otherUserIds = activeUserIds.filter((uid) => uid !== currentUserId);
|
|
291
292
|
if (otherUserIds.length > 0) {
|
package/dist/client.js
CHANGED
|
@@ -290,7 +290,7 @@ export class ComposioClient {
|
|
|
290
290
|
* Execute a single tool using COMPOSIO_MULTI_EXECUTE_TOOL
|
|
291
291
|
*/
|
|
292
292
|
async executeTool(toolSlug, args, userId, connectedAccountId) {
|
|
293
|
-
const
|
|
293
|
+
const requestedUid = this.getUserId(userId);
|
|
294
294
|
const normalizedToolSlug = normalizeToolSlug(toolSlug);
|
|
295
295
|
const toolRestrictionError = this.getToolSlugRestrictionError(normalizedToolSlug);
|
|
296
296
|
if (toolRestrictionError) {
|
|
@@ -305,13 +305,15 @@ export class ComposioClient {
|
|
|
305
305
|
}
|
|
306
306
|
const accountResolution = await this.resolveConnectedAccountForExecution({
|
|
307
307
|
toolkit,
|
|
308
|
-
userId:
|
|
308
|
+
userId: requestedUid,
|
|
309
309
|
connectedAccountId,
|
|
310
|
+
userIdWasExplicit: typeof userId === "string" && userId.trim().length > 0,
|
|
310
311
|
});
|
|
311
312
|
if ("error" in accountResolution) {
|
|
312
313
|
return { success: false, error: accountResolution.error };
|
|
313
314
|
}
|
|
314
|
-
const
|
|
315
|
+
const effectiveUid = accountResolution.userId || requestedUid;
|
|
316
|
+
const session = await this.getSession(effectiveUid, accountResolution.connectedAccountId
|
|
315
317
|
? { [toolkit]: accountResolution.connectedAccountId }
|
|
316
318
|
: undefined);
|
|
317
319
|
try {
|
|
@@ -321,7 +323,7 @@ export class ComposioClient {
|
|
|
321
323
|
});
|
|
322
324
|
if (!response.successful) {
|
|
323
325
|
const recovered = await this.tryExecutionRecovery({
|
|
324
|
-
uid,
|
|
326
|
+
uid: effectiveUid,
|
|
325
327
|
toolSlug: normalizedToolSlug,
|
|
326
328
|
args,
|
|
327
329
|
connectedAccountId: accountResolution.connectedAccountId,
|
|
@@ -341,7 +343,7 @@ export class ComposioClient {
|
|
|
341
343
|
const toolResponse = result.response;
|
|
342
344
|
if (!toolResponse.successful) {
|
|
343
345
|
const recovered = await this.tryExecutionRecovery({
|
|
344
|
-
uid,
|
|
346
|
+
uid: effectiveUid,
|
|
345
347
|
toolSlug: normalizedToolSlug,
|
|
346
348
|
args,
|
|
347
349
|
connectedAccountId: accountResolution.connectedAccountId,
|
|
@@ -483,9 +485,23 @@ export class ComposioClient {
|
|
|
483
485
|
const explicitId = params.connectedAccountId?.trim();
|
|
484
486
|
if (explicitId) {
|
|
485
487
|
try {
|
|
486
|
-
|
|
488
|
+
let rawAccount;
|
|
489
|
+
const retrieve = this.client?.client?.connectedAccounts?.retrieve;
|
|
490
|
+
if (typeof retrieve === "function") {
|
|
491
|
+
try {
|
|
492
|
+
rawAccount = await retrieve.call(this.client.client.connectedAccounts, explicitId);
|
|
493
|
+
}
|
|
494
|
+
catch {
|
|
495
|
+
// Best-effort: fall through to SDK get() which may omit user_id.
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
if (!rawAccount) {
|
|
499
|
+
rawAccount = await this.client.connectedAccounts.get(explicitId);
|
|
500
|
+
}
|
|
501
|
+
const account = rawAccount;
|
|
487
502
|
const accountToolkit = normalizeToolkitSlug(String(account?.toolkit?.slug || ""));
|
|
488
503
|
const accountStatus = String(account?.status || "").toUpperCase();
|
|
504
|
+
const accountUserId = String(account?.user_id || account?.userId || "").trim();
|
|
489
505
|
if (accountToolkit && accountToolkit !== toolkit) {
|
|
490
506
|
return {
|
|
491
507
|
error: `Connected account '${explicitId}' belongs to toolkit '${accountToolkit}', but tool '${toolkit}' was requested.`,
|
|
@@ -496,7 +512,13 @@ export class ComposioClient {
|
|
|
496
512
|
error: `Connected account '${explicitId}' is '${accountStatus}', not ACTIVE.`,
|
|
497
513
|
};
|
|
498
514
|
}
|
|
499
|
-
|
|
515
|
+
if (params.userIdWasExplicit && accountUserId && accountUserId !== userId) {
|
|
516
|
+
return {
|
|
517
|
+
error: `Connected account '${explicitId}' belongs to user_id '${accountUserId}', ` +
|
|
518
|
+
`but '${userId}' was requested. Use matching user_id or omit user_id when providing connected_account_id.`,
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
return { connectedAccountId: explicitId, userId: accountUserId || undefined };
|
|
500
522
|
}
|
|
501
523
|
catch (err) {
|
|
502
524
|
return {
|
|
@@ -87,7 +87,14 @@ export declare function createComposioConnectionsTool(client: ComposioClient, _c
|
|
|
87
87
|
text: string;
|
|
88
88
|
}[];
|
|
89
89
|
details: {
|
|
90
|
+
hints?: {
|
|
91
|
+
toolkit: string;
|
|
92
|
+
connected_user_ids: string[];
|
|
93
|
+
message: string;
|
|
94
|
+
}[] | undefined;
|
|
90
95
|
action: string;
|
|
96
|
+
checked_user_id: string | undefined;
|
|
97
|
+
user_id_explicit: boolean;
|
|
91
98
|
count: number;
|
|
92
99
|
connections: {
|
|
93
100
|
toolkit: string;
|
|
@@ -13,7 +13,7 @@ export const ComposioManageConnectionsToolSchema = Type.Object({
|
|
|
13
13
|
description: "Multiple toolkits to check status for",
|
|
14
14
|
})),
|
|
15
15
|
user_id: Type.Optional(Type.String({
|
|
16
|
-
description: "User ID for session scoping
|
|
16
|
+
description: "User ID for session scoping. Strongly recommended to avoid checking the wrong scope.",
|
|
17
17
|
})),
|
|
18
18
|
statuses: Type.Optional(Type.Array(Type.String(), {
|
|
19
19
|
description: "Optional connection statuses filter for 'accounts' (e.g., ['ACTIVE'])",
|
|
@@ -34,6 +34,7 @@ export function createComposioConnectionsTool(client, _config) {
|
|
|
34
34
|
async execute(_toolCallId, params) {
|
|
35
35
|
const action = String(params.action || "status");
|
|
36
36
|
const userId = typeof params.user_id === "string" ? params.user_id : undefined;
|
|
37
|
+
const userIdWasExplicit = typeof params.user_id === "string" && params.user_id.trim().length > 0;
|
|
37
38
|
try {
|
|
38
39
|
switch (action) {
|
|
39
40
|
case "list": {
|
|
@@ -119,13 +120,32 @@ export function createComposioConnectionsTool(client, _config) {
|
|
|
119
120
|
toolkitsToCheck = params.toolkits.filter((t) => typeof t === "string" && t.trim() !== "");
|
|
120
121
|
}
|
|
121
122
|
const statuses = await client.getConnectionStatus(toolkitsToCheck, userId);
|
|
123
|
+
const disconnectedToolkits = statuses.filter((s) => !s.connected).map((s) => s.toolkit);
|
|
124
|
+
const hints = [];
|
|
125
|
+
if (!userIdWasExplicit) {
|
|
126
|
+
for (const toolkit of disconnectedToolkits) {
|
|
127
|
+
const activeUserIds = await client.findActiveUserIdsForToolkit(toolkit);
|
|
128
|
+
if (activeUserIds.length === 0)
|
|
129
|
+
continue;
|
|
130
|
+
hints.push({
|
|
131
|
+
toolkit,
|
|
132
|
+
connected_user_ids: activeUserIds,
|
|
133
|
+
message: `No user_id was provided, so status checked the default scope. ` +
|
|
134
|
+
`'${toolkit}' has ACTIVE accounts under: ${activeUserIds.join(", ")}. ` +
|
|
135
|
+
"Pass user_id explicitly for deterministic results.",
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
122
139
|
const response = {
|
|
123
140
|
action: "status",
|
|
141
|
+
checked_user_id: statuses[0]?.userId,
|
|
142
|
+
user_id_explicit: userIdWasExplicit,
|
|
124
143
|
count: statuses.length,
|
|
125
144
|
connections: statuses.map((s) => ({
|
|
126
145
|
toolkit: s.toolkit,
|
|
127
146
|
connected: s.connected,
|
|
128
147
|
})),
|
|
148
|
+
...(hints.length > 0 ? { hints } : {}),
|
|
129
149
|
};
|
|
130
150
|
return {
|
|
131
151
|
content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
|
package/dist/tools/execute.js
CHANGED
|
@@ -10,7 +10,7 @@ export const ComposioExecuteToolSchema = Type.Object({
|
|
|
10
10
|
description: "Tool arguments matching the tool's parameter schema",
|
|
11
11
|
}),
|
|
12
12
|
user_id: Type.Optional(Type.String({
|
|
13
|
-
description: "User ID for session scoping
|
|
13
|
+
description: "User ID for session scoping. Strongly recommended to avoid executing in the wrong scope.",
|
|
14
14
|
})),
|
|
15
15
|
connected_account_id: Type.Optional(Type.String({
|
|
16
16
|
description: "Optional connected account ID to pin execution to a specific account when multiple are connected",
|