@mastra/editor 0.13.8 → 0.13.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/CHANGELOG.md +17 -0
- package/dist/arcade.cjs +645 -292
- package/dist/arcade.cjs.map +1 -1
- package/dist/arcade.d.cts +47 -46
- package/dist/arcade.d.cts.map +1 -0
- package/dist/arcade.d.ts +47 -46
- package/dist/arcade.d.ts.map +1 -0
- package/dist/arcade.js +642 -263
- package/dist/arcade.js.map +1 -1
- package/dist/composio.cjs +336 -361
- package/dist/composio.cjs.map +1 -1
- package/dist/composio.d.cts +52 -51
- package/dist/composio.d.cts.map +1 -0
- package/dist/composio.d.ts +52 -51
- package/dist/composio.d.ts.map +1 -0
- package/dist/composio.js +330 -329
- package/dist/composio.js.map +1 -1
- package/dist/ee/index.cjs +199 -191
- package/dist/ee/index.cjs.map +1 -1
- package/dist/ee/index.d.cts +47 -44
- package/dist/ee/index.d.cts.map +1 -0
- package/dist/ee/index.d.ts +47 -44
- package/dist/ee/index.d.ts.map +1 -0
- package/dist/ee/index.js +180 -158
- package/dist/ee/index.js.map +1 -1
- package/dist/index.cjs +2459 -3145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +461 -478
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +461 -478
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2442 -2797
- package/dist/index.js.map +1 -1
- package/dist/storage/index.cjs +24 -35
- package/dist/storage/index.d.cts +2 -1
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.js +2 -14
- package/package.json +11 -11
- package/dist/storage/index.cjs.map +0 -1
- package/dist/storage/index.js.map +0 -1
package/dist/composio.js
CHANGED
|
@@ -1,348 +1,349 @@
|
|
|
1
|
-
// src/providers/composio.ts
|
|
2
1
|
import { BaseToolProvider } from "@mastra/core/tool-provider";
|
|
3
2
|
import { MASTRA_RESOURCE_ID_KEY } from "@mastra/core/request-context";
|
|
4
3
|
import { Composio } from "@composio/core";
|
|
5
4
|
import { MastraProvider } from "@composio/mastra";
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
//#region src/providers/composio.ts
|
|
6
|
+
const COMPOSIO_PROVIDER_ID = "composio";
|
|
7
|
+
const DEFAULT_INTERNAL_USER_ID = "default";
|
|
8
|
+
/**
|
|
9
|
+
* Composio implementation of the {@link BaseToolProvider} contract.
|
|
10
|
+
*
|
|
11
|
+
* Discovery (`listAllToolkits`, `listAllTools`) uses the raw Composio
|
|
12
|
+
* client. Runtime (`resolveToolsVNext`) uses {@link MastraProvider} so resolved
|
|
13
|
+
* tools are already in `createTool()` shape; each tool gets a
|
|
14
|
+
* `beforeExecute` modifier that injects
|
|
15
|
+
* `connectedAccountId = connectionId`, and `outputSchema` is cleared
|
|
16
|
+
* because Composio returns union schemas that Mastra's runtime rejects.
|
|
17
|
+
*
|
|
18
|
+
* Allowlist filtering is layered by {@link BaseToolProvider}; this class
|
|
19
|
+
* never reads `allowedToolkits` / `allowedTools` directly.
|
|
20
|
+
*/
|
|
8
21
|
var ComposioToolProvider = class extends BaseToolProvider {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
message: err instanceof Error ? err.message : "Composio SDK reachability check failed"
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
// ── helpers ───────────────────────────────────────────────────────────
|
|
256
|
-
/**
|
|
257
|
-
* Resolve the single ENABLED auth config for `toolkit`. Throws if zero
|
|
258
|
-
* or multiple configs match — the admin must enable exactly one in the
|
|
259
|
-
* Composio dashboard before agents can connect.
|
|
260
|
-
*/
|
|
261
|
-
async resolveAuthConfig(toolkit) {
|
|
262
|
-
const composio = this.getRawClient();
|
|
263
|
-
const response = await composio.authConfigs.list({ toolkit });
|
|
264
|
-
const enabled = response.items.filter((item) => item.status === "ENABLED");
|
|
265
|
-
if (enabled.length === 0) {
|
|
266
|
-
throw new Error(
|
|
267
|
-
`[composio] No ENABLED auth config for toolkit "${toolkit}". Enable one in the Composio dashboard.`
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
if (enabled.length > 1) {
|
|
271
|
-
const ids = enabled.map((item) => item.id).join(", ");
|
|
272
|
-
throw new Error(
|
|
273
|
-
`[composio] Multiple ENABLED auth configs for toolkit "${toolkit}" (${ids}). Keep exactly one enabled.`
|
|
274
|
-
);
|
|
275
|
-
}
|
|
276
|
-
return { id: enabled[0].id, authScheme: enabled[0].authScheme };
|
|
277
|
-
}
|
|
22
|
+
constructor(config) {
|
|
23
|
+
super({
|
|
24
|
+
allowedToolkits: config.allowedToolkits,
|
|
25
|
+
allowedTools: config.allowedTools,
|
|
26
|
+
defaultScope: config.defaultScope
|
|
27
|
+
});
|
|
28
|
+
this.info = {
|
|
29
|
+
id: COMPOSIO_PROVIDER_ID,
|
|
30
|
+
name: "Composio",
|
|
31
|
+
description: "Access 10,000+ tools from 150+ apps via Composio"
|
|
32
|
+
};
|
|
33
|
+
this.capabilities = {
|
|
34
|
+
multipleConnectionsPerToolkit: true,
|
|
35
|
+
batchConnectionStatus: true,
|
|
36
|
+
reauthorizeReusesConnectionId: true,
|
|
37
|
+
supportsRevoke: true
|
|
38
|
+
};
|
|
39
|
+
this.rawClient = null;
|
|
40
|
+
this.mastraClient = null;
|
|
41
|
+
this.apiKey = config.apiKey;
|
|
42
|
+
}
|
|
43
|
+
getRawClient() {
|
|
44
|
+
if (!this.rawClient) this.rawClient = new Composio({ apiKey: this.apiKey });
|
|
45
|
+
return this.rawClient;
|
|
46
|
+
}
|
|
47
|
+
getMastraClient() {
|
|
48
|
+
if (!this.mastraClient) this.mastraClient = new Composio({
|
|
49
|
+
apiKey: this.apiKey,
|
|
50
|
+
provider: new MastraProvider()
|
|
51
|
+
});
|
|
52
|
+
return this.mastraClient;
|
|
53
|
+
}
|
|
54
|
+
async listAllToolkits() {
|
|
55
|
+
return (await this.getRawClient().toolkits.get({})).map((tk) => ({
|
|
56
|
+
slug: tk.slug,
|
|
57
|
+
name: tk.name,
|
|
58
|
+
description: tk.meta?.description,
|
|
59
|
+
icon: tk.meta?.logo
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
async listAllTools(opts) {
|
|
63
|
+
const composio = this.getRawClient();
|
|
64
|
+
const limit = opts.perPage;
|
|
65
|
+
const fallbackToolkits = this.allowedToolkits.length > 0 ? [...this.allowedToolkits] : void 0;
|
|
66
|
+
const query = opts.toolkit ? {
|
|
67
|
+
toolkits: [opts.toolkit],
|
|
68
|
+
limit,
|
|
69
|
+
search: opts.search
|
|
70
|
+
} : fallbackToolkits ? {
|
|
71
|
+
toolkits: fallbackToolkits,
|
|
72
|
+
limit,
|
|
73
|
+
search: opts.search
|
|
74
|
+
} : opts.search ? {
|
|
75
|
+
search: opts.search,
|
|
76
|
+
limit
|
|
77
|
+
} : {
|
|
78
|
+
toolkits: [],
|
|
79
|
+
limit
|
|
80
|
+
};
|
|
81
|
+
let rawTools = [];
|
|
82
|
+
try {
|
|
83
|
+
rawTools = await composio.tools.getRawComposioTools(query);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
console.warn(`[ComposioToolProvider] listAllTools failed for query ${JSON.stringify(query)} — returning empty page`, err);
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
data: rawTools.map((tool) => ({
|
|
89
|
+
slug: tool.slug,
|
|
90
|
+
name: tool.name ?? tool.slug,
|
|
91
|
+
description: tool.description,
|
|
92
|
+
toolkit: tool.toolkit?.slug ?? opts.toolkit ?? ""
|
|
93
|
+
})),
|
|
94
|
+
pagination: {
|
|
95
|
+
page: opts.page ?? 1,
|
|
96
|
+
perPage: limit,
|
|
97
|
+
hasMore: limit !== void 0 && rawTools.length >= limit
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async resolveToolsVNext(opts) {
|
|
102
|
+
if (opts.toolSlugs.length === 0) return {};
|
|
103
|
+
const internalUserId = opts.authorId && opts.authorId.length > 0 ? opts.authorId : resolveInternalUserId(opts.requestContext);
|
|
104
|
+
const mastraTools = await this.getMastraClient().tools.get(internalUserId, { tools: opts.toolSlugs }, { beforeExecute: ({ params }) => {
|
|
105
|
+
if (opts.scope !== "caller-supplied") params.connectedAccountId = opts.connectionId;
|
|
106
|
+
return params;
|
|
107
|
+
} });
|
|
108
|
+
const result = {};
|
|
109
|
+
for (const [key, tool] of Object.entries(mastraTools ?? {})) {
|
|
110
|
+
if (!tool) continue;
|
|
111
|
+
const slug = tool.id ?? key;
|
|
112
|
+
try {
|
|
113
|
+
tool.outputSchema = void 0;
|
|
114
|
+
} catch {}
|
|
115
|
+
const descOverride = opts.toolMeta?.[slug]?.description;
|
|
116
|
+
if (descOverride) try {
|
|
117
|
+
tool.description = descOverride;
|
|
118
|
+
} catch {}
|
|
119
|
+
result[slug] = tool;
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
async authorize(opts) {
|
|
124
|
+
const composio = this.getRawClient();
|
|
125
|
+
const { id: authConfigId, authScheme } = await this.resolveAuthConfig(opts.toolkit);
|
|
126
|
+
const internalUserId = opts.connectionId || DEFAULT_INTERNAL_USER_ID;
|
|
127
|
+
const initiateConfig = opts.config && Object.keys(opts.config).length > 0 && authScheme ? {
|
|
128
|
+
authScheme,
|
|
129
|
+
val: opts.config
|
|
130
|
+
} : void 0;
|
|
131
|
+
const request = initiateConfig ? await composio.connectedAccounts.initiate(internalUserId, authConfigId, {
|
|
132
|
+
allowMultiple: true,
|
|
133
|
+
config: initiateConfig
|
|
134
|
+
}) : await composio.connectedAccounts.link(internalUserId, authConfigId);
|
|
135
|
+
if (!request.redirectUrl) throw new Error(`[composio] authorize did not return a redirectUrl for toolkit "${opts.toolkit}"`);
|
|
136
|
+
return {
|
|
137
|
+
url: request.redirectUrl,
|
|
138
|
+
authId: request.id
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
async listConnectionFields({ toolkit }) {
|
|
142
|
+
const composio = this.getRawClient();
|
|
143
|
+
const { authScheme } = await this.resolveAuthConfig(toolkit);
|
|
144
|
+
if (!authScheme) return [];
|
|
145
|
+
return (await composio.toolkits.getConnectedAccountInitiationFields(toolkit, authScheme, { requiredOnly: false })).map((f) => ({
|
|
146
|
+
name: f.name,
|
|
147
|
+
displayName: f.displayName,
|
|
148
|
+
description: f.description,
|
|
149
|
+
type: coerceFieldType(f.type),
|
|
150
|
+
required: f.required ?? false,
|
|
151
|
+
default: f.default ?? void 0
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
async getAuthStatus(authId) {
|
|
155
|
+
switch ((await this.getRawClient().connectedAccounts.get(authId)).status) {
|
|
156
|
+
case "ACTIVE": return "completed";
|
|
157
|
+
case "INITIALIZING":
|
|
158
|
+
case "INITIATED": return "pending";
|
|
159
|
+
case "FAILED":
|
|
160
|
+
case "EXPIRED":
|
|
161
|
+
case "INACTIVE": return "failed";
|
|
162
|
+
default: return "pending";
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async getConnectionStatus(opts) {
|
|
166
|
+
if (opts.items.length === 0) return {};
|
|
167
|
+
const composio = this.getRawClient();
|
|
168
|
+
const toolkitSlugs = Array.from(new Set(opts.items.map((i) => i.toolkit)));
|
|
169
|
+
const list = await composio.connectedAccounts.list({ toolkitSlugs });
|
|
170
|
+
const liveById = /* @__PURE__ */ new Map();
|
|
171
|
+
for (const item of list.items) liveById.set(item.id, {
|
|
172
|
+
status: item.status,
|
|
173
|
+
isDisabled: item.isDisabled
|
|
174
|
+
});
|
|
175
|
+
const result = {};
|
|
176
|
+
for (const { connectionId } of opts.items) {
|
|
177
|
+
const live = liveById.get(connectionId);
|
|
178
|
+
result[connectionId] = { connected: live ? live.status === "ACTIVE" && !live.isDisabled : false };
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
async listConnections(opts) {
|
|
183
|
+
const composio = this.getRawClient();
|
|
184
|
+
const page = opts.page ?? 1;
|
|
185
|
+
const perPage = clampLimit(opts.perPage);
|
|
186
|
+
const userIds = resolveUserIds(opts);
|
|
187
|
+
if (userIds && userIds.length === 0) return {
|
|
188
|
+
items: [],
|
|
189
|
+
pagination: {
|
|
190
|
+
page,
|
|
191
|
+
perPage,
|
|
192
|
+
hasMore: false
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const list = await composio.connectedAccounts.list({
|
|
196
|
+
toolkitSlugs: [opts.toolkit],
|
|
197
|
+
...userIds ? { userIds } : {},
|
|
198
|
+
limit: perPage
|
|
199
|
+
});
|
|
200
|
+
const items = (list.items ?? []).map((account) => ({
|
|
201
|
+
connectionId: account.id,
|
|
202
|
+
status: mapComposioStatus(account.status, account.isDisabled),
|
|
203
|
+
createdAt: account.createdAt,
|
|
204
|
+
authorId: account.user_id
|
|
205
|
+
}));
|
|
206
|
+
const nextCursor = list.nextCursor ?? null;
|
|
207
|
+
return {
|
|
208
|
+
items,
|
|
209
|
+
pagination: {
|
|
210
|
+
page,
|
|
211
|
+
perPage,
|
|
212
|
+
hasMore: typeof nextCursor === "string" && nextCursor.length > 0
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Revoke a Composio connected account via
|
|
218
|
+
* `DELETE /api/v3/connected_accounts/:nanoid`. Composio performs a soft
|
|
219
|
+
* delete and responds with `{ success: boolean }`.
|
|
220
|
+
*
|
|
221
|
+
* Treats a 404 (account already deleted or never existed) as success so
|
|
222
|
+
* the caller can drop its local pin without an error path. A `success:
|
|
223
|
+
* false` response means the provider refused the delete and is surfaced
|
|
224
|
+
* as an error so the caller does not delete its local row.
|
|
225
|
+
*/
|
|
226
|
+
async revokeConnection(connectionId) {
|
|
227
|
+
const composio = this.getRawClient();
|
|
228
|
+
try {
|
|
229
|
+
const res = await composio.connectedAccounts.delete(connectionId);
|
|
230
|
+
if (res && res.success === false) throw new Error(`Composio refused to delete connected account ${connectionId} (success=false)`);
|
|
231
|
+
} catch (err) {
|
|
232
|
+
if (isNotFoundError(err)) return;
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async getHealth() {
|
|
237
|
+
try {
|
|
238
|
+
await this.getRawClient().toolkits.get({ limit: 1 });
|
|
239
|
+
return { ok: true };
|
|
240
|
+
} catch (err) {
|
|
241
|
+
return {
|
|
242
|
+
ok: false,
|
|
243
|
+
message: err instanceof Error ? err.message : "Composio SDK reachability check failed"
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Resolve the single ENABLED auth config for `toolkit`. Throws if zero
|
|
249
|
+
* or multiple configs match — the admin must enable exactly one in the
|
|
250
|
+
* Composio dashboard before agents can connect.
|
|
251
|
+
*/
|
|
252
|
+
async resolveAuthConfig(toolkit) {
|
|
253
|
+
const enabled = (await this.getRawClient().authConfigs.list({ toolkit })).items.filter((item) => item.status === "ENABLED");
|
|
254
|
+
if (enabled.length === 0) throw new Error(`[composio] No ENABLED auth config for toolkit "${toolkit}". Enable one in the Composio dashboard.`);
|
|
255
|
+
if (enabled.length > 1) {
|
|
256
|
+
const ids = enabled.map((item) => item.id).join(", ");
|
|
257
|
+
throw new Error(`[composio] Multiple ENABLED auth configs for toolkit "${toolkit}" (${ids}). Keep exactly one enabled.`);
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
id: enabled[0].id,
|
|
261
|
+
authScheme: enabled[0].authScheme
|
|
262
|
+
};
|
|
263
|
+
}
|
|
278
264
|
};
|
|
265
|
+
/**
|
|
266
|
+
* Best-effort 404 detection across the various error shapes the Composio
|
|
267
|
+
* SDK surfaces (typed error with `statusCode`, HTTP-like error with
|
|
268
|
+
* `status`, or a plain message containing "404" / "not found").
|
|
269
|
+
*/
|
|
279
270
|
function isNotFoundError(err) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
271
|
+
if (!err || typeof err !== "object") return false;
|
|
272
|
+
const e = err;
|
|
273
|
+
if (e.statusCode === 404 || e.status === 404) return true;
|
|
274
|
+
const msg = typeof e.message === "string" ? e.message.toLowerCase() : "";
|
|
275
|
+
return msg.includes("not found") || msg.includes("404");
|
|
285
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Composio reports a free-form `type` string. Map common values to our
|
|
279
|
+
* generic ConnectionField type vocabulary; everything else falls back to
|
|
280
|
+
* `'string'`.
|
|
281
|
+
*/
|
|
286
282
|
function coerceFieldType(type) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
default:
|
|
297
|
-
return "string";
|
|
298
|
-
}
|
|
283
|
+
switch (type.toLowerCase()) {
|
|
284
|
+
case "number":
|
|
285
|
+
case "integer":
|
|
286
|
+
case "int":
|
|
287
|
+
case "float": return "number";
|
|
288
|
+
case "bool":
|
|
289
|
+
case "boolean": return "boolean";
|
|
290
|
+
default: return "string";
|
|
291
|
+
}
|
|
299
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Map Composio account status + `isDisabled` to the {@link ExistingConnection}
|
|
295
|
+
* status vocabulary surfaced to the picker UI.
|
|
296
|
+
*/
|
|
300
297
|
function mapComposioStatus(status, isDisabled) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
case "INACTIVE":
|
|
312
|
-
return "inactive";
|
|
313
|
-
default:
|
|
314
|
-
return "pending";
|
|
315
|
-
}
|
|
298
|
+
if (isDisabled) return "inactive";
|
|
299
|
+
switch (status) {
|
|
300
|
+
case "ACTIVE": return "active";
|
|
301
|
+
case "INITIALIZING":
|
|
302
|
+
case "INITIATED": return "pending";
|
|
303
|
+
case "FAILED":
|
|
304
|
+
case "EXPIRED": return "failed";
|
|
305
|
+
case "INACTIVE": return "inactive";
|
|
306
|
+
default: return "pending";
|
|
307
|
+
}
|
|
316
308
|
}
|
|
317
|
-
|
|
309
|
+
const MASTRA_USER_KEY = "mastra__user";
|
|
310
|
+
/**
|
|
311
|
+
* Read the internal user id (Composio `userId`) from per-request context.
|
|
312
|
+
*
|
|
313
|
+
* The runtime fan-out is responsible for stamping the agent's resolved
|
|
314
|
+
* author id (or `'default'`) into `requestContext` under
|
|
315
|
+
* {@link MASTRA_RESOURCE_ID_KEY}.
|
|
316
|
+
*/
|
|
318
317
|
function resolveInternalUserId(requestContext) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
return id;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return DEFAULT_INTERNAL_USER_ID;
|
|
318
|
+
const resourceId = requestContext?.[MASTRA_RESOURCE_ID_KEY];
|
|
319
|
+
if (typeof resourceId === "string" && resourceId.length > 0) return resourceId;
|
|
320
|
+
const user = requestContext?.[MASTRA_USER_KEY];
|
|
321
|
+
if (user && typeof user === "object" && "id" in user) {
|
|
322
|
+
const id = user.id;
|
|
323
|
+
if (typeof id === "string" && id.length > 0) return id;
|
|
324
|
+
}
|
|
325
|
+
return DEFAULT_INTERNAL_USER_ID;
|
|
331
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Resolve `userIds[]` from `listConnections` opts.
|
|
329
|
+
*
|
|
330
|
+
* - If `userIds` is provided, use it as-is (including empty array, which
|
|
331
|
+
* means "no buckets to list against").
|
|
332
|
+
* - If `userId` is provided, normalize to `[userId]`.
|
|
333
|
+
* - Otherwise fall back to the default internal user id (single-bucket).
|
|
334
|
+
*/
|
|
332
335
|
function resolveUserIds(opts) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
+
if (Array.isArray(opts.userIds)) return opts.userIds;
|
|
337
|
+
if (typeof opts.userId === "string" && opts.userId.length > 0) return [opts.userId];
|
|
338
|
+
return [DEFAULT_INTERNAL_USER_ID];
|
|
336
339
|
}
|
|
337
|
-
|
|
338
|
-
|
|
340
|
+
const DEFAULT_LIMIT = 50;
|
|
341
|
+
const MAX_LIMIT = 200;
|
|
339
342
|
function clampLimit(limit) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
return Math.min(Math.floor(limit), MAX_LIMIT);
|
|
343
|
+
if (typeof limit !== "number" || !Number.isFinite(limit) || limit <= 0) return DEFAULT_LIMIT;
|
|
344
|
+
return Math.min(Math.floor(limit), MAX_LIMIT);
|
|
344
345
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
346
|
+
//#endregion
|
|
347
|
+
export { ComposioToolProvider };
|
|
348
|
+
|
|
348
349
|
//# sourceMappingURL=composio.js.map
|