@everworker/oneringai 0.4.2 → 0.4.3
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 +30 -8
- package/dist/{IProvider-CNJqZItJ.d.cts → IProvider-B8sqUzJG.d.cts} +36 -6
- package/dist/{IProvider-B6hqVVq8.d.ts → IProvider-CxDUGl6n.d.ts} +36 -6
- package/dist/{ImageModel-B64HX3lN.d.cts → ImageModel-Ds5_6sf7.d.cts} +1 -1
- package/dist/{ImageModel-DU-y_WOb.d.ts → ImageModel-OWbA277F.d.ts} +1 -1
- package/dist/capabilities/agents/index.d.cts +2 -2
- package/dist/capabilities/agents/index.d.ts +2 -2
- package/dist/capabilities/images/index.cjs +251 -106
- package/dist/capabilities/images/index.cjs.map +1 -1
- package/dist/capabilities/images/index.d.cts +2 -2
- package/dist/capabilities/images/index.d.ts +2 -2
- package/dist/capabilities/images/index.js +251 -106
- package/dist/capabilities/images/index.js.map +1 -1
- package/dist/{index-9VOnAX17.d.ts → index-CEjKTeSb.d.cts} +857 -2
- package/dist/{index-BMjyFNJQ.d.cts → index-CzGnmqOs.d.ts} +857 -2
- package/dist/index.cjs +1303 -432
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +234 -904
- package/dist/index.d.ts +234 -904
- package/dist/index.js +1286 -417
- package/dist/index.js.map +1 -1
- package/dist/shared/index.cjs +9 -0
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.js +9 -0
- package/dist/shared/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import * as z from 'zod/v4';
|
|
|
19
19
|
import spawn$1 from 'cross-spawn';
|
|
20
20
|
import process2 from 'process';
|
|
21
21
|
import { PassThrough } from 'stream';
|
|
22
|
-
import * as
|
|
22
|
+
import * as fs17 from 'fs/promises';
|
|
23
23
|
import { stat, readFile, mkdir, writeFile, readdir } from 'fs/promises';
|
|
24
24
|
import * as simpleIcons from 'simple-icons';
|
|
25
25
|
import { exec, spawn } from 'child_process';
|
|
@@ -163,6 +163,12 @@ var init_MemoryStorage = __esm({
|
|
|
163
163
|
size() {
|
|
164
164
|
return this.tokens.size;
|
|
165
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* List all storage keys (for account enumeration)
|
|
168
|
+
*/
|
|
169
|
+
async listKeys() {
|
|
170
|
+
return Array.from(this.tokens.keys());
|
|
171
|
+
}
|
|
166
172
|
};
|
|
167
173
|
}
|
|
168
174
|
});
|
|
@@ -180,14 +186,23 @@ var init_TokenStore = __esm({
|
|
|
180
186
|
this.storage = storage || new MemoryStorage();
|
|
181
187
|
}
|
|
182
188
|
/**
|
|
183
|
-
* Get user-scoped storage key
|
|
184
|
-
*
|
|
185
|
-
*
|
|
189
|
+
* Get user-scoped (and optionally account-scoped) storage key
|
|
190
|
+
*
|
|
191
|
+
* Key format (backward compatible):
|
|
192
|
+
* - No userId, no accountId → baseKey
|
|
193
|
+
* - userId only → baseKey:userId
|
|
194
|
+
* - userId + accountId → baseKey:userId:accountId
|
|
195
|
+
* - accountId only → baseKey:default:accountId
|
|
186
196
|
*
|
|
187
197
|
* @param userId - User identifier (optional, defaults to single-user mode)
|
|
188
|
-
* @
|
|
198
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
199
|
+
* @returns Storage key scoped to user and account
|
|
189
200
|
*/
|
|
190
|
-
getScopedKey(userId) {
|
|
201
|
+
getScopedKey(userId, accountId) {
|
|
202
|
+
if (accountId) {
|
|
203
|
+
const userPart = userId && userId !== "default" ? userId : "default";
|
|
204
|
+
return `${this.baseStorageKey}:${userPart}:${accountId}`;
|
|
205
|
+
}
|
|
191
206
|
if (!userId || userId === "default") {
|
|
192
207
|
return this.baseStorageKey;
|
|
193
208
|
}
|
|
@@ -197,8 +212,9 @@ var init_TokenStore = __esm({
|
|
|
197
212
|
* Store token (encrypted by storage layer)
|
|
198
213
|
* @param tokenResponse - Token response from OAuth provider
|
|
199
214
|
* @param userId - Optional user identifier for multi-user support
|
|
215
|
+
* @param accountId - Optional account alias for multi-account support
|
|
200
216
|
*/
|
|
201
|
-
async storeToken(tokenResponse, userId) {
|
|
217
|
+
async storeToken(tokenResponse, userId, accountId) {
|
|
202
218
|
if (!tokenResponse.access_token) {
|
|
203
219
|
throw new Error("OAuth response missing required access_token field");
|
|
204
220
|
}
|
|
@@ -216,39 +232,46 @@ var init_TokenStore = __esm({
|
|
|
216
232
|
scope: tokenResponse.scope,
|
|
217
233
|
obtained_at: Date.now()
|
|
218
234
|
};
|
|
219
|
-
const key = this.getScopedKey(userId);
|
|
235
|
+
const key = this.getScopedKey(userId, accountId);
|
|
220
236
|
await this.storage.storeToken(key, token);
|
|
221
237
|
}
|
|
222
238
|
/**
|
|
223
239
|
* Get access token
|
|
224
240
|
* @param userId - Optional user identifier for multi-user support
|
|
241
|
+
* @param accountId - Optional account alias for multi-account support
|
|
225
242
|
*/
|
|
226
|
-
async getAccessToken(userId) {
|
|
227
|
-
const key = this.getScopedKey(userId);
|
|
243
|
+
async getAccessToken(userId, accountId) {
|
|
244
|
+
const key = this.getScopedKey(userId, accountId);
|
|
228
245
|
const token = await this.storage.getToken(key);
|
|
229
246
|
if (!token) {
|
|
230
|
-
|
|
247
|
+
const userLabel = userId ? `user: ${userId}` : "default user";
|
|
248
|
+
const accountLabel = accountId ? `, account: ${accountId}` : "";
|
|
249
|
+
throw new Error(`No token stored for ${userLabel}${accountLabel}`);
|
|
231
250
|
}
|
|
232
251
|
return token.access_token;
|
|
233
252
|
}
|
|
234
253
|
/**
|
|
235
254
|
* Get refresh token
|
|
236
255
|
* @param userId - Optional user identifier for multi-user support
|
|
256
|
+
* @param accountId - Optional account alias for multi-account support
|
|
237
257
|
*/
|
|
238
|
-
async getRefreshToken(userId) {
|
|
239
|
-
const key = this.getScopedKey(userId);
|
|
258
|
+
async getRefreshToken(userId, accountId) {
|
|
259
|
+
const key = this.getScopedKey(userId, accountId);
|
|
240
260
|
const token = await this.storage.getToken(key);
|
|
241
261
|
if (!token?.refresh_token) {
|
|
242
|
-
|
|
262
|
+
const userLabel = userId ? `user: ${userId}` : "default user";
|
|
263
|
+
const accountLabel = accountId ? `, account: ${accountId}` : "";
|
|
264
|
+
throw new Error(`No refresh token available for ${userLabel}${accountLabel}`);
|
|
243
265
|
}
|
|
244
266
|
return token.refresh_token;
|
|
245
267
|
}
|
|
246
268
|
/**
|
|
247
269
|
* Check if has refresh token
|
|
248
270
|
* @param userId - Optional user identifier for multi-user support
|
|
271
|
+
* @param accountId - Optional account alias for multi-account support
|
|
249
272
|
*/
|
|
250
|
-
async hasRefreshToken(userId) {
|
|
251
|
-
const key = this.getScopedKey(userId);
|
|
273
|
+
async hasRefreshToken(userId, accountId) {
|
|
274
|
+
const key = this.getScopedKey(userId, accountId);
|
|
252
275
|
const token = await this.storage.getToken(key);
|
|
253
276
|
return !!token?.refresh_token;
|
|
254
277
|
}
|
|
@@ -257,9 +280,10 @@ var init_TokenStore = __esm({
|
|
|
257
280
|
*
|
|
258
281
|
* @param bufferSeconds - Refresh this many seconds before expiry (default: 300 = 5 min)
|
|
259
282
|
* @param userId - Optional user identifier for multi-user support
|
|
283
|
+
* @param accountId - Optional account alias for multi-account support
|
|
260
284
|
*/
|
|
261
|
-
async isValid(bufferSeconds = 300, userId) {
|
|
262
|
-
const key = this.getScopedKey(userId);
|
|
285
|
+
async isValid(bufferSeconds = 300, userId, accountId) {
|
|
286
|
+
const key = this.getScopedKey(userId, accountId);
|
|
263
287
|
const token = await this.storage.getToken(key);
|
|
264
288
|
if (!token) {
|
|
265
289
|
return false;
|
|
@@ -271,19 +295,46 @@ var init_TokenStore = __esm({
|
|
|
271
295
|
/**
|
|
272
296
|
* Clear stored token
|
|
273
297
|
* @param userId - Optional user identifier for multi-user support
|
|
298
|
+
* @param accountId - Optional account alias for multi-account support
|
|
274
299
|
*/
|
|
275
|
-
async clear(userId) {
|
|
276
|
-
const key = this.getScopedKey(userId);
|
|
300
|
+
async clear(userId, accountId) {
|
|
301
|
+
const key = this.getScopedKey(userId, accountId);
|
|
277
302
|
await this.storage.deleteToken(key);
|
|
278
303
|
}
|
|
279
304
|
/**
|
|
280
305
|
* Get full token info
|
|
281
306
|
* @param userId - Optional user identifier for multi-user support
|
|
307
|
+
* @param accountId - Optional account alias for multi-account support
|
|
282
308
|
*/
|
|
283
|
-
async getTokenInfo(userId) {
|
|
284
|
-
const key = this.getScopedKey(userId);
|
|
309
|
+
async getTokenInfo(userId, accountId) {
|
|
310
|
+
const key = this.getScopedKey(userId, accountId);
|
|
285
311
|
return this.storage.getToken(key);
|
|
286
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* List account aliases for a user on this connector.
|
|
315
|
+
* Returns account IDs that have stored tokens.
|
|
316
|
+
*
|
|
317
|
+
* @param userId - Optional user identifier
|
|
318
|
+
* @returns Array of account aliases (e.g., ['work', 'personal'])
|
|
319
|
+
*/
|
|
320
|
+
async listAccounts(userId) {
|
|
321
|
+
if (!this.storage.listKeys) {
|
|
322
|
+
return [];
|
|
323
|
+
}
|
|
324
|
+
const allKeys = await this.storage.listKeys();
|
|
325
|
+
const userPart = userId && userId !== "default" ? userId : "default";
|
|
326
|
+
const prefix = `${this.baseStorageKey}:${userPart}:`;
|
|
327
|
+
const accounts = [];
|
|
328
|
+
for (const key of allKeys) {
|
|
329
|
+
if (key.startsWith(prefix)) {
|
|
330
|
+
const accountId = key.slice(prefix.length);
|
|
331
|
+
if (accountId && !accountId.includes(":")) {
|
|
332
|
+
accounts.push(accountId);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return accounts;
|
|
337
|
+
}
|
|
287
338
|
};
|
|
288
339
|
}
|
|
289
340
|
});
|
|
@@ -324,20 +375,28 @@ var init_AuthCodePKCE = __esm({
|
|
|
324
375
|
this.tokenStore = new TokenStore(storageKey, config.storage);
|
|
325
376
|
}
|
|
326
377
|
tokenStore;
|
|
327
|
-
// Store PKCE data per user with timestamps for cleanup
|
|
378
|
+
// Store PKCE data per user+account with timestamps for cleanup
|
|
328
379
|
codeVerifiers = /* @__PURE__ */ new Map();
|
|
329
380
|
states = /* @__PURE__ */ new Map();
|
|
330
|
-
// Store refresh locks per user to prevent concurrent refresh
|
|
381
|
+
// Store refresh locks per user+account to prevent concurrent refresh
|
|
331
382
|
refreshLocks = /* @__PURE__ */ new Map();
|
|
332
383
|
// PKCE data TTL: 15 minutes (auth flows should complete within this time)
|
|
333
384
|
PKCE_TTL = 15 * 60 * 1e3;
|
|
385
|
+
/**
|
|
386
|
+
* Build a map key from userId and accountId for internal PKCE/state/lock maps.
|
|
387
|
+
*/
|
|
388
|
+
getMapKey(userId, accountId) {
|
|
389
|
+
const userPart = userId || "default";
|
|
390
|
+
return accountId ? `${userPart}:${accountId}` : userPart;
|
|
391
|
+
}
|
|
334
392
|
/**
|
|
335
393
|
* Generate authorization URL for user to visit
|
|
336
394
|
* Opens browser or redirects user to this URL
|
|
337
395
|
*
|
|
338
396
|
* @param userId - User identifier for multi-user support (optional)
|
|
397
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
339
398
|
*/
|
|
340
|
-
async getAuthorizationUrl(userId) {
|
|
399
|
+
async getAuthorizationUrl(userId, accountId) {
|
|
341
400
|
if (!this.config.authorizationUrl) {
|
|
342
401
|
throw new Error("authorizationUrl is required for authorization_code flow");
|
|
343
402
|
}
|
|
@@ -345,11 +404,11 @@ var init_AuthCodePKCE = __esm({
|
|
|
345
404
|
throw new Error("redirectUri is required for authorization_code flow");
|
|
346
405
|
}
|
|
347
406
|
this.cleanupExpiredPKCE();
|
|
348
|
-
const
|
|
407
|
+
const mapKey = this.getMapKey(userId, accountId);
|
|
349
408
|
const { codeVerifier, codeChallenge } = generatePKCE();
|
|
350
|
-
this.codeVerifiers.set(
|
|
409
|
+
this.codeVerifiers.set(mapKey, { verifier: codeVerifier, timestamp: Date.now() });
|
|
351
410
|
const state = generateState();
|
|
352
|
-
this.states.set(
|
|
411
|
+
this.states.set(mapKey, { state, timestamp: Date.now() });
|
|
353
412
|
const params = new URLSearchParams({
|
|
354
413
|
response_type: "code",
|
|
355
414
|
client_id: this.config.clientId,
|
|
@@ -363,33 +422,48 @@ var init_AuthCodePKCE = __esm({
|
|
|
363
422
|
params.append("code_challenge", codeChallenge);
|
|
364
423
|
params.append("code_challenge_method", "S256");
|
|
365
424
|
}
|
|
366
|
-
|
|
367
|
-
|
|
425
|
+
let stateWithMetadata = state;
|
|
426
|
+
if (userId || accountId) {
|
|
427
|
+
stateWithMetadata = `${state}::${userId || ""}`;
|
|
428
|
+
if (accountId) {
|
|
429
|
+
stateWithMetadata += `::${accountId}`;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
params.set("state", stateWithMetadata);
|
|
368
433
|
return `${this.config.authorizationUrl}?${params.toString()}`;
|
|
369
434
|
}
|
|
370
435
|
/**
|
|
371
436
|
* Exchange authorization code for access token
|
|
372
437
|
*
|
|
373
438
|
* @param code - Authorization code from callback
|
|
374
|
-
* @param state - State parameter from callback (for CSRF verification, may include userId)
|
|
439
|
+
* @param state - State parameter from callback (for CSRF verification, may include userId/accountId)
|
|
375
440
|
* @param userId - User identifier (optional, can be extracted from state)
|
|
441
|
+
* @param accountId - Account alias (optional, can be extracted from state)
|
|
376
442
|
*/
|
|
377
|
-
async exchangeCode(code, state, userId) {
|
|
443
|
+
async exchangeCode(code, state, userId, accountId) {
|
|
378
444
|
let actualState = state;
|
|
379
445
|
let actualUserId = userId;
|
|
446
|
+
let actualAccountId = accountId;
|
|
380
447
|
if (state.includes("::")) {
|
|
381
448
|
const parts = state.split("::");
|
|
382
449
|
actualState = parts[0];
|
|
383
|
-
actualUserId
|
|
450
|
+
if (!actualUserId && parts[1]) {
|
|
451
|
+
actualUserId = parts[1];
|
|
452
|
+
}
|
|
453
|
+
if (!actualAccountId && parts[2]) {
|
|
454
|
+
actualAccountId = parts[2];
|
|
455
|
+
}
|
|
384
456
|
}
|
|
385
|
-
const
|
|
386
|
-
const stateData = this.states.get(
|
|
457
|
+
const mapKey = this.getMapKey(actualUserId, actualAccountId);
|
|
458
|
+
const stateData = this.states.get(mapKey);
|
|
387
459
|
if (!stateData) {
|
|
388
|
-
|
|
460
|
+
const label = actualAccountId ? `user ${actualUserId}, account ${actualAccountId}` : `user ${actualUserId}`;
|
|
461
|
+
throw new Error(`No PKCE state found for ${label}. Authorization flow may have expired (15 min TTL).`);
|
|
389
462
|
}
|
|
390
463
|
const expectedState = stateData.state;
|
|
391
464
|
if (actualState !== expectedState) {
|
|
392
|
-
|
|
465
|
+
const label = actualAccountId ? `user ${actualUserId}, account ${actualAccountId}` : `user ${actualUserId}`;
|
|
466
|
+
throw new Error(`State mismatch for ${label} - possible CSRF attack. Expected: ${expectedState}, Got: ${actualState}`);
|
|
393
467
|
}
|
|
394
468
|
if (!this.config.redirectUri) {
|
|
395
469
|
throw new Error("redirectUri is required");
|
|
@@ -403,7 +477,7 @@ var init_AuthCodePKCE = __esm({
|
|
|
403
477
|
if (this.config.clientSecret) {
|
|
404
478
|
params.append("client_secret", this.config.clientSecret);
|
|
405
479
|
}
|
|
406
|
-
const verifierData = this.codeVerifiers.get(
|
|
480
|
+
const verifierData = this.codeVerifiers.get(mapKey);
|
|
407
481
|
if (this.config.usePKCE !== false && verifierData) {
|
|
408
482
|
params.append("code_verifier", verifierData.verifier);
|
|
409
483
|
}
|
|
@@ -437,39 +511,43 @@ var init_AuthCodePKCE = __esm({
|
|
|
437
511
|
throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${error}`);
|
|
438
512
|
}
|
|
439
513
|
const data = await response.json();
|
|
440
|
-
await this.tokenStore.storeToken(data, actualUserId);
|
|
441
|
-
this.codeVerifiers.delete(
|
|
442
|
-
this.states.delete(
|
|
514
|
+
await this.tokenStore.storeToken(data, actualUserId, actualAccountId);
|
|
515
|
+
this.codeVerifiers.delete(mapKey);
|
|
516
|
+
this.states.delete(mapKey);
|
|
443
517
|
}
|
|
444
518
|
/**
|
|
445
519
|
* Get valid token (auto-refreshes if needed)
|
|
446
520
|
* @param userId - User identifier for multi-user support
|
|
521
|
+
* @param accountId - Account alias for multi-account support
|
|
447
522
|
*/
|
|
448
|
-
async getToken(userId) {
|
|
449
|
-
const
|
|
450
|
-
if (this.refreshLocks.has(
|
|
451
|
-
return this.refreshLocks.get(
|
|
523
|
+
async getToken(userId, accountId) {
|
|
524
|
+
const mapKey = this.getMapKey(userId, accountId);
|
|
525
|
+
if (this.refreshLocks.has(mapKey)) {
|
|
526
|
+
return this.refreshLocks.get(mapKey);
|
|
452
527
|
}
|
|
453
|
-
if (await this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId)) {
|
|
454
|
-
return this.tokenStore.getAccessToken(userId);
|
|
528
|
+
if (await this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId, accountId)) {
|
|
529
|
+
return this.tokenStore.getAccessToken(userId, accountId);
|
|
455
530
|
}
|
|
456
|
-
if (await this.tokenStore.hasRefreshToken(userId)) {
|
|
457
|
-
const refreshPromise = this.refreshToken(userId);
|
|
458
|
-
this.refreshLocks.set(
|
|
531
|
+
if (await this.tokenStore.hasRefreshToken(userId, accountId)) {
|
|
532
|
+
const refreshPromise = this.refreshToken(userId, accountId);
|
|
533
|
+
this.refreshLocks.set(mapKey, refreshPromise);
|
|
459
534
|
try {
|
|
460
535
|
return await refreshPromise;
|
|
461
536
|
} finally {
|
|
462
|
-
this.refreshLocks.delete(
|
|
537
|
+
this.refreshLocks.delete(mapKey);
|
|
463
538
|
}
|
|
464
539
|
}
|
|
465
|
-
|
|
540
|
+
const userLabel = userId ? `user: ${userId}` : "default user";
|
|
541
|
+
const accountLabel = accountId ? `, account: ${accountId}` : "";
|
|
542
|
+
throw new Error(`No valid token available for ${userLabel}${accountLabel}. User needs to authorize (call startAuthFlow).`);
|
|
466
543
|
}
|
|
467
544
|
/**
|
|
468
545
|
* Refresh access token using refresh token
|
|
469
546
|
* @param userId - User identifier for multi-user support
|
|
547
|
+
* @param accountId - Account alias for multi-account support
|
|
470
548
|
*/
|
|
471
|
-
async refreshToken(userId) {
|
|
472
|
-
const refreshToken = await this.tokenStore.getRefreshToken(userId);
|
|
549
|
+
async refreshToken(userId, accountId) {
|
|
550
|
+
const refreshToken = await this.tokenStore.getRefreshToken(userId, accountId);
|
|
473
551
|
const params = new URLSearchParams({
|
|
474
552
|
grant_type: "refresh_token",
|
|
475
553
|
refresh_token: refreshToken,
|
|
@@ -508,28 +586,30 @@ var init_AuthCodePKCE = __esm({
|
|
|
508
586
|
throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${error}`);
|
|
509
587
|
}
|
|
510
588
|
const data = await response.json();
|
|
511
|
-
await this.tokenStore.storeToken(data, userId);
|
|
589
|
+
await this.tokenStore.storeToken(data, userId, accountId);
|
|
512
590
|
return data.access_token;
|
|
513
591
|
}
|
|
514
592
|
/**
|
|
515
593
|
* Check if token is valid
|
|
516
594
|
* @param userId - User identifier for multi-user support
|
|
595
|
+
* @param accountId - Account alias for multi-account support
|
|
517
596
|
*/
|
|
518
|
-
async isTokenValid(userId) {
|
|
519
|
-
return this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId);
|
|
597
|
+
async isTokenValid(userId, accountId) {
|
|
598
|
+
return this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId, accountId);
|
|
520
599
|
}
|
|
521
600
|
/**
|
|
522
601
|
* Revoke token (if supported by provider)
|
|
523
602
|
* @param revocationUrl - Optional revocation endpoint
|
|
524
603
|
* @param userId - User identifier for multi-user support
|
|
604
|
+
* @param accountId - Account alias for multi-account support
|
|
525
605
|
*/
|
|
526
|
-
async revokeToken(revocationUrl, userId) {
|
|
606
|
+
async revokeToken(revocationUrl, userId, accountId) {
|
|
527
607
|
if (!revocationUrl) {
|
|
528
|
-
await this.tokenStore.clear(userId);
|
|
608
|
+
await this.tokenStore.clear(userId, accountId);
|
|
529
609
|
return;
|
|
530
610
|
}
|
|
531
611
|
try {
|
|
532
|
-
const token = await this.tokenStore.getAccessToken(userId);
|
|
612
|
+
const token = await this.tokenStore.getAccessToken(userId, accountId);
|
|
533
613
|
await fetch(revocationUrl, {
|
|
534
614
|
method: "POST",
|
|
535
615
|
headers: {
|
|
@@ -541,9 +621,16 @@ var init_AuthCodePKCE = __esm({
|
|
|
541
621
|
})
|
|
542
622
|
});
|
|
543
623
|
} finally {
|
|
544
|
-
await this.tokenStore.clear(userId);
|
|
624
|
+
await this.tokenStore.clear(userId, accountId);
|
|
545
625
|
}
|
|
546
626
|
}
|
|
627
|
+
/**
|
|
628
|
+
* List account aliases for a user.
|
|
629
|
+
* @param userId - User identifier (optional)
|
|
630
|
+
*/
|
|
631
|
+
async listAccounts(userId) {
|
|
632
|
+
return this.tokenStore.listAccounts(userId);
|
|
633
|
+
}
|
|
547
634
|
/**
|
|
548
635
|
* Clean up expired PKCE data to prevent memory leaks
|
|
549
636
|
* Removes verifiers and states older than PKCE_TTL (15 minutes)
|
|
@@ -575,17 +662,19 @@ var init_ClientCredentials = __esm({
|
|
|
575
662
|
tokenStore;
|
|
576
663
|
/**
|
|
577
664
|
* Get token using client credentials
|
|
665
|
+
* @param userId - User identifier for multi-user support (optional, rarely used for client_credentials)
|
|
666
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
578
667
|
*/
|
|
579
|
-
async getToken() {
|
|
580
|
-
if (await this.tokenStore.isValid(this.config.refreshBeforeExpiry)) {
|
|
581
|
-
return this.tokenStore.getAccessToken();
|
|
668
|
+
async getToken(userId, accountId) {
|
|
669
|
+
if (await this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId, accountId)) {
|
|
670
|
+
return this.tokenStore.getAccessToken(userId, accountId);
|
|
582
671
|
}
|
|
583
|
-
return this.requestToken();
|
|
672
|
+
return this.requestToken(userId, accountId);
|
|
584
673
|
}
|
|
585
674
|
/**
|
|
586
675
|
* Request a new token from the authorization server
|
|
587
676
|
*/
|
|
588
|
-
async requestToken() {
|
|
677
|
+
async requestToken(userId, accountId) {
|
|
589
678
|
const auth2 = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString(
|
|
590
679
|
"base64"
|
|
591
680
|
);
|
|
@@ -608,22 +697,26 @@ var init_ClientCredentials = __esm({
|
|
|
608
697
|
throw new Error(`Token request failed: ${response.status} ${response.statusText} - ${error}`);
|
|
609
698
|
}
|
|
610
699
|
const data = await response.json();
|
|
611
|
-
await this.tokenStore.storeToken(data);
|
|
700
|
+
await this.tokenStore.storeToken(data, userId, accountId);
|
|
612
701
|
return data.access_token;
|
|
613
702
|
}
|
|
614
703
|
/**
|
|
615
704
|
* Refresh token (client credentials don't use refresh tokens)
|
|
616
705
|
* Just requests a new token
|
|
706
|
+
* @param userId - User identifier for multi-user support (optional)
|
|
707
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
617
708
|
*/
|
|
618
|
-
async refreshToken() {
|
|
619
|
-
await this.tokenStore.clear();
|
|
620
|
-
return this.requestToken();
|
|
709
|
+
async refreshToken(userId, accountId) {
|
|
710
|
+
await this.tokenStore.clear(userId, accountId);
|
|
711
|
+
return this.requestToken(userId, accountId);
|
|
621
712
|
}
|
|
622
713
|
/**
|
|
623
714
|
* Check if token is valid
|
|
715
|
+
* @param userId - User identifier for multi-user support (optional)
|
|
716
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
624
717
|
*/
|
|
625
|
-
async isTokenValid() {
|
|
626
|
-
return this.tokenStore.isValid(this.config.refreshBeforeExpiry);
|
|
718
|
+
async isTokenValid(userId, accountId) {
|
|
719
|
+
return this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId, accountId);
|
|
627
720
|
}
|
|
628
721
|
};
|
|
629
722
|
}
|
|
@@ -665,17 +758,19 @@ var init_JWTBearer = __esm({
|
|
|
665
758
|
}
|
|
666
759
|
/**
|
|
667
760
|
* Get token using JWT Bearer assertion
|
|
761
|
+
* @param userId - User identifier for multi-user support (optional)
|
|
762
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
668
763
|
*/
|
|
669
|
-
async getToken() {
|
|
670
|
-
if (await this.tokenStore.isValid(this.config.refreshBeforeExpiry)) {
|
|
671
|
-
return this.tokenStore.getAccessToken();
|
|
764
|
+
async getToken(userId, accountId) {
|
|
765
|
+
if (await this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId, accountId)) {
|
|
766
|
+
return this.tokenStore.getAccessToken(userId, accountId);
|
|
672
767
|
}
|
|
673
|
-
return this.requestToken();
|
|
768
|
+
return this.requestToken(userId, accountId);
|
|
674
769
|
}
|
|
675
770
|
/**
|
|
676
771
|
* Request token using JWT assertion
|
|
677
772
|
*/
|
|
678
|
-
async requestToken() {
|
|
773
|
+
async requestToken(userId, accountId) {
|
|
679
774
|
const assertion = await this.generateJWT();
|
|
680
775
|
const params = new URLSearchParams({
|
|
681
776
|
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
@@ -693,21 +788,25 @@ var init_JWTBearer = __esm({
|
|
|
693
788
|
throw new Error(`JWT Bearer token request failed: ${response.status} ${response.statusText} - ${error}`);
|
|
694
789
|
}
|
|
695
790
|
const data = await response.json();
|
|
696
|
-
await this.tokenStore.storeToken(data);
|
|
791
|
+
await this.tokenStore.storeToken(data, userId, accountId);
|
|
697
792
|
return data.access_token;
|
|
698
793
|
}
|
|
699
794
|
/**
|
|
700
795
|
* Refresh token (generate new JWT and request new token)
|
|
796
|
+
* @param userId - User identifier for multi-user support (optional)
|
|
797
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
701
798
|
*/
|
|
702
|
-
async refreshToken() {
|
|
703
|
-
await this.tokenStore.clear();
|
|
704
|
-
return this.requestToken();
|
|
799
|
+
async refreshToken(userId, accountId) {
|
|
800
|
+
await this.tokenStore.clear(userId, accountId);
|
|
801
|
+
return this.requestToken(userId, accountId);
|
|
705
802
|
}
|
|
706
803
|
/**
|
|
707
804
|
* Check if token is valid
|
|
805
|
+
* @param userId - User identifier for multi-user support (optional)
|
|
806
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
708
807
|
*/
|
|
709
|
-
async isTokenValid() {
|
|
710
|
-
return this.tokenStore.isValid(this.config.refreshBeforeExpiry);
|
|
808
|
+
async isTokenValid(userId, accountId) {
|
|
809
|
+
return this.tokenStore.isValid(this.config.refreshBeforeExpiry, userId, accountId);
|
|
711
810
|
}
|
|
712
811
|
};
|
|
713
812
|
}
|
|
@@ -787,25 +886,28 @@ var init_OAuthManager = __esm({
|
|
|
787
886
|
* Automatically refreshes if expired
|
|
788
887
|
*
|
|
789
888
|
* @param userId - User identifier for multi-user support (optional)
|
|
889
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
790
890
|
*/
|
|
791
|
-
async getToken(userId) {
|
|
792
|
-
return this.flow.getToken(userId);
|
|
891
|
+
async getToken(userId, accountId) {
|
|
892
|
+
return this.flow.getToken(userId, accountId);
|
|
793
893
|
}
|
|
794
894
|
/**
|
|
795
895
|
* Force refresh the token
|
|
796
896
|
*
|
|
797
897
|
* @param userId - User identifier for multi-user support (optional)
|
|
898
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
798
899
|
*/
|
|
799
|
-
async refreshToken(userId) {
|
|
800
|
-
return this.flow.refreshToken(userId);
|
|
900
|
+
async refreshToken(userId, accountId) {
|
|
901
|
+
return this.flow.refreshToken(userId, accountId);
|
|
801
902
|
}
|
|
802
903
|
/**
|
|
803
904
|
* Check if current token is valid
|
|
804
905
|
*
|
|
805
906
|
* @param userId - User identifier for multi-user support (optional)
|
|
907
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
806
908
|
*/
|
|
807
|
-
async isTokenValid(userId) {
|
|
808
|
-
return this.flow.isTokenValid(userId);
|
|
909
|
+
async isTokenValid(userId, accountId) {
|
|
910
|
+
return this.flow.isTokenValid(userId, accountId);
|
|
809
911
|
}
|
|
810
912
|
// ==================== Authorization Code Flow Methods ====================
|
|
811
913
|
/**
|
|
@@ -813,13 +915,14 @@ var init_OAuthManager = __esm({
|
|
|
813
915
|
* Returns URL for user to visit
|
|
814
916
|
*
|
|
815
917
|
* @param userId - User identifier for multi-user support (optional)
|
|
918
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
816
919
|
* @returns Authorization URL for the user to visit
|
|
817
920
|
*/
|
|
818
|
-
async startAuthFlow(userId) {
|
|
921
|
+
async startAuthFlow(userId, accountId) {
|
|
819
922
|
if (!(this.flow instanceof AuthCodePKCEFlow)) {
|
|
820
923
|
throw new Error("startAuthFlow() is only available for authorization_code flow");
|
|
821
924
|
}
|
|
822
|
-
return this.flow.getAuthorizationUrl(userId);
|
|
925
|
+
return this.flow.getAuthorizationUrl(userId, accountId);
|
|
823
926
|
}
|
|
824
927
|
/**
|
|
825
928
|
* Handle OAuth callback (Authorization Code only)
|
|
@@ -827,8 +930,9 @@ var init_OAuthManager = __esm({
|
|
|
827
930
|
*
|
|
828
931
|
* @param callbackUrl - Full callback URL with code and state parameters
|
|
829
932
|
* @param userId - Optional user identifier (can be extracted from state if embedded)
|
|
933
|
+
* @param accountId - Optional account alias (can be extracted from state if embedded)
|
|
830
934
|
*/
|
|
831
|
-
async handleCallback(callbackUrl, userId) {
|
|
935
|
+
async handleCallback(callbackUrl, userId, accountId) {
|
|
832
936
|
if (!(this.flow instanceof AuthCodePKCEFlow)) {
|
|
833
937
|
throw new Error("handleCallback() is only available for authorization_code flow");
|
|
834
938
|
}
|
|
@@ -841,21 +945,34 @@ var init_OAuthManager = __esm({
|
|
|
841
945
|
if (!state) {
|
|
842
946
|
throw new Error("Missing state parameter in callback URL");
|
|
843
947
|
}
|
|
844
|
-
await this.flow.exchangeCode(code, state, userId);
|
|
948
|
+
await this.flow.exchangeCode(code, state, userId, accountId);
|
|
845
949
|
}
|
|
846
950
|
/**
|
|
847
951
|
* Revoke token (if supported by provider)
|
|
848
952
|
*
|
|
849
953
|
* @param revocationUrl - Optional revocation endpoint URL
|
|
850
954
|
* @param userId - User identifier for multi-user support (optional)
|
|
955
|
+
* @param accountId - Account alias for multi-account support (optional)
|
|
851
956
|
*/
|
|
852
|
-
async revokeToken(revocationUrl, userId) {
|
|
957
|
+
async revokeToken(revocationUrl, userId, accountId) {
|
|
853
958
|
if (this.flow instanceof AuthCodePKCEFlow) {
|
|
854
|
-
await this.flow.revokeToken(revocationUrl, userId);
|
|
959
|
+
await this.flow.revokeToken(revocationUrl, userId, accountId);
|
|
855
960
|
} else {
|
|
856
961
|
throw new Error("Token revocation not implemented for this flow");
|
|
857
962
|
}
|
|
858
963
|
}
|
|
964
|
+
/**
|
|
965
|
+
* List account aliases for a user (Authorization Code only)
|
|
966
|
+
*
|
|
967
|
+
* @param userId - User identifier (optional)
|
|
968
|
+
* @returns Array of account aliases (e.g., ['work', 'personal'])
|
|
969
|
+
*/
|
|
970
|
+
async listAccounts(userId) {
|
|
971
|
+
if (this.flow instanceof AuthCodePKCEFlow) {
|
|
972
|
+
return this.flow.listAccounts(userId);
|
|
973
|
+
}
|
|
974
|
+
return [];
|
|
975
|
+
}
|
|
859
976
|
// ==================== Validation ====================
|
|
860
977
|
validateConfig(config) {
|
|
861
978
|
if (!config.flow) {
|
|
@@ -2061,46 +2178,59 @@ var init_Connector = __esm({
|
|
|
2061
2178
|
/**
|
|
2062
2179
|
* Get the current access token (for OAuth, JWT, or API key)
|
|
2063
2180
|
* Handles automatic refresh if needed
|
|
2181
|
+
*
|
|
2182
|
+
* @param userId - Optional user identifier for multi-user support
|
|
2183
|
+
* @param accountId - Optional account alias for multi-account support (e.g., 'work', 'personal')
|
|
2064
2184
|
*/
|
|
2065
|
-
async getToken(userId) {
|
|
2185
|
+
async getToken(userId, accountId) {
|
|
2066
2186
|
if (this.config.auth.type === "api_key") {
|
|
2067
2187
|
return this.config.auth.apiKey;
|
|
2068
2188
|
}
|
|
2069
2189
|
if (!this.oauthManager) {
|
|
2070
2190
|
throw new Error(`OAuth manager not initialized for connector '${this.name}'`);
|
|
2071
2191
|
}
|
|
2072
|
-
return this.oauthManager.getToken(userId);
|
|
2192
|
+
return this.oauthManager.getToken(userId, accountId);
|
|
2073
2193
|
}
|
|
2074
2194
|
/**
|
|
2075
2195
|
* Start OAuth authorization flow
|
|
2076
2196
|
* Returns the URL to redirect the user to
|
|
2197
|
+
*
|
|
2198
|
+
* @param userId - Optional user identifier for multi-user support
|
|
2199
|
+
* @param accountId - Optional account alias for multi-account support (e.g., 'work', 'personal')
|
|
2077
2200
|
*/
|
|
2078
|
-
async startAuth(userId) {
|
|
2201
|
+
async startAuth(userId, accountId) {
|
|
2079
2202
|
if (!this.oauthManager) {
|
|
2080
2203
|
throw new Error(`Connector '${this.name}' is not an OAuth connector`);
|
|
2081
2204
|
}
|
|
2082
|
-
return this.oauthManager.startAuthFlow(userId);
|
|
2205
|
+
return this.oauthManager.startAuthFlow(userId, accountId);
|
|
2083
2206
|
}
|
|
2084
2207
|
/**
|
|
2085
2208
|
* Handle OAuth callback
|
|
2086
2209
|
* Call this after user is redirected back from OAuth provider
|
|
2210
|
+
*
|
|
2211
|
+
* @param callbackUrl - Full callback URL with code and state parameters
|
|
2212
|
+
* @param userId - Optional user identifier (can be extracted from state if embedded)
|
|
2213
|
+
* @param accountId - Optional account alias (can be extracted from state if embedded)
|
|
2087
2214
|
*/
|
|
2088
|
-
async handleCallback(callbackUrl, userId) {
|
|
2215
|
+
async handleCallback(callbackUrl, userId, accountId) {
|
|
2089
2216
|
if (!this.oauthManager) {
|
|
2090
2217
|
throw new Error(`Connector '${this.name}' is not an OAuth connector`);
|
|
2091
2218
|
}
|
|
2092
|
-
await this.oauthManager.handleCallback(callbackUrl, userId);
|
|
2219
|
+
await this.oauthManager.handleCallback(callbackUrl, userId, accountId);
|
|
2093
2220
|
}
|
|
2094
2221
|
/**
|
|
2095
2222
|
* Check if the connector has a valid token
|
|
2223
|
+
*
|
|
2224
|
+
* @param userId - Optional user identifier for multi-user support
|
|
2225
|
+
* @param accountId - Optional account alias for multi-account support
|
|
2096
2226
|
*/
|
|
2097
|
-
async hasValidToken(userId) {
|
|
2227
|
+
async hasValidToken(userId, accountId) {
|
|
2098
2228
|
try {
|
|
2099
2229
|
if (this.config.auth.type === "api_key") {
|
|
2100
2230
|
return true;
|
|
2101
2231
|
}
|
|
2102
2232
|
if (this.oauthManager) {
|
|
2103
|
-
const token = await this.oauthManager.getToken(userId);
|
|
2233
|
+
const token = await this.oauthManager.getToken(userId, accountId);
|
|
2104
2234
|
return !!token;
|
|
2105
2235
|
}
|
|
2106
2236
|
return false;
|
|
@@ -2108,6 +2238,19 @@ var init_Connector = __esm({
|
|
|
2108
2238
|
return false;
|
|
2109
2239
|
}
|
|
2110
2240
|
}
|
|
2241
|
+
/**
|
|
2242
|
+
* List account aliases for a user on this connector.
|
|
2243
|
+
* Only applicable for OAuth connectors with multi-account support.
|
|
2244
|
+
*
|
|
2245
|
+
* @param userId - Optional user identifier
|
|
2246
|
+
* @returns Array of account aliases (e.g., ['work', 'personal'])
|
|
2247
|
+
*/
|
|
2248
|
+
async listAccounts(userId) {
|
|
2249
|
+
if (!this.oauthManager) {
|
|
2250
|
+
return [];
|
|
2251
|
+
}
|
|
2252
|
+
return this.oauthManager.listAccounts(userId);
|
|
2253
|
+
}
|
|
2111
2254
|
/**
|
|
2112
2255
|
* Get vendor-specific options from config
|
|
2113
2256
|
*/
|
|
@@ -2151,9 +2294,10 @@ var init_Connector = __esm({
|
|
|
2151
2294
|
* @param endpoint - API endpoint (relative to baseURL) or full URL
|
|
2152
2295
|
* @param options - Fetch options with connector-specific settings
|
|
2153
2296
|
* @param userId - Optional user ID for multi-user OAuth
|
|
2297
|
+
* @param accountId - Optional account alias for multi-account OAuth
|
|
2154
2298
|
* @returns Fetch Response
|
|
2155
2299
|
*/
|
|
2156
|
-
async fetch(endpoint, options, userId) {
|
|
2300
|
+
async fetch(endpoint, options, userId, accountId) {
|
|
2157
2301
|
if (this.disposed) {
|
|
2158
2302
|
throw new Error(`Connector '${this.name}' has been disposed`);
|
|
2159
2303
|
}
|
|
@@ -2172,7 +2316,7 @@ var init_Connector = __esm({
|
|
|
2172
2316
|
this.logRequest(url2, options);
|
|
2173
2317
|
}
|
|
2174
2318
|
const doFetch = async () => {
|
|
2175
|
-
const token = await this.getToken(userId);
|
|
2319
|
+
const token = await this.getToken(userId, accountId);
|
|
2176
2320
|
const auth2 = this.config.auth;
|
|
2177
2321
|
let headerName = "Authorization";
|
|
2178
2322
|
let headerValue = `Bearer ${token}`;
|
|
@@ -2284,10 +2428,11 @@ var init_Connector = __esm({
|
|
|
2284
2428
|
* @param endpoint - API endpoint (relative to baseURL) or full URL
|
|
2285
2429
|
* @param options - Fetch options with connector-specific settings
|
|
2286
2430
|
* @param userId - Optional user ID for multi-user OAuth
|
|
2431
|
+
* @param accountId - Optional account alias for multi-account OAuth
|
|
2287
2432
|
* @returns Parsed JSON response
|
|
2288
2433
|
*/
|
|
2289
|
-
async fetchJSON(endpoint, options, userId) {
|
|
2290
|
-
const response = await this.fetch(endpoint, options, userId);
|
|
2434
|
+
async fetchJSON(endpoint, options, userId, accountId) {
|
|
2435
|
+
const response = await this.fetch(endpoint, options, userId, accountId);
|
|
2291
2436
|
const text = await response.text();
|
|
2292
2437
|
let data;
|
|
2293
2438
|
try {
|
|
@@ -11236,6 +11381,18 @@ var ToolManager = class extends EventEmitter {
|
|
|
11236
11381
|
this.register(tool, options);
|
|
11237
11382
|
}
|
|
11238
11383
|
}
|
|
11384
|
+
/**
|
|
11385
|
+
* Register tools produced by a specific connector.
|
|
11386
|
+
* Sets `source: 'connector:<connectorName>'` (or `'connector:<name>:<accountId>'` for identity-bound tools)
|
|
11387
|
+
* so agent-level filtering can restrict which connector tools are visible to a given agent.
|
|
11388
|
+
*/
|
|
11389
|
+
registerConnectorTools(connectorName, tools, options = {}) {
|
|
11390
|
+
const { accountId, ...toolOptions } = options;
|
|
11391
|
+
const source = accountId ? `connector:${connectorName}:${accountId}` : `connector:${connectorName}`;
|
|
11392
|
+
for (const tool of tools) {
|
|
11393
|
+
this.register(tool, { ...toolOptions, source });
|
|
11394
|
+
}
|
|
11395
|
+
}
|
|
11239
11396
|
/**
|
|
11240
11397
|
* Unregister a tool by name
|
|
11241
11398
|
*/
|
|
@@ -11426,6 +11583,14 @@ var ToolManager = class extends EventEmitter {
|
|
|
11426
11583
|
getEnabled() {
|
|
11427
11584
|
return this.getSortedByPriority().filter((reg) => reg.enabled).map((reg) => reg.tool);
|
|
11428
11585
|
}
|
|
11586
|
+
/**
|
|
11587
|
+
* Get all enabled registrations (sorted by priority).
|
|
11588
|
+
* Includes full registration metadata (source, namespace, etc.)
|
|
11589
|
+
* for use in connector-aware filtering.
|
|
11590
|
+
*/
|
|
11591
|
+
getEnabledRegistrations() {
|
|
11592
|
+
return this.getSortedByPriority().filter((reg) => reg.enabled);
|
|
11593
|
+
}
|
|
11429
11594
|
/**
|
|
11430
11595
|
* Get all tools (enabled and disabled)
|
|
11431
11596
|
*/
|
|
@@ -11618,6 +11783,13 @@ var ToolManager = class extends EventEmitter {
|
|
|
11618
11783
|
if (!registration.enabled) {
|
|
11619
11784
|
throw new ToolExecutionError(toolName, "Tool is disabled");
|
|
11620
11785
|
}
|
|
11786
|
+
if (registration.source?.startsWith("connector:")) {
|
|
11787
|
+
const connName = registration.source.slice("connector:".length);
|
|
11788
|
+
const registry = this._toolContext?.connectorRegistry;
|
|
11789
|
+
if (registry && !registry.has(connName)) {
|
|
11790
|
+
throw new ToolExecutionError(toolName, `Connector '${connName}' is not available to this agent`);
|
|
11791
|
+
}
|
|
11792
|
+
}
|
|
11621
11793
|
const breaker = this.getOrCreateCircuitBreaker(toolName, registration);
|
|
11622
11794
|
this.toolLogger.debug({ toolName, args }, "Tool execution started");
|
|
11623
11795
|
const startTime = Date.now();
|
|
@@ -16710,8 +16882,8 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16710
16882
|
_agentId;
|
|
16711
16883
|
/** User ID for multi-user scenarios */
|
|
16712
16884
|
_userId;
|
|
16713
|
-
/**
|
|
16714
|
-
|
|
16885
|
+
/** Auth identities this agent is scoped to (connector + optional accountId) */
|
|
16886
|
+
_identities;
|
|
16715
16887
|
/** Storage backend */
|
|
16716
16888
|
_storage;
|
|
16717
16889
|
/** Destroyed flag */
|
|
@@ -16751,7 +16923,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16751
16923
|
this._systemPrompt = config.systemPrompt;
|
|
16752
16924
|
this._agentId = this._config.agentId;
|
|
16753
16925
|
this._userId = config.userId;
|
|
16754
|
-
this.
|
|
16926
|
+
this._identities = config.identities;
|
|
16755
16927
|
const sessionFactory = StorageRegistry.get("sessions");
|
|
16756
16928
|
const storageCtx = StorageRegistry.getContext() ?? (config.userId ? { userId: config.userId } : void 0);
|
|
16757
16929
|
this._storage = config.storage ?? (sessionFactory ? sessionFactory(this._agentId, storageCtx) : void 0);
|
|
@@ -16823,7 +16995,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16823
16995
|
* Merges with existing ToolContext to preserve other fields (memory, signal, taskId).
|
|
16824
16996
|
*
|
|
16825
16997
|
* Connector registry resolution order:
|
|
16826
|
-
* 1. If `
|
|
16998
|
+
* 1. If `identities` is set → filtered view showing only identity connectors
|
|
16827
16999
|
* 2. If access policy + userId → scoped view via Connector.scoped()
|
|
16828
17000
|
* 3. Otherwise → full global registry
|
|
16829
17001
|
*/
|
|
@@ -16833,6 +17005,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16833
17005
|
...existing,
|
|
16834
17006
|
agentId: this._agentId,
|
|
16835
17007
|
userId: this._userId,
|
|
17008
|
+
identities: this._identities,
|
|
16836
17009
|
connectorRegistry: this.buildConnectorRegistry()
|
|
16837
17010
|
});
|
|
16838
17011
|
}
|
|
@@ -16840,13 +17013,13 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16840
17013
|
* Build the connector registry appropriate for this agent's config.
|
|
16841
17014
|
*/
|
|
16842
17015
|
buildConnectorRegistry() {
|
|
16843
|
-
if (this.
|
|
16844
|
-
const allowedSet = new Set(this.
|
|
17016
|
+
if (this._identities?.length) {
|
|
17017
|
+
const allowedSet = new Set(this._identities.map((id) => id.connector));
|
|
16845
17018
|
const base = this._userId && Connector.getAccessPolicy() ? Connector.scoped({ userId: this._userId }) : Connector.asRegistry();
|
|
16846
17019
|
return {
|
|
16847
17020
|
get: (name) => {
|
|
16848
17021
|
if (!allowedSet.has(name)) {
|
|
16849
|
-
const available =
|
|
17022
|
+
const available = [...allowedSet].filter((n) => base.has(n)).join(", ") || "none";
|
|
16850
17023
|
throw new Error(`Connector '${name}' not found. Available: ${available}`);
|
|
16851
17024
|
}
|
|
16852
17025
|
return base.get(name);
|
|
@@ -16898,13 +17071,13 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16898
17071
|
this._userId = value;
|
|
16899
17072
|
this.syncToolContext();
|
|
16900
17073
|
}
|
|
16901
|
-
/** Get the
|
|
16902
|
-
get
|
|
16903
|
-
return this.
|
|
17074
|
+
/** Get the auth identities this agent is scoped to (undefined = all visible connectors) */
|
|
17075
|
+
get identities() {
|
|
17076
|
+
return this._identities;
|
|
16904
17077
|
}
|
|
16905
|
-
/** Set
|
|
16906
|
-
set
|
|
16907
|
-
this.
|
|
17078
|
+
/** Set auth identities. Updates ToolContext.connectorRegistry and identity-aware descriptions. */
|
|
17079
|
+
set identities(value) {
|
|
17080
|
+
this._identities = value;
|
|
16908
17081
|
this.syncToolContext();
|
|
16909
17082
|
}
|
|
16910
17083
|
/** Get/set system prompt */
|
|
@@ -21383,7 +21556,7 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21383
21556
|
model: config.model,
|
|
21384
21557
|
agentId: config.name,
|
|
21385
21558
|
userId: config.userId,
|
|
21386
|
-
|
|
21559
|
+
identities: config.identities,
|
|
21387
21560
|
// Include storage and sessionId if session config is provided
|
|
21388
21561
|
storage: config.session?.storage,
|
|
21389
21562
|
// Thread tool execution timeout to ToolManager
|
|
@@ -21553,16 +21726,16 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21553
21726
|
this._agentContext.userId = value;
|
|
21554
21727
|
}
|
|
21555
21728
|
/**
|
|
21556
|
-
* Get the
|
|
21729
|
+
* Get the auth identities this agent is scoped to (undefined = all visible connectors).
|
|
21557
21730
|
*/
|
|
21558
|
-
get
|
|
21559
|
-
return this._agentContext.
|
|
21731
|
+
get identities() {
|
|
21732
|
+
return this._agentContext.identities;
|
|
21560
21733
|
}
|
|
21561
21734
|
/**
|
|
21562
|
-
*
|
|
21735
|
+
* Set auth identities at runtime. Updates ToolContext.connectorRegistry and tool descriptions.
|
|
21563
21736
|
*/
|
|
21564
|
-
set
|
|
21565
|
-
this._agentContext.
|
|
21737
|
+
set identities(value) {
|
|
21738
|
+
this._agentContext.identities = value;
|
|
21566
21739
|
}
|
|
21567
21740
|
/**
|
|
21568
21741
|
* Permission management. Returns ToolPermissionManager for approval control.
|
|
@@ -21574,9 +21747,12 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21574
21747
|
/**
|
|
21575
21748
|
* Add a tool to the agent.
|
|
21576
21749
|
* Tools are registered with AgentContext (single source of truth).
|
|
21750
|
+
*
|
|
21751
|
+
* @param tool - The tool function to register
|
|
21752
|
+
* @param options - Optional registration options (namespace, source, priority, etc.)
|
|
21577
21753
|
*/
|
|
21578
|
-
addTool(tool) {
|
|
21579
|
-
this._agentContext.tools.register(tool);
|
|
21754
|
+
addTool(tool, options) {
|
|
21755
|
+
this._agentContext.tools.register(tool, options);
|
|
21580
21756
|
if (tool.permission) {
|
|
21581
21757
|
this._permissionManager.setToolConfig(tool.definition.function.name, tool.permission);
|
|
21582
21758
|
}
|
|
@@ -21616,7 +21792,34 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21616
21792
|
*/
|
|
21617
21793
|
getEnabledToolDefinitions() {
|
|
21618
21794
|
const toolContext = this._agentContext.tools.getToolContext();
|
|
21619
|
-
|
|
21795
|
+
const identities = this._agentContext.identities;
|
|
21796
|
+
let allowedSources;
|
|
21797
|
+
let allowedConnectorNames;
|
|
21798
|
+
if (identities) {
|
|
21799
|
+
allowedSources = /* @__PURE__ */ new Set();
|
|
21800
|
+
allowedConnectorNames = /* @__PURE__ */ new Set();
|
|
21801
|
+
for (const id of identities) {
|
|
21802
|
+
allowedConnectorNames.add(id.connector);
|
|
21803
|
+
if (id.accountId) {
|
|
21804
|
+
allowedSources.add(`connector:${id.connector}:${id.accountId}`);
|
|
21805
|
+
} else {
|
|
21806
|
+
allowedSources.add(`connector:${id.connector}`);
|
|
21807
|
+
allowedConnectorNames.add(id.connector);
|
|
21808
|
+
}
|
|
21809
|
+
}
|
|
21810
|
+
}
|
|
21811
|
+
return this._agentContext.tools.getEnabledRegistrations().filter((reg) => {
|
|
21812
|
+
if (!allowedSources) return true;
|
|
21813
|
+
if (!reg.source?.startsWith("connector:")) return true;
|
|
21814
|
+
if (allowedSources.has(reg.source)) return true;
|
|
21815
|
+
const sourceParts = reg.source.slice("connector:".length).split(":");
|
|
21816
|
+
const connectorName = sourceParts[0];
|
|
21817
|
+
if (allowedConnectorNames.has(connectorName) && allowedSources.has(`connector:${connectorName}`)) {
|
|
21818
|
+
return true;
|
|
21819
|
+
}
|
|
21820
|
+
return false;
|
|
21821
|
+
}).map((reg) => {
|
|
21822
|
+
const tool = reg.tool;
|
|
21620
21823
|
if (tool.descriptionFactory) {
|
|
21621
21824
|
const dynamicDescription = tool.descriptionFactory(toolContext);
|
|
21622
21825
|
return {
|
|
@@ -24001,6 +24204,7 @@ function createTask(input) {
|
|
|
24001
24204
|
suggestedTools: input.suggestedTools,
|
|
24002
24205
|
validation: input.validation,
|
|
24003
24206
|
expectedOutput: input.expectedOutput,
|
|
24207
|
+
controlFlow: input.controlFlow,
|
|
24004
24208
|
attempts: 0,
|
|
24005
24209
|
maxAttempts: input.maxAttempts ?? 3,
|
|
24006
24210
|
createdAt: now,
|
|
@@ -24253,6 +24457,7 @@ function createRoutineDefinition(input) {
|
|
|
24253
24457
|
instructions: input.instructions,
|
|
24254
24458
|
concurrency: input.concurrency,
|
|
24255
24459
|
allowDynamicTasks: input.allowDynamicTasks ?? false,
|
|
24460
|
+
parameters: input.parameters,
|
|
24256
24461
|
tags: input.tags,
|
|
24257
24462
|
author: input.author,
|
|
24258
24463
|
createdAt: now,
|
|
@@ -24468,6 +24673,321 @@ function extractNumber(text, patterns = [
|
|
|
24468
24673
|
|
|
24469
24674
|
// src/core/routineRunner.ts
|
|
24470
24675
|
init_Logger();
|
|
24676
|
+
|
|
24677
|
+
// src/core/routineControlFlow.ts
|
|
24678
|
+
init_Logger();
|
|
24679
|
+
var HARD_MAX_ITERATIONS = 1e3;
|
|
24680
|
+
var ICM_LARGE_THRESHOLD = 5e3;
|
|
24681
|
+
var ROUTINE_KEYS = {
|
|
24682
|
+
/** Plan overview with task statuses (ICM) */
|
|
24683
|
+
PLAN: "__routine_plan",
|
|
24684
|
+
/** Dependency results location guide (ICM) */
|
|
24685
|
+
DEPS: "__routine_deps",
|
|
24686
|
+
/** Prefix for per-dependency result keys (ICM/WM) */
|
|
24687
|
+
DEP_RESULT_PREFIX: "__dep_result_",
|
|
24688
|
+
/** Current map/fold item (ICM) */
|
|
24689
|
+
MAP_ITEM: "__map_item",
|
|
24690
|
+
/** Current map/fold index, 0-based (ICM) */
|
|
24691
|
+
MAP_INDEX: "__map_index",
|
|
24692
|
+
/** Total items in map/fold (ICM) */
|
|
24693
|
+
MAP_TOTAL: "__map_total",
|
|
24694
|
+
/** Running fold accumulator (ICM) */
|
|
24695
|
+
FOLD_ACCUMULATOR: "__fold_accumulator",
|
|
24696
|
+
/** Prefix for large dep results stored in WM findings tier */
|
|
24697
|
+
WM_DEP_FINDINGS_PREFIX: "findings/__dep_result_"
|
|
24698
|
+
};
|
|
24699
|
+
function resolveTemplates(text, inputs, icmPlugin) {
|
|
24700
|
+
return text.replace(/\{\{(\w+)\.(\w+)\}\}/g, (_match, namespace, key) => {
|
|
24701
|
+
let value;
|
|
24702
|
+
if (namespace === "param") {
|
|
24703
|
+
value = inputs[key];
|
|
24704
|
+
} else if (namespace === "map") {
|
|
24705
|
+
const icmKey = `__map_${key}`;
|
|
24706
|
+
value = icmPlugin?.get(icmKey);
|
|
24707
|
+
} else if (namespace === "fold") {
|
|
24708
|
+
const icmKey = `__fold_${key}`;
|
|
24709
|
+
value = icmPlugin?.get(icmKey);
|
|
24710
|
+
} else {
|
|
24711
|
+
return _match;
|
|
24712
|
+
}
|
|
24713
|
+
if (value === void 0) {
|
|
24714
|
+
return _match;
|
|
24715
|
+
}
|
|
24716
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
24717
|
+
});
|
|
24718
|
+
}
|
|
24719
|
+
function resolveTaskTemplates(task, inputs, icmPlugin) {
|
|
24720
|
+
const resolvedDescription = resolveTemplates(task.description, inputs, icmPlugin);
|
|
24721
|
+
const resolvedExpectedOutput = task.expectedOutput ? resolveTemplates(task.expectedOutput, inputs, icmPlugin) : task.expectedOutput;
|
|
24722
|
+
if (resolvedDescription === task.description && resolvedExpectedOutput === task.expectedOutput) {
|
|
24723
|
+
return task;
|
|
24724
|
+
}
|
|
24725
|
+
return {
|
|
24726
|
+
...task,
|
|
24727
|
+
description: resolvedDescription,
|
|
24728
|
+
expectedOutput: resolvedExpectedOutput
|
|
24729
|
+
};
|
|
24730
|
+
}
|
|
24731
|
+
function validateAndResolveInputs(parameters, inputs) {
|
|
24732
|
+
const resolved = { ...inputs ?? {} };
|
|
24733
|
+
if (!parameters || parameters.length === 0) {
|
|
24734
|
+
return resolved;
|
|
24735
|
+
}
|
|
24736
|
+
for (const param of parameters) {
|
|
24737
|
+
if (resolved[param.name] === void 0) {
|
|
24738
|
+
if (param.required) {
|
|
24739
|
+
throw new Error(`Missing required parameter: "${param.name}"`);
|
|
24740
|
+
}
|
|
24741
|
+
if (param.default !== void 0) {
|
|
24742
|
+
resolved[param.name] = param.default;
|
|
24743
|
+
}
|
|
24744
|
+
}
|
|
24745
|
+
}
|
|
24746
|
+
return resolved;
|
|
24747
|
+
}
|
|
24748
|
+
async function readMemoryValue(key, icmPlugin, wmPlugin) {
|
|
24749
|
+
if (icmPlugin) {
|
|
24750
|
+
const icmValue = icmPlugin.get(key);
|
|
24751
|
+
if (icmValue !== void 0) return icmValue;
|
|
24752
|
+
}
|
|
24753
|
+
if (wmPlugin) {
|
|
24754
|
+
const wmValue = await wmPlugin.retrieve(key);
|
|
24755
|
+
if (wmValue !== void 0) return wmValue;
|
|
24756
|
+
}
|
|
24757
|
+
return void 0;
|
|
24758
|
+
}
|
|
24759
|
+
async function storeResult(key, description, value, icmPlugin, wmPlugin) {
|
|
24760
|
+
const serialized = typeof value === "string" ? value : JSON.stringify(value);
|
|
24761
|
+
const estimatedTokens = Math.ceil(serialized.length / 4);
|
|
24762
|
+
if (estimatedTokens < ICM_LARGE_THRESHOLD && icmPlugin) {
|
|
24763
|
+
icmPlugin.set(key, description, value, "high");
|
|
24764
|
+
} else if (wmPlugin) {
|
|
24765
|
+
await wmPlugin.store(key, description, serialized, { tier: "findings" });
|
|
24766
|
+
} else if (icmPlugin) {
|
|
24767
|
+
icmPlugin.set(key, description, value, "high");
|
|
24768
|
+
}
|
|
24769
|
+
}
|
|
24770
|
+
function resolveSubRoutine(spec, parentTaskName) {
|
|
24771
|
+
if (!Array.isArray(spec)) {
|
|
24772
|
+
return spec;
|
|
24773
|
+
}
|
|
24774
|
+
return createRoutineDefinition({
|
|
24775
|
+
name: `${parentTaskName} (sub-routine)`,
|
|
24776
|
+
description: `Sub-routine of ${parentTaskName}`,
|
|
24777
|
+
tasks: spec
|
|
24778
|
+
});
|
|
24779
|
+
}
|
|
24780
|
+
function getPlugins(agent) {
|
|
24781
|
+
const icmPlugin = agent.context.getPlugin("in_context_memory");
|
|
24782
|
+
const wmPlugin = agent.context.memory;
|
|
24783
|
+
return { icmPlugin, wmPlugin };
|
|
24784
|
+
}
|
|
24785
|
+
function cleanMapKeys(icmPlugin) {
|
|
24786
|
+
if (!icmPlugin) return;
|
|
24787
|
+
icmPlugin.delete(ROUTINE_KEYS.MAP_ITEM);
|
|
24788
|
+
icmPlugin.delete(ROUTINE_KEYS.MAP_INDEX);
|
|
24789
|
+
icmPlugin.delete(ROUTINE_KEYS.MAP_TOTAL);
|
|
24790
|
+
}
|
|
24791
|
+
function cleanFoldKeys(icmPlugin) {
|
|
24792
|
+
if (!icmPlugin) return;
|
|
24793
|
+
cleanMapKeys(icmPlugin);
|
|
24794
|
+
icmPlugin.delete(ROUTINE_KEYS.FOLD_ACCUMULATOR);
|
|
24795
|
+
}
|
|
24796
|
+
async function readSourceArray(flow, flowType, icmPlugin, wmPlugin) {
|
|
24797
|
+
const sourceValue = await readMemoryValue(flow.sourceKey, icmPlugin, wmPlugin);
|
|
24798
|
+
if (!Array.isArray(sourceValue)) {
|
|
24799
|
+
return {
|
|
24800
|
+
completed: false,
|
|
24801
|
+
error: `${flowType} sourceKey "${flow.sourceKey}" is not an array (got ${typeof sourceValue})`
|
|
24802
|
+
};
|
|
24803
|
+
}
|
|
24804
|
+
const maxIter = Math.min(sourceValue.length, flow.maxIterations ?? sourceValue.length, HARD_MAX_ITERATIONS);
|
|
24805
|
+
return { array: sourceValue, maxIter };
|
|
24806
|
+
}
|
|
24807
|
+
function prepareSubRoutine(tasks, parentTaskName) {
|
|
24808
|
+
const subRoutine = resolveSubRoutine(tasks, parentTaskName);
|
|
24809
|
+
return {
|
|
24810
|
+
augmented: { ...subRoutine },
|
|
24811
|
+
baseInstructions: subRoutine.instructions ?? ""
|
|
24812
|
+
};
|
|
24813
|
+
}
|
|
24814
|
+
function getSubRoutineOutput(execution) {
|
|
24815
|
+
const tasks = execution.plan.tasks;
|
|
24816
|
+
for (let i = tasks.length - 1; i >= 0; i--) {
|
|
24817
|
+
if (tasks[i].status === "completed") {
|
|
24818
|
+
return tasks[i].result?.output ?? null;
|
|
24819
|
+
}
|
|
24820
|
+
}
|
|
24821
|
+
return null;
|
|
24822
|
+
}
|
|
24823
|
+
function setIterationKeys(icmPlugin, item, index, total, label) {
|
|
24824
|
+
if (!icmPlugin) return;
|
|
24825
|
+
icmPlugin.set(ROUTINE_KEYS.MAP_ITEM, `Current ${label} item (${index + 1}/${total})`, item, "high");
|
|
24826
|
+
icmPlugin.set(ROUTINE_KEYS.MAP_INDEX, `Current ${label} index (0-based)`, index, "high");
|
|
24827
|
+
icmPlugin.set(ROUTINE_KEYS.MAP_TOTAL, `Total items in ${label}`, total, "high");
|
|
24828
|
+
}
|
|
24829
|
+
async function withTimeout(promise, timeoutMs, label) {
|
|
24830
|
+
if (!timeoutMs) return promise;
|
|
24831
|
+
let timer;
|
|
24832
|
+
const timeout = new Promise((_, reject) => {
|
|
24833
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
24834
|
+
});
|
|
24835
|
+
try {
|
|
24836
|
+
return await Promise.race([promise, timeout]);
|
|
24837
|
+
} finally {
|
|
24838
|
+
clearTimeout(timer);
|
|
24839
|
+
}
|
|
24840
|
+
}
|
|
24841
|
+
async function handleMap(agent, flow, task, inputs) {
|
|
24842
|
+
const { icmPlugin, wmPlugin } = getPlugins(agent);
|
|
24843
|
+
const log = logger.child({ controlFlow: "map", task: task.name });
|
|
24844
|
+
const sourceResult = await readSourceArray(flow, "Map", icmPlugin, wmPlugin);
|
|
24845
|
+
if ("completed" in sourceResult) return sourceResult;
|
|
24846
|
+
const { array: array3, maxIter } = sourceResult;
|
|
24847
|
+
const results = [];
|
|
24848
|
+
const { augmented, baseInstructions } = prepareSubRoutine(flow.tasks, task.name);
|
|
24849
|
+
log.info({ arrayLength: array3.length, maxIterations: maxIter }, "Starting map iteration");
|
|
24850
|
+
try {
|
|
24851
|
+
for (let i = 0; i < maxIter; i++) {
|
|
24852
|
+
setIterationKeys(icmPlugin, array3[i], i, array3.length, "map");
|
|
24853
|
+
augmented.instructions = [
|
|
24854
|
+
`You are processing item ${i + 1} of ${array3.length} in a map operation.`,
|
|
24855
|
+
"The current item is available in your live context as __map_item.",
|
|
24856
|
+
"Current index (0-based) is in __map_index, total count in __map_total.",
|
|
24857
|
+
"",
|
|
24858
|
+
baseInstructions
|
|
24859
|
+
].join("\n");
|
|
24860
|
+
const subExecution = await withTimeout(
|
|
24861
|
+
executeRoutine({ definition: augmented, agent, inputs }),
|
|
24862
|
+
flow.iterationTimeoutMs,
|
|
24863
|
+
`Map iteration ${i}`
|
|
24864
|
+
);
|
|
24865
|
+
if (subExecution.status !== "completed") {
|
|
24866
|
+
return {
|
|
24867
|
+
completed: false,
|
|
24868
|
+
error: `Map iteration ${i} failed: ${subExecution.error ?? "sub-routine failed"}`
|
|
24869
|
+
};
|
|
24870
|
+
}
|
|
24871
|
+
results.push(getSubRoutineOutput(subExecution));
|
|
24872
|
+
}
|
|
24873
|
+
} finally {
|
|
24874
|
+
cleanMapKeys(icmPlugin);
|
|
24875
|
+
}
|
|
24876
|
+
if (flow.resultKey) {
|
|
24877
|
+
await storeResult(flow.resultKey, `Map results from "${task.name}"`, results, icmPlugin, wmPlugin);
|
|
24878
|
+
}
|
|
24879
|
+
log.info({ resultCount: results.length }, "Map completed");
|
|
24880
|
+
return { completed: true, result: results };
|
|
24881
|
+
}
|
|
24882
|
+
async function handleFold(agent, flow, task, inputs) {
|
|
24883
|
+
const { icmPlugin, wmPlugin } = getPlugins(agent);
|
|
24884
|
+
const log = logger.child({ controlFlow: "fold", task: task.name });
|
|
24885
|
+
const sourceResult = await readSourceArray(flow, "Fold", icmPlugin, wmPlugin);
|
|
24886
|
+
if ("completed" in sourceResult) return sourceResult;
|
|
24887
|
+
const { array: array3, maxIter } = sourceResult;
|
|
24888
|
+
let accumulator = flow.initialValue;
|
|
24889
|
+
const { augmented, baseInstructions } = prepareSubRoutine(flow.tasks, task.name);
|
|
24890
|
+
log.info({ arrayLength: array3.length, maxIterations: maxIter }, "Starting fold iteration");
|
|
24891
|
+
try {
|
|
24892
|
+
for (let i = 0; i < maxIter; i++) {
|
|
24893
|
+
setIterationKeys(icmPlugin, array3[i], i, array3.length, "fold");
|
|
24894
|
+
if (icmPlugin) {
|
|
24895
|
+
icmPlugin.set(ROUTINE_KEYS.FOLD_ACCUMULATOR, "Running accumulator \u2014 update via context_set", accumulator, "high");
|
|
24896
|
+
}
|
|
24897
|
+
augmented.instructions = [
|
|
24898
|
+
`You are processing item ${i + 1} of ${array3.length} in a fold/accumulate operation.`,
|
|
24899
|
+
"The current item is in __map_item. The running accumulator is in __fold_accumulator.",
|
|
24900
|
+
"After processing, use context_set to update __fold_accumulator with the new accumulated value.",
|
|
24901
|
+
"Your final text response will also be captured as the result.",
|
|
24902
|
+
"",
|
|
24903
|
+
baseInstructions
|
|
24904
|
+
].join("\n");
|
|
24905
|
+
const subExecution = await withTimeout(
|
|
24906
|
+
executeRoutine({ definition: augmented, agent, inputs }),
|
|
24907
|
+
flow.iterationTimeoutMs,
|
|
24908
|
+
`Fold iteration ${i}`
|
|
24909
|
+
);
|
|
24910
|
+
if (subExecution.status !== "completed") {
|
|
24911
|
+
return {
|
|
24912
|
+
completed: false,
|
|
24913
|
+
error: `Fold iteration ${i} failed: ${subExecution.error ?? "sub-routine failed"}`
|
|
24914
|
+
};
|
|
24915
|
+
}
|
|
24916
|
+
const taskOutput = getSubRoutineOutput(subExecution);
|
|
24917
|
+
if (taskOutput !== null) {
|
|
24918
|
+
accumulator = taskOutput;
|
|
24919
|
+
} else if (icmPlugin) {
|
|
24920
|
+
const icmAccumulator = icmPlugin.get(ROUTINE_KEYS.FOLD_ACCUMULATOR);
|
|
24921
|
+
if (icmAccumulator !== void 0) {
|
|
24922
|
+
accumulator = icmAccumulator;
|
|
24923
|
+
}
|
|
24924
|
+
}
|
|
24925
|
+
}
|
|
24926
|
+
} finally {
|
|
24927
|
+
cleanFoldKeys(icmPlugin);
|
|
24928
|
+
}
|
|
24929
|
+
await storeResult(flow.resultKey, `Fold result from "${task.name}"`, accumulator, icmPlugin, wmPlugin);
|
|
24930
|
+
log.info("Fold completed");
|
|
24931
|
+
return { completed: true, result: accumulator };
|
|
24932
|
+
}
|
|
24933
|
+
async function handleUntil(agent, flow, task, inputs) {
|
|
24934
|
+
const { icmPlugin, wmPlugin } = getPlugins(agent);
|
|
24935
|
+
const log = logger.child({ controlFlow: "until", task: task.name });
|
|
24936
|
+
const { augmented, baseInstructions } = prepareSubRoutine(flow.tasks, task.name);
|
|
24937
|
+
log.info({ maxIterations: flow.maxIterations }, "Starting until loop");
|
|
24938
|
+
const memoryAccess = {
|
|
24939
|
+
get: (key) => readMemoryValue(key, icmPlugin, wmPlugin)
|
|
24940
|
+
};
|
|
24941
|
+
try {
|
|
24942
|
+
for (let i = 0; i < flow.maxIterations; i++) {
|
|
24943
|
+
if (flow.iterationKey && icmPlugin) {
|
|
24944
|
+
icmPlugin.set(flow.iterationKey, "Current iteration index", i, "high");
|
|
24945
|
+
}
|
|
24946
|
+
augmented.instructions = [
|
|
24947
|
+
`You are in iteration ${i + 1} of a repeating operation (max ${flow.maxIterations}).`,
|
|
24948
|
+
"Complete the task. The loop will continue until its exit condition is met.",
|
|
24949
|
+
"",
|
|
24950
|
+
baseInstructions
|
|
24951
|
+
].join("\n");
|
|
24952
|
+
const subExecution = await withTimeout(
|
|
24953
|
+
executeRoutine({ definition: augmented, agent, inputs }),
|
|
24954
|
+
flow.iterationTimeoutMs,
|
|
24955
|
+
`Until iteration ${i}`
|
|
24956
|
+
);
|
|
24957
|
+
if (subExecution.status !== "completed") {
|
|
24958
|
+
return {
|
|
24959
|
+
completed: false,
|
|
24960
|
+
error: `Until iteration ${i} failed: ${subExecution.error ?? "sub-routine failed"}`
|
|
24961
|
+
};
|
|
24962
|
+
}
|
|
24963
|
+
const conditionMet = await evaluateCondition(flow.condition, memoryAccess);
|
|
24964
|
+
if (conditionMet) {
|
|
24965
|
+
log.info({ iteration: i + 1 }, "Until condition met");
|
|
24966
|
+
return { completed: true };
|
|
24967
|
+
}
|
|
24968
|
+
}
|
|
24969
|
+
} finally {
|
|
24970
|
+
if (flow.iterationKey && icmPlugin) {
|
|
24971
|
+
icmPlugin.delete(flow.iterationKey);
|
|
24972
|
+
}
|
|
24973
|
+
}
|
|
24974
|
+
return { completed: false, error: `Until loop: maxIterations (${flow.maxIterations}) exceeded` };
|
|
24975
|
+
}
|
|
24976
|
+
async function executeControlFlow(agent, task, inputs) {
|
|
24977
|
+
const flow = task.controlFlow;
|
|
24978
|
+
switch (flow.type) {
|
|
24979
|
+
case "map":
|
|
24980
|
+
return handleMap(agent, flow, task, inputs);
|
|
24981
|
+
case "fold":
|
|
24982
|
+
return handleFold(agent, flow, task, inputs);
|
|
24983
|
+
case "until":
|
|
24984
|
+
return handleUntil(agent, flow, task, inputs);
|
|
24985
|
+
default:
|
|
24986
|
+
return { completed: false, error: `Unknown control flow type: ${flow.type}` };
|
|
24987
|
+
}
|
|
24988
|
+
}
|
|
24989
|
+
|
|
24990
|
+
// src/core/routineRunner.ts
|
|
24471
24991
|
function defaultSystemPrompt(definition) {
|
|
24472
24992
|
const parts = [];
|
|
24473
24993
|
if (definition.instructions) {
|
|
@@ -24596,6 +25116,14 @@ async function collectValidationContext(agent, responseText) {
|
|
|
24596
25116
|
toolCallLog
|
|
24597
25117
|
};
|
|
24598
25118
|
}
|
|
25119
|
+
function isTransientError(error) {
|
|
25120
|
+
if (error instanceof ProviderAuthError) return false;
|
|
25121
|
+
if (error instanceof ProviderContextLengthError) return false;
|
|
25122
|
+
if (error instanceof ProviderNotFoundError) return false;
|
|
25123
|
+
if (error instanceof ModelNotSupportedError) return false;
|
|
25124
|
+
if (error instanceof InvalidConfigError) return false;
|
|
25125
|
+
return true;
|
|
25126
|
+
}
|
|
24599
25127
|
function estimateTokens(text) {
|
|
24600
25128
|
return Math.ceil(text.length / 4);
|
|
24601
25129
|
}
|
|
@@ -24639,32 +25167,42 @@ function buildPlanOverview(execution, definition, currentTaskId) {
|
|
|
24639
25167
|
}
|
|
24640
25168
|
return parts.join("\n");
|
|
24641
25169
|
}
|
|
24642
|
-
async function
|
|
24643
|
-
const icmPlugin = agent.context.getPlugin("in_context_memory");
|
|
24644
|
-
const wmPlugin = agent.context.memory;
|
|
24645
|
-
if (!icmPlugin && !wmPlugin) {
|
|
24646
|
-
logger.warn("injectRoutineContext: No ICM or WM plugin available \u2014 skipping context injection");
|
|
24647
|
-
return;
|
|
24648
|
-
}
|
|
24649
|
-
const planOverview = buildPlanOverview(execution, definition, currentTask.id);
|
|
24650
|
-
if (icmPlugin) {
|
|
24651
|
-
icmPlugin.set("__routine_plan", "Routine plan overview with task statuses", planOverview, "high");
|
|
24652
|
-
}
|
|
25170
|
+
async function cleanupMemoryKeys(icmPlugin, wmPlugin, config) {
|
|
24653
25171
|
if (icmPlugin) {
|
|
24654
25172
|
for (const entry of icmPlugin.list()) {
|
|
24655
|
-
|
|
24656
|
-
|
|
24657
|
-
}
|
|
25173
|
+
const shouldDelete = config.icmPrefixes.some((p) => entry.key.startsWith(p)) || (config.icmExactKeys?.includes(entry.key) ?? false);
|
|
25174
|
+
if (shouldDelete) icmPlugin.delete(entry.key);
|
|
24658
25175
|
}
|
|
24659
25176
|
}
|
|
24660
25177
|
if (wmPlugin) {
|
|
24661
25178
|
const { entries: wmEntries } = await wmPlugin.query();
|
|
24662
25179
|
for (const entry of wmEntries) {
|
|
24663
|
-
if (
|
|
25180
|
+
if (config.wmPrefixes.some((p) => entry.key.startsWith(p))) {
|
|
24664
25181
|
await wmPlugin.delete(entry.key);
|
|
24665
25182
|
}
|
|
24666
25183
|
}
|
|
24667
25184
|
}
|
|
25185
|
+
}
|
|
25186
|
+
var DEP_CLEANUP_CONFIG = {
|
|
25187
|
+
icmPrefixes: [ROUTINE_KEYS.DEP_RESULT_PREFIX],
|
|
25188
|
+
icmExactKeys: [ROUTINE_KEYS.DEPS],
|
|
25189
|
+
wmPrefixes: [ROUTINE_KEYS.DEP_RESULT_PREFIX, ROUTINE_KEYS.WM_DEP_FINDINGS_PREFIX]
|
|
25190
|
+
};
|
|
25191
|
+
var FULL_CLEANUP_CONFIG = {
|
|
25192
|
+
icmPrefixes: ["__routine_", ROUTINE_KEYS.DEP_RESULT_PREFIX, "__map_", "__fold_"],
|
|
25193
|
+
wmPrefixes: [ROUTINE_KEYS.DEP_RESULT_PREFIX, ROUTINE_KEYS.WM_DEP_FINDINGS_PREFIX]
|
|
25194
|
+
};
|
|
25195
|
+
async function injectRoutineContext(agent, execution, definition, currentTask) {
|
|
25196
|
+
const { icmPlugin, wmPlugin } = getPlugins(agent);
|
|
25197
|
+
if (!icmPlugin && !wmPlugin) {
|
|
25198
|
+
logger.warn("injectRoutineContext: No ICM or WM plugin available \u2014 skipping context injection");
|
|
25199
|
+
return;
|
|
25200
|
+
}
|
|
25201
|
+
const planOverview = buildPlanOverview(execution, definition, currentTask.id);
|
|
25202
|
+
if (icmPlugin) {
|
|
25203
|
+
icmPlugin.set(ROUTINE_KEYS.PLAN, "Routine plan overview with task statuses", planOverview, "high");
|
|
25204
|
+
}
|
|
25205
|
+
await cleanupMemoryKeys(icmPlugin, wmPlugin, DEP_CLEANUP_CONFIG);
|
|
24668
25206
|
if (currentTask.dependsOn.length === 0) return;
|
|
24669
25207
|
const inContextDeps = [];
|
|
24670
25208
|
const workingMemoryDeps = [];
|
|
@@ -24673,7 +25211,7 @@ async function injectRoutineContext(agent, execution, definition, currentTask) {
|
|
|
24673
25211
|
if (!depTask?.result?.output) continue;
|
|
24674
25212
|
const output = typeof depTask.result.output === "string" ? depTask.result.output : JSON.stringify(depTask.result.output);
|
|
24675
25213
|
const tokens = estimateTokens(output);
|
|
24676
|
-
const depKey =
|
|
25214
|
+
const depKey = `${ROUTINE_KEYS.DEP_RESULT_PREFIX}${depId}`;
|
|
24677
25215
|
const depLabel = `Result from task "${depTask.name}"`;
|
|
24678
25216
|
if (tokens < 5e3 && icmPlugin) {
|
|
24679
25217
|
icmPlugin.set(depKey, depLabel, output, "high");
|
|
@@ -24695,27 +25233,12 @@ async function injectRoutineContext(agent, execution, definition, currentTask) {
|
|
|
24695
25233
|
if (workingMemoryDeps.length > 0) {
|
|
24696
25234
|
summaryParts.push(`In working memory (use memory_retrieve): ${workingMemoryDeps.join(", ")}`);
|
|
24697
25235
|
}
|
|
24698
|
-
icmPlugin.set(
|
|
25236
|
+
icmPlugin.set(ROUTINE_KEYS.DEPS, "Dependency results location guide", summaryParts.join("\n"), "high");
|
|
24699
25237
|
}
|
|
24700
25238
|
}
|
|
24701
25239
|
async function cleanupRoutineContext(agent) {
|
|
24702
|
-
const icmPlugin = agent
|
|
24703
|
-
|
|
24704
|
-
if (icmPlugin) {
|
|
24705
|
-
for (const entry of icmPlugin.list()) {
|
|
24706
|
-
if (entry.key.startsWith("__routine_") || entry.key.startsWith("__dep_result_")) {
|
|
24707
|
-
icmPlugin.delete(entry.key);
|
|
24708
|
-
}
|
|
24709
|
-
}
|
|
24710
|
-
}
|
|
24711
|
-
if (wmPlugin) {
|
|
24712
|
-
const { entries: wmEntries } = await wmPlugin.query();
|
|
24713
|
-
for (const entry of wmEntries) {
|
|
24714
|
-
if (entry.key.startsWith("__dep_result_") || entry.key.startsWith("findings/__dep_result_")) {
|
|
24715
|
-
await wmPlugin.delete(entry.key);
|
|
24716
|
-
}
|
|
24717
|
-
}
|
|
24718
|
-
}
|
|
25240
|
+
const { icmPlugin, wmPlugin } = getPlugins(agent);
|
|
25241
|
+
await cleanupMemoryKeys(icmPlugin, wmPlugin, FULL_CLEANUP_CONFIG);
|
|
24719
25242
|
}
|
|
24720
25243
|
async function validateTaskCompletion(agent, task, responseText, validationPromptBuilder) {
|
|
24721
25244
|
const hasExplicitValidation = task.validation?.skipReflection === false && task.validation?.completionCriteria && task.validation.completionCriteria.length > 0;
|
|
@@ -24764,11 +25287,13 @@ async function executeRoutine(options) {
|
|
|
24764
25287
|
onTaskFailed,
|
|
24765
25288
|
onTaskValidation,
|
|
24766
25289
|
hooks,
|
|
24767
|
-
prompts
|
|
25290
|
+
prompts,
|
|
25291
|
+
inputs: rawInputs
|
|
24768
25292
|
} = options;
|
|
24769
25293
|
if (!existingAgent && (!connector || !model)) {
|
|
24770
25294
|
throw new Error("executeRoutine requires either `agent` or both `connector` and `model`");
|
|
24771
25295
|
}
|
|
25296
|
+
const resolvedInputs = validateAndResolveInputs(definition.parameters, rawInputs);
|
|
24772
25297
|
const ownsAgent = !existingAgent;
|
|
24773
25298
|
const log = logger.child({ routine: definition.name });
|
|
24774
25299
|
const execution = createRoutineExecution(definition);
|
|
@@ -24861,85 +25386,115 @@ async function executeRoutine(options) {
|
|
|
24861
25386
|
return { shouldPause: false };
|
|
24862
25387
|
};
|
|
24863
25388
|
agent.registerHook("pause:check", iterationLimiter);
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
|
|
24870
|
-
|
|
24871
|
-
|
|
24872
|
-
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
24878
|
-
|
|
24879
|
-
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "completed");
|
|
24880
|
-
execution.plan.tasks[taskIndex].result = {
|
|
24881
|
-
success: true,
|
|
24882
|
-
output: responseText,
|
|
24883
|
-
validationScore: validationResult.completionScore,
|
|
24884
|
-
validationExplanation: validationResult.explanation
|
|
24885
|
-
};
|
|
24886
|
-
taskCompleted = true;
|
|
24887
|
-
log.info(
|
|
24888
|
-
{ taskName: getTask().name, score: validationResult.completionScore },
|
|
24889
|
-
"Task completed"
|
|
24890
|
-
);
|
|
24891
|
-
execution.progress = getRoutineProgress(execution);
|
|
24892
|
-
execution.lastUpdatedAt = Date.now();
|
|
24893
|
-
onTaskComplete?.(execution.plan.tasks[taskIndex], execution);
|
|
24894
|
-
} else {
|
|
24895
|
-
log.warn(
|
|
24896
|
-
{
|
|
24897
|
-
taskName: getTask().name,
|
|
24898
|
-
score: validationResult.completionScore,
|
|
24899
|
-
attempt: getTask().attempts,
|
|
24900
|
-
maxAttempts: getTask().maxAttempts
|
|
24901
|
-
},
|
|
24902
|
-
"Task validation failed"
|
|
24903
|
-
);
|
|
24904
|
-
if (getTask().attempts >= getTask().maxAttempts) {
|
|
25389
|
+
try {
|
|
25390
|
+
const getTask = () => execution.plan.tasks[taskIndex];
|
|
25391
|
+
await injectRoutineContext(agent, execution, definition, getTask());
|
|
25392
|
+
const { icmPlugin } = getPlugins(agent);
|
|
25393
|
+
if (getTask().controlFlow) {
|
|
25394
|
+
try {
|
|
25395
|
+
const cfResult = await executeControlFlow(agent, getTask(), resolvedInputs);
|
|
25396
|
+
if (cfResult.completed) {
|
|
25397
|
+
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "completed");
|
|
25398
|
+
execution.plan.tasks[taskIndex].result = { success: true, output: cfResult.result };
|
|
25399
|
+
taskCompleted = true;
|
|
25400
|
+
execution.progress = getRoutineProgress(execution);
|
|
25401
|
+
execution.lastUpdatedAt = Date.now();
|
|
25402
|
+
onTaskComplete?.(execution.plan.tasks[taskIndex], execution);
|
|
25403
|
+
} else {
|
|
24905
25404
|
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "failed");
|
|
24906
|
-
execution.plan.tasks[taskIndex].result = {
|
|
24907
|
-
success: false,
|
|
24908
|
-
error: validationResult.explanation,
|
|
24909
|
-
validationScore: validationResult.completionScore,
|
|
24910
|
-
validationExplanation: validationResult.explanation
|
|
24911
|
-
};
|
|
24912
|
-
break;
|
|
25405
|
+
execution.plan.tasks[taskIndex].result = { success: false, error: cfResult.error };
|
|
24913
25406
|
}
|
|
24914
|
-
|
|
24915
|
-
|
|
24916
|
-
|
|
24917
|
-
const errorMessage = error.message;
|
|
24918
|
-
log.error({ taskName: getTask().name, error: errorMessage }, "Task execution error");
|
|
24919
|
-
if (getTask().attempts >= getTask().maxAttempts) {
|
|
25407
|
+
} catch (error) {
|
|
25408
|
+
const errorMessage = error.message;
|
|
25409
|
+
log.error({ taskName: getTask().name, error: errorMessage }, "Control flow error");
|
|
24920
25410
|
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "failed");
|
|
24921
|
-
execution.plan.tasks[taskIndex].result = {
|
|
24922
|
-
|
|
24923
|
-
|
|
24924
|
-
|
|
24925
|
-
|
|
25411
|
+
execution.plan.tasks[taskIndex].result = { success: false, error: errorMessage };
|
|
25412
|
+
}
|
|
25413
|
+
} else {
|
|
25414
|
+
while (!taskCompleted) {
|
|
25415
|
+
try {
|
|
25416
|
+
const resolvedTask = resolveTaskTemplates(getTask(), resolvedInputs, icmPlugin);
|
|
25417
|
+
const taskPrompt = buildTaskPrompt(resolvedTask);
|
|
25418
|
+
const response = await agent.run(taskPrompt);
|
|
25419
|
+
const responseText = response.output_text ?? "";
|
|
25420
|
+
const validationResult = await validateTaskCompletion(
|
|
25421
|
+
agent,
|
|
25422
|
+
getTask(),
|
|
25423
|
+
responseText,
|
|
25424
|
+
buildValidationPrompt
|
|
25425
|
+
);
|
|
25426
|
+
onTaskValidation?.(getTask(), validationResult, execution);
|
|
25427
|
+
if (validationResult.isComplete) {
|
|
25428
|
+
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "completed");
|
|
25429
|
+
execution.plan.tasks[taskIndex].result = {
|
|
25430
|
+
success: true,
|
|
25431
|
+
output: responseText,
|
|
25432
|
+
validationScore: validationResult.completionScore,
|
|
25433
|
+
validationExplanation: validationResult.explanation
|
|
25434
|
+
};
|
|
25435
|
+
taskCompleted = true;
|
|
25436
|
+
log.info(
|
|
25437
|
+
{ taskName: getTask().name, score: validationResult.completionScore },
|
|
25438
|
+
"Task completed"
|
|
25439
|
+
);
|
|
25440
|
+
execution.progress = getRoutineProgress(execution);
|
|
25441
|
+
execution.lastUpdatedAt = Date.now();
|
|
25442
|
+
onTaskComplete?.(execution.plan.tasks[taskIndex], execution);
|
|
25443
|
+
} else {
|
|
25444
|
+
log.warn(
|
|
25445
|
+
{
|
|
25446
|
+
taskName: getTask().name,
|
|
25447
|
+
score: validationResult.completionScore,
|
|
25448
|
+
attempt: getTask().attempts,
|
|
25449
|
+
maxAttempts: getTask().maxAttempts
|
|
25450
|
+
},
|
|
25451
|
+
"Task validation failed"
|
|
25452
|
+
);
|
|
25453
|
+
if (getTask().attempts >= getTask().maxAttempts) {
|
|
25454
|
+
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "failed");
|
|
25455
|
+
execution.plan.tasks[taskIndex].result = {
|
|
25456
|
+
success: false,
|
|
25457
|
+
error: validationResult.explanation,
|
|
25458
|
+
validationScore: validationResult.completionScore,
|
|
25459
|
+
validationExplanation: validationResult.explanation
|
|
25460
|
+
};
|
|
25461
|
+
break;
|
|
25462
|
+
}
|
|
25463
|
+
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "in_progress");
|
|
25464
|
+
}
|
|
25465
|
+
} catch (error) {
|
|
25466
|
+
const errorMessage = error.message;
|
|
25467
|
+
log.error({ taskName: getTask().name, error: errorMessage }, "Task execution error");
|
|
25468
|
+
if (!isTransientError(error) || getTask().attempts >= getTask().maxAttempts) {
|
|
25469
|
+
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "failed");
|
|
25470
|
+
execution.plan.tasks[taskIndex].result = {
|
|
25471
|
+
success: false,
|
|
25472
|
+
error: errorMessage
|
|
25473
|
+
};
|
|
25474
|
+
break;
|
|
25475
|
+
}
|
|
25476
|
+
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "in_progress");
|
|
25477
|
+
}
|
|
24926
25478
|
}
|
|
24927
|
-
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "in_progress");
|
|
24928
25479
|
}
|
|
24929
|
-
|
|
24930
|
-
|
|
24931
|
-
execution.progress = getRoutineProgress(execution);
|
|
24932
|
-
execution.lastUpdatedAt = Date.now();
|
|
24933
|
-
onTaskFailed?.(execution.plan.tasks[taskIndex], execution);
|
|
24934
|
-
if (failureMode === "fail-fast") {
|
|
24935
|
-
execution.status = "failed";
|
|
24936
|
-
execution.error = `Task "${getTask().name}" failed after ${getTask().attempts} attempt(s)`;
|
|
24937
|
-
execution.completedAt = Date.now();
|
|
25480
|
+
if (!taskCompleted) {
|
|
25481
|
+
execution.progress = getRoutineProgress(execution);
|
|
24938
25482
|
execution.lastUpdatedAt = Date.now();
|
|
24939
|
-
|
|
25483
|
+
onTaskFailed?.(execution.plan.tasks[taskIndex], execution);
|
|
25484
|
+
if (failureMode === "fail-fast") {
|
|
25485
|
+
execution.status = "failed";
|
|
25486
|
+
execution.error = `Task "${getTask().name}" failed after ${getTask().attempts} attempt(s)`;
|
|
25487
|
+
execution.completedAt = Date.now();
|
|
25488
|
+
execution.lastUpdatedAt = Date.now();
|
|
25489
|
+
break;
|
|
25490
|
+
}
|
|
25491
|
+
}
|
|
25492
|
+
} finally {
|
|
25493
|
+
try {
|
|
25494
|
+
agent.unregisterHook("pause:check", iterationLimiter);
|
|
25495
|
+
} catch {
|
|
24940
25496
|
}
|
|
24941
25497
|
}
|
|
24942
|
-
agent.unregisterHook("pause:check", iterationLimiter);
|
|
24943
25498
|
agent.clearConversation("task-boundary");
|
|
24944
25499
|
nextTasks = getNextExecutableTasks(execution.plan);
|
|
24945
25500
|
}
|
|
@@ -24967,16 +25522,22 @@ async function executeRoutine(options) {
|
|
|
24967
25522
|
} finally {
|
|
24968
25523
|
try {
|
|
24969
25524
|
await cleanupRoutineContext(agent);
|
|
24970
|
-
} catch {
|
|
25525
|
+
} catch (e) {
|
|
25526
|
+
log.debug({ error: e.message }, "Failed to clean up routine context");
|
|
24971
25527
|
}
|
|
24972
25528
|
for (const { name, hook } of registeredHooks) {
|
|
24973
25529
|
try {
|
|
24974
25530
|
agent.unregisterHook(name, hook);
|
|
24975
|
-
} catch {
|
|
25531
|
+
} catch (e) {
|
|
25532
|
+
log.debug({ hookName: name, error: e.message }, "Failed to unregister hook");
|
|
24976
25533
|
}
|
|
24977
25534
|
}
|
|
24978
25535
|
if (ownsAgent) {
|
|
24979
|
-
|
|
25536
|
+
try {
|
|
25537
|
+
agent.destroy();
|
|
25538
|
+
} catch (e) {
|
|
25539
|
+
log.debug({ error: e.message }, "Failed to destroy agent");
|
|
25540
|
+
}
|
|
24980
25541
|
}
|
|
24981
25542
|
}
|
|
24982
25543
|
}
|
|
@@ -31783,7 +32344,7 @@ var TextToSpeech = class _TextToSpeech {
|
|
|
31783
32344
|
*/
|
|
31784
32345
|
async toFile(text, filePath, options) {
|
|
31785
32346
|
const response = await this.synthesize(text, options);
|
|
31786
|
-
await
|
|
32347
|
+
await fs17.writeFile(filePath, response.audio);
|
|
31787
32348
|
}
|
|
31788
32349
|
// ======================== Introspection Methods ========================
|
|
31789
32350
|
/**
|
|
@@ -32131,7 +32692,7 @@ var SpeechToText = class _SpeechToText {
|
|
|
32131
32692
|
* @param options - Optional transcription parameters
|
|
32132
32693
|
*/
|
|
32133
32694
|
async transcribeFile(filePath, options) {
|
|
32134
|
-
const audio = await
|
|
32695
|
+
const audio = await fs17.readFile(filePath);
|
|
32135
32696
|
return this.transcribe(audio, options);
|
|
32136
32697
|
}
|
|
32137
32698
|
/**
|
|
@@ -38874,10 +39435,10 @@ var FileMediaStorage = class {
|
|
|
38874
39435
|
}
|
|
38875
39436
|
async save(data, metadata) {
|
|
38876
39437
|
const dir = metadata.userId ? path2.join(this.outputDir, metadata.userId) : this.outputDir;
|
|
38877
|
-
await
|
|
39438
|
+
await fs17.mkdir(dir, { recursive: true });
|
|
38878
39439
|
const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
|
|
38879
39440
|
const filePath = path2.join(dir, filename);
|
|
38880
|
-
await
|
|
39441
|
+
await fs17.writeFile(filePath, data);
|
|
38881
39442
|
const format = metadata.format.toLowerCase();
|
|
38882
39443
|
const mimeType = MIME_TYPES2[format] ?? "application/octet-stream";
|
|
38883
39444
|
return {
|
|
@@ -38888,7 +39449,7 @@ var FileMediaStorage = class {
|
|
|
38888
39449
|
}
|
|
38889
39450
|
async read(location) {
|
|
38890
39451
|
try {
|
|
38891
|
-
return await
|
|
39452
|
+
return await fs17.readFile(location);
|
|
38892
39453
|
} catch (err) {
|
|
38893
39454
|
if (err.code === "ENOENT") {
|
|
38894
39455
|
return null;
|
|
@@ -38898,7 +39459,7 @@ var FileMediaStorage = class {
|
|
|
38898
39459
|
}
|
|
38899
39460
|
async delete(location) {
|
|
38900
39461
|
try {
|
|
38901
|
-
await
|
|
39462
|
+
await fs17.unlink(location);
|
|
38902
39463
|
} catch (err) {
|
|
38903
39464
|
if (err.code === "ENOENT") {
|
|
38904
39465
|
return;
|
|
@@ -38908,7 +39469,7 @@ var FileMediaStorage = class {
|
|
|
38908
39469
|
}
|
|
38909
39470
|
async exists(location) {
|
|
38910
39471
|
try {
|
|
38911
|
-
await
|
|
39472
|
+
await fs17.access(location);
|
|
38912
39473
|
return true;
|
|
38913
39474
|
} catch {
|
|
38914
39475
|
return false;
|
|
@@ -38917,11 +39478,11 @@ var FileMediaStorage = class {
|
|
|
38917
39478
|
async list(options) {
|
|
38918
39479
|
await this.ensureDir();
|
|
38919
39480
|
let entries = [];
|
|
38920
|
-
const files = await
|
|
39481
|
+
const files = await fs17.readdir(this.outputDir);
|
|
38921
39482
|
for (const file of files) {
|
|
38922
39483
|
const filePath = path2.join(this.outputDir, file);
|
|
38923
39484
|
try {
|
|
38924
|
-
const stat6 = await
|
|
39485
|
+
const stat6 = await fs17.stat(filePath);
|
|
38925
39486
|
if (!stat6.isFile()) continue;
|
|
38926
39487
|
const ext = path2.extname(file).slice(1).toLowerCase();
|
|
38927
39488
|
const mimeType = MIME_TYPES2[ext] ?? "application/octet-stream";
|
|
@@ -38961,7 +39522,7 @@ var FileMediaStorage = class {
|
|
|
38961
39522
|
}
|
|
38962
39523
|
async ensureDir() {
|
|
38963
39524
|
if (!this.initialized) {
|
|
38964
|
-
await
|
|
39525
|
+
await fs17.mkdir(this.outputDir, { recursive: true });
|
|
38965
39526
|
this.initialized = true;
|
|
38966
39527
|
}
|
|
38967
39528
|
}
|
|
@@ -39813,6 +40374,15 @@ var SERVICE_DEFINITIONS = [
|
|
|
39813
40374
|
baseURL: "https://api.telegram.org",
|
|
39814
40375
|
docsURL: "https://core.telegram.org/bots/api"
|
|
39815
40376
|
},
|
|
40377
|
+
{
|
|
40378
|
+
id: "twitter",
|
|
40379
|
+
name: "X (Twitter)",
|
|
40380
|
+
category: "communication",
|
|
40381
|
+
urlPattern: /api\.x\.com|api\.twitter\.com/i,
|
|
40382
|
+
baseURL: "https://api.x.com/2",
|
|
40383
|
+
docsURL: "https://developer.x.com/en/docs/x-api",
|
|
40384
|
+
commonScopes: ["tweet.read", "tweet.write", "users.read", "offline.access"]
|
|
40385
|
+
},
|
|
39816
40386
|
// ============ Development & Project Management ============
|
|
39817
40387
|
{
|
|
39818
40388
|
id: "github",
|
|
@@ -40300,19 +40870,30 @@ var ConnectorTools = class {
|
|
|
40300
40870
|
*/
|
|
40301
40871
|
static for(connectorOrName, userId, options) {
|
|
40302
40872
|
const connector = this.resolveConnector(connectorOrName, options?.registry);
|
|
40873
|
+
const accountId = options?.accountId;
|
|
40303
40874
|
const tools = [];
|
|
40875
|
+
const namePrefix = accountId ? `${sanitizeToolName(connector.name)}_${sanitizeToolName(accountId)}` : sanitizeToolName(connector.name);
|
|
40304
40876
|
if (connector.baseURL) {
|
|
40305
|
-
|
|
40877
|
+
const accountLabel = accountId ? ` (account: ${accountId})` : "";
|
|
40878
|
+
tools.push(this.createGenericAPITool(connector, {
|
|
40879
|
+
userId,
|
|
40880
|
+
accountId,
|
|
40881
|
+
toolName: `${namePrefix}_api`,
|
|
40882
|
+
description: `Make an authenticated API call to ${connector.displayName}${accountLabel}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}.` : " Provide full URL in endpoint.") + ' IMPORTANT: For POST/PUT/PATCH requests, pass data in the "body" parameter as a JSON object, NOT as query string parameters in the endpoint URL. The body is sent as application/json.'
|
|
40883
|
+
}));
|
|
40306
40884
|
}
|
|
40307
40885
|
const serviceType = this.detectService(connector);
|
|
40308
40886
|
if (serviceType && this.factories.has(serviceType)) {
|
|
40309
40887
|
const factory = this.factories.get(serviceType);
|
|
40310
40888
|
const serviceTools = factory(connector, userId);
|
|
40311
40889
|
for (const tool of serviceTools) {
|
|
40312
|
-
tool.definition.function.name = `${
|
|
40890
|
+
tool.definition.function.name = `${namePrefix}_${tool.definition.function.name}`;
|
|
40313
40891
|
}
|
|
40314
40892
|
tools.push(...serviceTools);
|
|
40315
40893
|
}
|
|
40894
|
+
if (accountId) {
|
|
40895
|
+
return tools.map((tool) => this.bindAccountId(tool, accountId));
|
|
40896
|
+
}
|
|
40316
40897
|
return tools;
|
|
40317
40898
|
}
|
|
40318
40899
|
/**
|
|
@@ -40462,6 +41043,56 @@ var ConnectorTools = class {
|
|
|
40462
41043
|
}
|
|
40463
41044
|
return connectorOrName;
|
|
40464
41045
|
}
|
|
41046
|
+
/**
|
|
41047
|
+
* Generate tools for a set of auth identities.
|
|
41048
|
+
* Each identity gets its own tool set with unique name prefixes.
|
|
41049
|
+
*
|
|
41050
|
+
* @param identities - Array of auth identities
|
|
41051
|
+
* @param userId - Optional user ID for multi-user OAuth
|
|
41052
|
+
* @param options - Optional registry for scoped connector lookup
|
|
41053
|
+
* @returns Map of identity key to tool array
|
|
41054
|
+
*
|
|
41055
|
+
* @example
|
|
41056
|
+
* ```typescript
|
|
41057
|
+
* const toolsByIdentity = ConnectorTools.forIdentities([
|
|
41058
|
+
* { connector: 'microsoft', accountId: 'work' },
|
|
41059
|
+
* { connector: 'microsoft', accountId: 'personal' },
|
|
41060
|
+
* { connector: 'github' },
|
|
41061
|
+
* ]);
|
|
41062
|
+
* // Keys: 'microsoft:work', 'microsoft:personal', 'github'
|
|
41063
|
+
* ```
|
|
41064
|
+
*/
|
|
41065
|
+
static forIdentities(identities, userId, options) {
|
|
41066
|
+
const result = /* @__PURE__ */ new Map();
|
|
41067
|
+
for (const identity of identities) {
|
|
41068
|
+
const key = identity.accountId ? `${identity.connector}:${identity.accountId}` : identity.connector;
|
|
41069
|
+
try {
|
|
41070
|
+
const tools = this.for(identity.connector, userId, {
|
|
41071
|
+
registry: options?.registry,
|
|
41072
|
+
accountId: identity.accountId
|
|
41073
|
+
});
|
|
41074
|
+
if (tools.length > 0) {
|
|
41075
|
+
result.set(key, tools);
|
|
41076
|
+
}
|
|
41077
|
+
} catch (err) {
|
|
41078
|
+
logger.error(`[ConnectorTools.forIdentities] Error generating tools for identity ${key}: ${err instanceof Error ? err.message : String(err)}`);
|
|
41079
|
+
}
|
|
41080
|
+
}
|
|
41081
|
+
return result;
|
|
41082
|
+
}
|
|
41083
|
+
/**
|
|
41084
|
+
* Wrap a tool to inject accountId into ToolContext at execute time.
|
|
41085
|
+
* This allows identity-bound tools to use the correct account without
|
|
41086
|
+
* modifying every service tool factory.
|
|
41087
|
+
*/
|
|
41088
|
+
static bindAccountId(tool, accountId) {
|
|
41089
|
+
return {
|
|
41090
|
+
...tool,
|
|
41091
|
+
execute: async (args, context) => {
|
|
41092
|
+
return tool.execute(args, { ...context, accountId });
|
|
41093
|
+
}
|
|
41094
|
+
};
|
|
41095
|
+
}
|
|
40465
41096
|
static createGenericAPITool(connector, options) {
|
|
40466
41097
|
const toolName = options?.toolName ?? `${sanitizeToolName(connector.name)}_api`;
|
|
40467
41098
|
const userId = options?.userId;
|
|
@@ -40503,6 +41134,7 @@ var ConnectorTools = class {
|
|
|
40503
41134
|
},
|
|
40504
41135
|
execute: async (args, context) => {
|
|
40505
41136
|
const effectiveUserId = context?.userId ?? userId;
|
|
41137
|
+
const effectiveAccountId = context?.accountId;
|
|
40506
41138
|
let url2 = args.endpoint;
|
|
40507
41139
|
if (args.queryParams && Object.keys(args.queryParams).length > 0) {
|
|
40508
41140
|
const params = new URLSearchParams();
|
|
@@ -40535,7 +41167,8 @@ var ConnectorTools = class {
|
|
|
40535
41167
|
},
|
|
40536
41168
|
body: bodyStr
|
|
40537
41169
|
},
|
|
40538
|
-
effectiveUserId
|
|
41170
|
+
effectiveUserId,
|
|
41171
|
+
effectiveAccountId
|
|
40539
41172
|
);
|
|
40540
41173
|
const text = await response.text();
|
|
40541
41174
|
let data;
|
|
@@ -40596,8 +41229,8 @@ var FileStorage = class {
|
|
|
40596
41229
|
}
|
|
40597
41230
|
async ensureDirectory() {
|
|
40598
41231
|
try {
|
|
40599
|
-
await
|
|
40600
|
-
await
|
|
41232
|
+
await fs17.mkdir(this.directory, { recursive: true });
|
|
41233
|
+
await fs17.chmod(this.directory, 448);
|
|
40601
41234
|
} catch (error) {
|
|
40602
41235
|
}
|
|
40603
41236
|
}
|
|
@@ -40611,24 +41244,27 @@ var FileStorage = class {
|
|
|
40611
41244
|
async storeToken(key, token) {
|
|
40612
41245
|
await this.ensureDirectory();
|
|
40613
41246
|
const filePath = this.getFilePath(key);
|
|
40614
|
-
const
|
|
41247
|
+
const tokenWithKey = { ...token, _storageKey: key };
|
|
41248
|
+
const plaintext = JSON.stringify(tokenWithKey);
|
|
40615
41249
|
const encrypted = encrypt(plaintext, this.encryptionKey);
|
|
40616
|
-
await
|
|
40617
|
-
await
|
|
41250
|
+
await fs17.writeFile(filePath, encrypted, "utf8");
|
|
41251
|
+
await fs17.chmod(filePath, 384);
|
|
40618
41252
|
}
|
|
40619
41253
|
async getToken(key) {
|
|
40620
41254
|
const filePath = this.getFilePath(key);
|
|
40621
41255
|
try {
|
|
40622
|
-
const encrypted = await
|
|
41256
|
+
const encrypted = await fs17.readFile(filePath, "utf8");
|
|
40623
41257
|
const decrypted = decrypt(encrypted, this.encryptionKey);
|
|
40624
|
-
|
|
41258
|
+
const parsed = JSON.parse(decrypted);
|
|
41259
|
+
const { _storageKey, ...token } = parsed;
|
|
41260
|
+
return token;
|
|
40625
41261
|
} catch (error) {
|
|
40626
41262
|
if (error.code === "ENOENT") {
|
|
40627
41263
|
return null;
|
|
40628
41264
|
}
|
|
40629
41265
|
console.error("Failed to read/decrypt token file:", error);
|
|
40630
41266
|
try {
|
|
40631
|
-
await
|
|
41267
|
+
await fs17.unlink(filePath);
|
|
40632
41268
|
} catch {
|
|
40633
41269
|
}
|
|
40634
41270
|
return null;
|
|
@@ -40637,7 +41273,7 @@ var FileStorage = class {
|
|
|
40637
41273
|
async deleteToken(key) {
|
|
40638
41274
|
const filePath = this.getFilePath(key);
|
|
40639
41275
|
try {
|
|
40640
|
-
await
|
|
41276
|
+
await fs17.unlink(filePath);
|
|
40641
41277
|
} catch (error) {
|
|
40642
41278
|
if (error.code !== "ENOENT") {
|
|
40643
41279
|
throw error;
|
|
@@ -40647,18 +41283,44 @@ var FileStorage = class {
|
|
|
40647
41283
|
async hasToken(key) {
|
|
40648
41284
|
const filePath = this.getFilePath(key);
|
|
40649
41285
|
try {
|
|
40650
|
-
await
|
|
41286
|
+
await fs17.access(filePath);
|
|
40651
41287
|
return true;
|
|
40652
41288
|
} catch {
|
|
40653
41289
|
return false;
|
|
40654
41290
|
}
|
|
40655
41291
|
}
|
|
41292
|
+
/**
|
|
41293
|
+
* List all storage keys by decrypting each token file and reading _storageKey.
|
|
41294
|
+
* Falls back to returning hashed filenames for tokens stored before multi-account support.
|
|
41295
|
+
*/
|
|
41296
|
+
async listKeys() {
|
|
41297
|
+
try {
|
|
41298
|
+
const files = await fs17.readdir(this.directory);
|
|
41299
|
+
const tokenFiles = files.filter((f) => f.endsWith(".token"));
|
|
41300
|
+
const keys = [];
|
|
41301
|
+
for (const file of tokenFiles) {
|
|
41302
|
+
try {
|
|
41303
|
+
const filePath = path2.join(this.directory, file);
|
|
41304
|
+
const encrypted = await fs17.readFile(filePath, "utf8");
|
|
41305
|
+
const decrypted = decrypt(encrypted, this.encryptionKey);
|
|
41306
|
+
const parsed = JSON.parse(decrypted);
|
|
41307
|
+
if (parsed._storageKey) {
|
|
41308
|
+
keys.push(parsed._storageKey);
|
|
41309
|
+
}
|
|
41310
|
+
} catch {
|
|
41311
|
+
}
|
|
41312
|
+
}
|
|
41313
|
+
return keys;
|
|
41314
|
+
} catch {
|
|
41315
|
+
return [];
|
|
41316
|
+
}
|
|
41317
|
+
}
|
|
40656
41318
|
/**
|
|
40657
41319
|
* List all token keys (for debugging)
|
|
40658
41320
|
*/
|
|
40659
41321
|
async listTokens() {
|
|
40660
41322
|
try {
|
|
40661
|
-
const files = await
|
|
41323
|
+
const files = await fs17.readdir(this.directory);
|
|
40662
41324
|
return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
|
|
40663
41325
|
} catch {
|
|
40664
41326
|
return [];
|
|
@@ -40669,10 +41331,10 @@ var FileStorage = class {
|
|
|
40669
41331
|
*/
|
|
40670
41332
|
async clearAll() {
|
|
40671
41333
|
try {
|
|
40672
|
-
const files = await
|
|
41334
|
+
const files = await fs17.readdir(this.directory);
|
|
40673
41335
|
const tokenFiles = files.filter((f) => f.endsWith(".token"));
|
|
40674
41336
|
await Promise.all(
|
|
40675
|
-
tokenFiles.map((f) =>
|
|
41337
|
+
tokenFiles.map((f) => fs17.unlink(path2.join(this.directory, f)).catch(() => {
|
|
40676
41338
|
}))
|
|
40677
41339
|
);
|
|
40678
41340
|
} catch {
|
|
@@ -40682,14 +41344,14 @@ var FileStorage = class {
|
|
|
40682
41344
|
|
|
40683
41345
|
// src/connectors/authenticatedFetch.ts
|
|
40684
41346
|
init_Connector();
|
|
40685
|
-
async function authenticatedFetch(url2, options, authProvider, userId) {
|
|
41347
|
+
async function authenticatedFetch(url2, options, authProvider, userId, accountId) {
|
|
40686
41348
|
const connector = Connector.get(authProvider);
|
|
40687
|
-
return connector.fetch(url2.toString(), options, userId);
|
|
41349
|
+
return connector.fetch(url2.toString(), options, userId, accountId);
|
|
40688
41350
|
}
|
|
40689
|
-
function createAuthenticatedFetch(authProvider, userId) {
|
|
41351
|
+
function createAuthenticatedFetch(authProvider, userId, accountId) {
|
|
40690
41352
|
const connector = Connector.get(authProvider);
|
|
40691
41353
|
return async (url2, options) => {
|
|
40692
|
-
return connector.fetch(url2.toString(), options, userId);
|
|
41354
|
+
return connector.fetch(url2.toString(), options, userId, accountId);
|
|
40693
41355
|
};
|
|
40694
41356
|
}
|
|
40695
41357
|
|
|
@@ -41120,14 +41782,14 @@ var FileConnectorStorage = class {
|
|
|
41120
41782
|
await this.ensureDirectory();
|
|
41121
41783
|
const filePath = this.getFilePath(name);
|
|
41122
41784
|
const json = JSON.stringify(stored, null, 2);
|
|
41123
|
-
await
|
|
41124
|
-
await
|
|
41785
|
+
await fs17.writeFile(filePath, json, "utf8");
|
|
41786
|
+
await fs17.chmod(filePath, 384);
|
|
41125
41787
|
await this.updateIndex(name, "add");
|
|
41126
41788
|
}
|
|
41127
41789
|
async get(name) {
|
|
41128
41790
|
const filePath = this.getFilePath(name);
|
|
41129
41791
|
try {
|
|
41130
|
-
const json = await
|
|
41792
|
+
const json = await fs17.readFile(filePath, "utf8");
|
|
41131
41793
|
return JSON.parse(json);
|
|
41132
41794
|
} catch (error) {
|
|
41133
41795
|
const err = error;
|
|
@@ -41140,7 +41802,7 @@ var FileConnectorStorage = class {
|
|
|
41140
41802
|
async delete(name) {
|
|
41141
41803
|
const filePath = this.getFilePath(name);
|
|
41142
41804
|
try {
|
|
41143
|
-
await
|
|
41805
|
+
await fs17.unlink(filePath);
|
|
41144
41806
|
await this.updateIndex(name, "remove");
|
|
41145
41807
|
return true;
|
|
41146
41808
|
} catch (error) {
|
|
@@ -41154,7 +41816,7 @@ var FileConnectorStorage = class {
|
|
|
41154
41816
|
async has(name) {
|
|
41155
41817
|
const filePath = this.getFilePath(name);
|
|
41156
41818
|
try {
|
|
41157
|
-
await
|
|
41819
|
+
await fs17.access(filePath);
|
|
41158
41820
|
return true;
|
|
41159
41821
|
} catch {
|
|
41160
41822
|
return false;
|
|
@@ -41180,13 +41842,13 @@ var FileConnectorStorage = class {
|
|
|
41180
41842
|
*/
|
|
41181
41843
|
async clear() {
|
|
41182
41844
|
try {
|
|
41183
|
-
const files = await
|
|
41845
|
+
const files = await fs17.readdir(this.directory);
|
|
41184
41846
|
const connectorFiles = files.filter(
|
|
41185
41847
|
(f) => f.endsWith(".connector.json") || f === "_index.json"
|
|
41186
41848
|
);
|
|
41187
41849
|
await Promise.all(
|
|
41188
41850
|
connectorFiles.map(
|
|
41189
|
-
(f) =>
|
|
41851
|
+
(f) => fs17.unlink(path2.join(this.directory, f)).catch(() => {
|
|
41190
41852
|
})
|
|
41191
41853
|
)
|
|
41192
41854
|
);
|
|
@@ -41213,8 +41875,8 @@ var FileConnectorStorage = class {
|
|
|
41213
41875
|
async ensureDirectory() {
|
|
41214
41876
|
if (this.initialized) return;
|
|
41215
41877
|
try {
|
|
41216
|
-
await
|
|
41217
|
-
await
|
|
41878
|
+
await fs17.mkdir(this.directory, { recursive: true });
|
|
41879
|
+
await fs17.chmod(this.directory, 448);
|
|
41218
41880
|
this.initialized = true;
|
|
41219
41881
|
} catch {
|
|
41220
41882
|
this.initialized = true;
|
|
@@ -41225,7 +41887,7 @@ var FileConnectorStorage = class {
|
|
|
41225
41887
|
*/
|
|
41226
41888
|
async loadIndex() {
|
|
41227
41889
|
try {
|
|
41228
|
-
const json = await
|
|
41890
|
+
const json = await fs17.readFile(this.indexPath, "utf8");
|
|
41229
41891
|
return JSON.parse(json);
|
|
41230
41892
|
} catch {
|
|
41231
41893
|
return { connectors: {} };
|
|
@@ -41243,8 +41905,8 @@ var FileConnectorStorage = class {
|
|
|
41243
41905
|
delete index.connectors[hash];
|
|
41244
41906
|
}
|
|
41245
41907
|
const json = JSON.stringify(index, null, 2);
|
|
41246
|
-
await
|
|
41247
|
-
await
|
|
41908
|
+
await fs17.writeFile(this.indexPath, json, "utf8");
|
|
41909
|
+
await fs17.chmod(this.indexPath, 384);
|
|
41248
41910
|
}
|
|
41249
41911
|
};
|
|
41250
41912
|
|
|
@@ -41467,14 +42129,15 @@ var microsoftTemplate = {
|
|
|
41467
42129
|
name: "OAuth (Delegated Permissions)",
|
|
41468
42130
|
type: "oauth",
|
|
41469
42131
|
flow: "authorization_code",
|
|
41470
|
-
description: "User signs in with Microsoft account. Best for accessing user data (mail, calendar, files)",
|
|
41471
|
-
requiredFields: ["clientId", "
|
|
41472
|
-
optionalFields: ["scope"],
|
|
42132
|
+
description: "User signs in with Microsoft account. Best for accessing user data (mail, calendar, files). Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42133
|
+
requiredFields: ["clientId", "redirectUri", "tenantId"],
|
|
42134
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41473
42135
|
defaults: {
|
|
41474
42136
|
type: "oauth",
|
|
41475
42137
|
flow: "authorization_code",
|
|
41476
42138
|
authorizationUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize",
|
|
41477
|
-
tokenUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token"
|
|
42139
|
+
tokenUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token",
|
|
42140
|
+
usePKCE: true
|
|
41478
42141
|
},
|
|
41479
42142
|
scopes: [
|
|
41480
42143
|
"User.Read",
|
|
@@ -41560,14 +42223,15 @@ var googleTemplate = {
|
|
|
41560
42223
|
name: "OAuth (User Consent)",
|
|
41561
42224
|
type: "oauth",
|
|
41562
42225
|
flow: "authorization_code",
|
|
41563
|
-
description: "User logs in with Google account. Best for accessing user data (Drive, Gmail, Calendar)",
|
|
41564
|
-
requiredFields: ["clientId", "
|
|
41565
|
-
optionalFields: ["scope"],
|
|
42226
|
+
description: "User logs in with Google account. Best for accessing user data (Drive, Gmail, Calendar). Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42227
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42228
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41566
42229
|
defaults: {
|
|
41567
42230
|
type: "oauth",
|
|
41568
42231
|
flow: "authorization_code",
|
|
41569
42232
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
41570
|
-
tokenUrl: "https://oauth2.googleapis.com/token"
|
|
42233
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
42234
|
+
usePKCE: true
|
|
41571
42235
|
},
|
|
41572
42236
|
scopes: [
|
|
41573
42237
|
"https://www.googleapis.com/auth/drive",
|
|
@@ -41646,14 +42310,15 @@ var slackTemplate = {
|
|
|
41646
42310
|
name: "OAuth (User Token)",
|
|
41647
42311
|
type: "oauth",
|
|
41648
42312
|
flow: "authorization_code",
|
|
41649
|
-
description: "Distributed app - users authorize via Slack OAuth",
|
|
41650
|
-
requiredFields: ["clientId", "
|
|
41651
|
-
optionalFields: ["scope", "userScope"],
|
|
42313
|
+
description: "Distributed app - users authorize via Slack OAuth. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42314
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42315
|
+
optionalFields: ["clientSecret", "scope", "userScope"],
|
|
41652
42316
|
defaults: {
|
|
41653
42317
|
type: "oauth",
|
|
41654
42318
|
flow: "authorization_code",
|
|
41655
42319
|
authorizationUrl: "https://slack.com/oauth/v2/authorize",
|
|
41656
|
-
tokenUrl: "https://slack.com/api/oauth.v2.access"
|
|
42320
|
+
tokenUrl: "https://slack.com/api/oauth.v2.access",
|
|
42321
|
+
usePKCE: true
|
|
41657
42322
|
},
|
|
41658
42323
|
scopes: ["chat:write", "channels:read", "users:read", "im:write", "groups:read", "files:read", "files:write", "reactions:read", "reactions:write", "team:read"],
|
|
41659
42324
|
scopeDescriptions: {
|
|
@@ -41699,14 +42364,15 @@ var discordTemplate = {
|
|
|
41699
42364
|
name: "OAuth (User Token)",
|
|
41700
42365
|
type: "oauth",
|
|
41701
42366
|
flow: "authorization_code",
|
|
41702
|
-
description: "OAuth2 for user authorization - users grant permissions to your app",
|
|
41703
|
-
requiredFields: ["clientId", "
|
|
41704
|
-
optionalFields: ["scope"],
|
|
42367
|
+
description: "OAuth2 for user authorization - users grant permissions to your app. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42368
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42369
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41705
42370
|
defaults: {
|
|
41706
42371
|
type: "oauth",
|
|
41707
42372
|
flow: "authorization_code",
|
|
41708
42373
|
authorizationUrl: "https://discord.com/api/oauth2/authorize",
|
|
41709
|
-
tokenUrl: "https://discord.com/api/oauth2/token"
|
|
42374
|
+
tokenUrl: "https://discord.com/api/oauth2/token",
|
|
42375
|
+
usePKCE: true
|
|
41710
42376
|
},
|
|
41711
42377
|
scopes: ["identify", "email", "guilds", "guilds.members.read", "messages.read", "bot", "connections"],
|
|
41712
42378
|
scopeDescriptions: {
|
|
@@ -41748,6 +42414,92 @@ var telegramTemplate = {
|
|
|
41748
42414
|
]
|
|
41749
42415
|
};
|
|
41750
42416
|
|
|
42417
|
+
// src/connectors/vendors/templates/twitter.ts
|
|
42418
|
+
var twitterTemplate = {
|
|
42419
|
+
id: "twitter",
|
|
42420
|
+
name: "X (Twitter)",
|
|
42421
|
+
serviceType: "twitter",
|
|
42422
|
+
baseURL: "https://api.x.com/2",
|
|
42423
|
+
docsURL: "https://developer.x.com/en/docs/x-api",
|
|
42424
|
+
credentialsSetupURL: "https://developer.x.com/en/portal/dashboard",
|
|
42425
|
+
category: "communication",
|
|
42426
|
+
notes: "X (formerly Twitter) API v2. OAuth 2.0 with PKCE for user-context actions, Bearer Token for app-only access.",
|
|
42427
|
+
authTemplates: [
|
|
42428
|
+
{
|
|
42429
|
+
id: "oauth-user",
|
|
42430
|
+
name: "OAuth 2.0 (User Context)",
|
|
42431
|
+
type: "oauth",
|
|
42432
|
+
flow: "authorization_code",
|
|
42433
|
+
description: "User authorizes via X login - required for posting tweets, managing likes/follows, and accessing private data. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42434
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42435
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42436
|
+
defaults: {
|
|
42437
|
+
type: "oauth",
|
|
42438
|
+
flow: "authorization_code",
|
|
42439
|
+
authorizationUrl: "https://x.com/i/oauth2/authorize",
|
|
42440
|
+
tokenUrl: "https://api.x.com/2/oauth2/token",
|
|
42441
|
+
usePKCE: true
|
|
42442
|
+
},
|
|
42443
|
+
scopes: [
|
|
42444
|
+
"tweet.read",
|
|
42445
|
+
"tweet.write",
|
|
42446
|
+
"tweet.moderate.write",
|
|
42447
|
+
"users.read",
|
|
42448
|
+
"follows.read",
|
|
42449
|
+
"follows.write",
|
|
42450
|
+
"like.read",
|
|
42451
|
+
"like.write",
|
|
42452
|
+
"bookmark.read",
|
|
42453
|
+
"bookmark.write",
|
|
42454
|
+
"list.read",
|
|
42455
|
+
"list.write",
|
|
42456
|
+
"block.read",
|
|
42457
|
+
"block.write",
|
|
42458
|
+
"mute.read",
|
|
42459
|
+
"mute.write",
|
|
42460
|
+
"space.read",
|
|
42461
|
+
"dm.read",
|
|
42462
|
+
"dm.write",
|
|
42463
|
+
"offline.access"
|
|
42464
|
+
],
|
|
42465
|
+
scopeDescriptions: {
|
|
42466
|
+
"tweet.read": "Read tweets and timelines",
|
|
42467
|
+
"tweet.write": "Post and delete tweets",
|
|
42468
|
+
"tweet.moderate.write": "Hide and unhide replies",
|
|
42469
|
+
"users.read": "Read user profile information",
|
|
42470
|
+
"follows.read": "Read following/followers lists",
|
|
42471
|
+
"follows.write": "Follow and unfollow users",
|
|
42472
|
+
"like.read": "Read liked tweets",
|
|
42473
|
+
"like.write": "Like and unlike tweets",
|
|
42474
|
+
"bookmark.read": "Read bookmarked tweets",
|
|
42475
|
+
"bookmark.write": "Bookmark and remove bookmarks",
|
|
42476
|
+
"list.read": "Read lists",
|
|
42477
|
+
"list.write": "Create, edit, and delete lists",
|
|
42478
|
+
"block.read": "Read blocked users",
|
|
42479
|
+
"block.write": "Block and unblock users",
|
|
42480
|
+
"mute.read": "Read muted users",
|
|
42481
|
+
"mute.write": "Mute and unmute users",
|
|
42482
|
+
"space.read": "Read Spaces information",
|
|
42483
|
+
"dm.read": "Read direct messages",
|
|
42484
|
+
"dm.write": "Send direct messages",
|
|
42485
|
+
"offline.access": "Stay connected (refresh token)"
|
|
42486
|
+
}
|
|
42487
|
+
},
|
|
42488
|
+
{
|
|
42489
|
+
id: "bearer-token",
|
|
42490
|
+
name: "Bearer Token (App-Only)",
|
|
42491
|
+
type: "api_key",
|
|
42492
|
+
description: "App-only access using Bearer Token from developer portal. Can read public tweets, users, and spaces but cannot post or access private data.",
|
|
42493
|
+
requiredFields: ["apiKey"],
|
|
42494
|
+
defaults: {
|
|
42495
|
+
type: "api_key",
|
|
42496
|
+
headerName: "Authorization",
|
|
42497
|
+
headerPrefix: "Bearer"
|
|
42498
|
+
}
|
|
42499
|
+
}
|
|
42500
|
+
]
|
|
42501
|
+
};
|
|
42502
|
+
|
|
41751
42503
|
// src/connectors/vendors/templates/github.ts
|
|
41752
42504
|
var githubTemplate = {
|
|
41753
42505
|
id: "github",
|
|
@@ -41775,14 +42527,15 @@ var githubTemplate = {
|
|
|
41775
42527
|
name: "OAuth App (User Authorization)",
|
|
41776
42528
|
type: "oauth",
|
|
41777
42529
|
flow: "authorization_code",
|
|
41778
|
-
description: "User logs in via GitHub and grants permissions to your app",
|
|
41779
|
-
requiredFields: ["clientId", "
|
|
41780
|
-
optionalFields: ["scope"],
|
|
42530
|
+
description: "User logs in via GitHub and grants permissions to your app. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42531
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42532
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41781
42533
|
defaults: {
|
|
41782
42534
|
type: "oauth",
|
|
41783
42535
|
flow: "authorization_code",
|
|
41784
42536
|
authorizationUrl: "https://github.com/login/oauth/authorize",
|
|
41785
|
-
tokenUrl: "https://github.com/login/oauth/access_token"
|
|
42537
|
+
tokenUrl: "https://github.com/login/oauth/access_token",
|
|
42538
|
+
usePKCE: true
|
|
41786
42539
|
},
|
|
41787
42540
|
scopes: ["repo", "read:user", "user:email", "read:org", "workflow", "gist", "notifications", "delete_repo", "admin:org"],
|
|
41788
42541
|
scopeDescriptions: {
|
|
@@ -41841,14 +42594,15 @@ var gitlabTemplate = {
|
|
|
41841
42594
|
name: "OAuth (User Authorization)",
|
|
41842
42595
|
type: "oauth",
|
|
41843
42596
|
flow: "authorization_code",
|
|
41844
|
-
description: "OAuth2 application for user authorization",
|
|
41845
|
-
requiredFields: ["clientId", "
|
|
41846
|
-
optionalFields: ["scope"],
|
|
42597
|
+
description: "OAuth2 application for user authorization. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42598
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42599
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41847
42600
|
defaults: {
|
|
41848
42601
|
type: "oauth",
|
|
41849
42602
|
flow: "authorization_code",
|
|
41850
42603
|
authorizationUrl: "https://gitlab.com/oauth/authorize",
|
|
41851
|
-
tokenUrl: "https://gitlab.com/oauth/token"
|
|
42604
|
+
tokenUrl: "https://gitlab.com/oauth/token",
|
|
42605
|
+
usePKCE: true
|
|
41852
42606
|
},
|
|
41853
42607
|
scopes: ["api", "read_user", "read_repository", "write_repository"],
|
|
41854
42608
|
scopeDescriptions: {
|
|
@@ -41889,14 +42643,15 @@ var jiraTemplate = {
|
|
|
41889
42643
|
name: "OAuth 2.0 (3LO)",
|
|
41890
42644
|
type: "oauth",
|
|
41891
42645
|
flow: "authorization_code",
|
|
41892
|
-
description: "Three-legged OAuth for user authorization. Create app at developer.atlassian.com",
|
|
41893
|
-
requiredFields: ["clientId", "
|
|
41894
|
-
optionalFields: ["scope"],
|
|
42646
|
+
description: "Three-legged OAuth for user authorization. Create app at developer.atlassian.com. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42647
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42648
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41895
42649
|
defaults: {
|
|
41896
42650
|
type: "oauth",
|
|
41897
42651
|
flow: "authorization_code",
|
|
41898
42652
|
authorizationUrl: "https://auth.atlassian.com/authorize",
|
|
41899
|
-
tokenUrl: "https://auth.atlassian.com/oauth/token"
|
|
42653
|
+
tokenUrl: "https://auth.atlassian.com/oauth/token",
|
|
42654
|
+
usePKCE: true
|
|
41900
42655
|
},
|
|
41901
42656
|
scopes: ["read:jira-work", "write:jira-work", "read:jira-user", "manage:jira-project", "manage:jira-configuration"],
|
|
41902
42657
|
scopeDescriptions: {
|
|
@@ -41936,14 +42691,15 @@ var confluenceTemplate = {
|
|
|
41936
42691
|
name: "OAuth 2.0 (3LO)",
|
|
41937
42692
|
type: "oauth",
|
|
41938
42693
|
flow: "authorization_code",
|
|
41939
|
-
description: "Three-legged OAuth for user authorization",
|
|
41940
|
-
requiredFields: ["clientId", "
|
|
41941
|
-
optionalFields: ["scope"],
|
|
42694
|
+
description: "Three-legged OAuth for user authorization. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42695
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42696
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41942
42697
|
defaults: {
|
|
41943
42698
|
type: "oauth",
|
|
41944
42699
|
flow: "authorization_code",
|
|
41945
42700
|
authorizationUrl: "https://auth.atlassian.com/authorize",
|
|
41946
|
-
tokenUrl: "https://auth.atlassian.com/oauth/token"
|
|
42701
|
+
tokenUrl: "https://auth.atlassian.com/oauth/token",
|
|
42702
|
+
usePKCE: true
|
|
41947
42703
|
},
|
|
41948
42704
|
scopes: ["read:confluence-content.all", "write:confluence-content", "read:confluence-space.summary", "write:confluence-space", "read:confluence-user"],
|
|
41949
42705
|
scopeDescriptions: {
|
|
@@ -41982,14 +42738,15 @@ var bitbucketTemplate = {
|
|
|
41982
42738
|
name: "OAuth Consumer",
|
|
41983
42739
|
type: "oauth",
|
|
41984
42740
|
flow: "authorization_code",
|
|
41985
|
-
description: "OAuth consumer for user authorization. Create at Workspace Settings > OAuth consumers",
|
|
41986
|
-
requiredFields: ["clientId", "
|
|
41987
|
-
optionalFields: ["scope"],
|
|
42741
|
+
description: "OAuth consumer for user authorization. Create at Workspace Settings > OAuth consumers. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42742
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42743
|
+
optionalFields: ["clientSecret", "scope"],
|
|
41988
42744
|
defaults: {
|
|
41989
42745
|
type: "oauth",
|
|
41990
42746
|
flow: "authorization_code",
|
|
41991
42747
|
authorizationUrl: "https://bitbucket.org/site/oauth2/authorize",
|
|
41992
|
-
tokenUrl: "https://bitbucket.org/site/oauth2/access_token"
|
|
42748
|
+
tokenUrl: "https://bitbucket.org/site/oauth2/access_token",
|
|
42749
|
+
usePKCE: true
|
|
41993
42750
|
},
|
|
41994
42751
|
scopes: ["repository", "repository:write", "pullrequest", "pullrequest:write", "account", "pipeline", "wiki"],
|
|
41995
42752
|
scopeDescriptions: {
|
|
@@ -42031,14 +42788,15 @@ var trelloTemplate = {
|
|
|
42031
42788
|
name: "OAuth 1.0a",
|
|
42032
42789
|
type: "oauth",
|
|
42033
42790
|
flow: "authorization_code",
|
|
42034
|
-
description: "OAuth 1.0a for user authorization (legacy)",
|
|
42035
|
-
requiredFields: ["clientId", "
|
|
42036
|
-
optionalFields: ["scope"],
|
|
42791
|
+
description: "OAuth 1.0a for user authorization (legacy). Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42792
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42793
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42037
42794
|
defaults: {
|
|
42038
42795
|
type: "oauth",
|
|
42039
42796
|
flow: "authorization_code",
|
|
42040
42797
|
authorizationUrl: "https://trello.com/1/authorize",
|
|
42041
|
-
tokenUrl: "https://trello.com/1/OAuthGetAccessToken"
|
|
42798
|
+
tokenUrl: "https://trello.com/1/OAuthGetAccessToken",
|
|
42799
|
+
usePKCE: true
|
|
42042
42800
|
},
|
|
42043
42801
|
scopes: ["read", "write", "account"],
|
|
42044
42802
|
scopeDescriptions: {
|
|
@@ -42078,14 +42836,15 @@ var linearTemplate = {
|
|
|
42078
42836
|
name: "OAuth (User Authorization)",
|
|
42079
42837
|
type: "oauth",
|
|
42080
42838
|
flow: "authorization_code",
|
|
42081
|
-
description: "OAuth application for user authorization. Create at Settings > API > OAuth applications",
|
|
42082
|
-
requiredFields: ["clientId", "
|
|
42083
|
-
optionalFields: ["scope"],
|
|
42839
|
+
description: "OAuth application for user authorization. Create at Settings > API > OAuth applications. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42840
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42841
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42084
42842
|
defaults: {
|
|
42085
42843
|
type: "oauth",
|
|
42086
42844
|
flow: "authorization_code",
|
|
42087
42845
|
authorizationUrl: "https://linear.app/oauth/authorize",
|
|
42088
|
-
tokenUrl: "https://api.linear.app/oauth/token"
|
|
42846
|
+
tokenUrl: "https://api.linear.app/oauth/token",
|
|
42847
|
+
usePKCE: true
|
|
42089
42848
|
},
|
|
42090
42849
|
scopes: ["read", "write", "issues:create", "comments:create"]
|
|
42091
42850
|
}
|
|
@@ -42119,14 +42878,15 @@ var asanaTemplate = {
|
|
|
42119
42878
|
name: "OAuth (User Authorization)",
|
|
42120
42879
|
type: "oauth",
|
|
42121
42880
|
flow: "authorization_code",
|
|
42122
|
-
description: "OAuth application for user authorization. Create at developer console",
|
|
42123
|
-
requiredFields: ["clientId", "
|
|
42124
|
-
optionalFields: ["scope"],
|
|
42881
|
+
description: "OAuth application for user authorization. Create at developer console. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42882
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42883
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42125
42884
|
defaults: {
|
|
42126
42885
|
type: "oauth",
|
|
42127
42886
|
flow: "authorization_code",
|
|
42128
42887
|
authorizationUrl: "https://app.asana.com/-/oauth_authorize",
|
|
42129
|
-
tokenUrl: "https://app.asana.com/-/oauth_token"
|
|
42888
|
+
tokenUrl: "https://app.asana.com/-/oauth_token",
|
|
42889
|
+
usePKCE: true
|
|
42130
42890
|
},
|
|
42131
42891
|
scopes: ["default"]
|
|
42132
42892
|
}
|
|
@@ -42160,14 +42920,15 @@ var notionTemplate = {
|
|
|
42160
42920
|
name: "Public Integration (OAuth)",
|
|
42161
42921
|
type: "oauth",
|
|
42162
42922
|
flow: "authorization_code",
|
|
42163
|
-
description: "Public integration for multi-workspace access",
|
|
42164
|
-
requiredFields: ["clientId", "
|
|
42165
|
-
optionalFields: ["scope"],
|
|
42923
|
+
description: "Public integration for multi-workspace access. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42924
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42925
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42166
42926
|
defaults: {
|
|
42167
42927
|
type: "oauth",
|
|
42168
42928
|
flow: "authorization_code",
|
|
42169
42929
|
authorizationUrl: "https://api.notion.com/v1/oauth/authorize",
|
|
42170
|
-
tokenUrl: "https://api.notion.com/v1/oauth/token"
|
|
42930
|
+
tokenUrl: "https://api.notion.com/v1/oauth/token",
|
|
42931
|
+
usePKCE: true
|
|
42171
42932
|
}
|
|
42172
42933
|
}
|
|
42173
42934
|
]
|
|
@@ -42200,9 +42961,9 @@ var airtableTemplate = {
|
|
|
42200
42961
|
name: "OAuth (User Authorization)",
|
|
42201
42962
|
type: "oauth",
|
|
42202
42963
|
flow: "authorization_code",
|
|
42203
|
-
description: "OAuth integration for multi-user access. Register at airtable.com/create/oauth",
|
|
42204
|
-
requiredFields: ["clientId", "
|
|
42205
|
-
optionalFields: ["scope"],
|
|
42964
|
+
description: "OAuth integration for multi-user access. Register at airtable.com/create/oauth. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42965
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42966
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42206
42967
|
defaults: {
|
|
42207
42968
|
type: "oauth",
|
|
42208
42969
|
flow: "authorization_code",
|
|
@@ -42231,14 +42992,15 @@ var salesforceTemplate = {
|
|
|
42231
42992
|
name: "OAuth (User Authorization)",
|
|
42232
42993
|
type: "oauth",
|
|
42233
42994
|
flow: "authorization_code",
|
|
42234
|
-
description: "User logs in via Salesforce. Create Connected App in Setup",
|
|
42235
|
-
requiredFields: ["clientId", "
|
|
42236
|
-
optionalFields: ["scope"],
|
|
42995
|
+
description: "User logs in via Salesforce. Create Connected App in Setup. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
42996
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
42997
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42237
42998
|
defaults: {
|
|
42238
42999
|
type: "oauth",
|
|
42239
43000
|
flow: "authorization_code",
|
|
42240
43001
|
authorizationUrl: "https://login.salesforce.com/services/oauth2/authorize",
|
|
42241
|
-
tokenUrl: "https://login.salesforce.com/services/oauth2/token"
|
|
43002
|
+
tokenUrl: "https://login.salesforce.com/services/oauth2/token",
|
|
43003
|
+
usePKCE: true
|
|
42242
43004
|
},
|
|
42243
43005
|
scopes: ["api", "refresh_token", "offline_access", "chatter_api", "wave_api", "full"],
|
|
42244
43006
|
scopeDescriptions: {
|
|
@@ -42294,14 +43056,15 @@ var hubspotTemplate = {
|
|
|
42294
43056
|
name: "OAuth (User Authorization)",
|
|
42295
43057
|
type: "oauth",
|
|
42296
43058
|
flow: "authorization_code",
|
|
42297
|
-
description: "Public app OAuth for multi-portal access. Create app at developers.hubspot.com",
|
|
42298
|
-
requiredFields: ["clientId", "
|
|
42299
|
-
optionalFields: ["scope"],
|
|
43059
|
+
description: "Public app OAuth for multi-portal access. Create app at developers.hubspot.com. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43060
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43061
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42300
43062
|
defaults: {
|
|
42301
43063
|
type: "oauth",
|
|
42302
43064
|
flow: "authorization_code",
|
|
42303
43065
|
authorizationUrl: "https://app.hubspot.com/oauth/authorize",
|
|
42304
|
-
tokenUrl: "https://api.hubapi.com/oauth/v1/token"
|
|
43066
|
+
tokenUrl: "https://api.hubapi.com/oauth/v1/token",
|
|
43067
|
+
usePKCE: true
|
|
42305
43068
|
},
|
|
42306
43069
|
scopes: [
|
|
42307
43070
|
"crm.objects.contacts.read",
|
|
@@ -42323,6 +43086,22 @@ var hubspotTemplate = {
|
|
|
42323
43086
|
"tickets": "Read and write support tickets",
|
|
42324
43087
|
"e-commerce": "Access e-commerce data (products, line items)"
|
|
42325
43088
|
}
|
|
43089
|
+
},
|
|
43090
|
+
{
|
|
43091
|
+
id: "oauth-mcp",
|
|
43092
|
+
name: "MCP Auth App (OAuth 2.1)",
|
|
43093
|
+
type: "oauth",
|
|
43094
|
+
flow: "authorization_code",
|
|
43095
|
+
description: "HubSpot MCP Auth app using OAuth 2.1 with PKCE. Scopes are auto-granted based on user permissions at install time. Create app at developers.hubspot.com under MCP Auth Apps.",
|
|
43096
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43097
|
+
optionalFields: ["clientSecret"],
|
|
43098
|
+
defaults: {
|
|
43099
|
+
type: "oauth",
|
|
43100
|
+
flow: "authorization_code",
|
|
43101
|
+
authorizationUrl: "https://mcp.hubspot.com/oauth/authorize/user",
|
|
43102
|
+
tokenUrl: "https://mcp.hubspot.com/oauth/v1/token",
|
|
43103
|
+
usePKCE: true
|
|
43104
|
+
}
|
|
42326
43105
|
}
|
|
42327
43106
|
]
|
|
42328
43107
|
};
|
|
@@ -42354,14 +43133,15 @@ var pipedriveTemplate = {
|
|
|
42354
43133
|
name: "OAuth (App Authorization)",
|
|
42355
43134
|
type: "oauth",
|
|
42356
43135
|
flow: "authorization_code",
|
|
42357
|
-
description: "OAuth app for marketplace distribution. Create at developers.pipedrive.com",
|
|
42358
|
-
requiredFields: ["clientId", "
|
|
42359
|
-
optionalFields: ["scope"],
|
|
43136
|
+
description: "OAuth app for marketplace distribution. Create at developers.pipedrive.com. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43137
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43138
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42360
43139
|
defaults: {
|
|
42361
43140
|
type: "oauth",
|
|
42362
43141
|
flow: "authorization_code",
|
|
42363
43142
|
authorizationUrl: "https://oauth.pipedrive.com/oauth/authorize",
|
|
42364
|
-
tokenUrl: "https://oauth.pipedrive.com/oauth/token"
|
|
43143
|
+
tokenUrl: "https://oauth.pipedrive.com/oauth/token",
|
|
43144
|
+
usePKCE: true
|
|
42365
43145
|
}
|
|
42366
43146
|
}
|
|
42367
43147
|
]
|
|
@@ -42394,14 +43174,15 @@ var stripeTemplate = {
|
|
|
42394
43174
|
name: "OAuth (Stripe Connect)",
|
|
42395
43175
|
type: "oauth",
|
|
42396
43176
|
flow: "authorization_code",
|
|
42397
|
-
description: "Stripe Connect for marketplace platforms. Requires Connect setup in dashboard",
|
|
42398
|
-
requiredFields: ["clientId", "
|
|
42399
|
-
optionalFields: ["scope"],
|
|
43177
|
+
description: "Stripe Connect for marketplace platforms. Requires Connect setup in dashboard. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43178
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43179
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42400
43180
|
defaults: {
|
|
42401
43181
|
type: "oauth",
|
|
42402
43182
|
flow: "authorization_code",
|
|
42403
43183
|
authorizationUrl: "https://connect.stripe.com/oauth/authorize",
|
|
42404
|
-
tokenUrl: "https://connect.stripe.com/oauth/token"
|
|
43184
|
+
tokenUrl: "https://connect.stripe.com/oauth/token",
|
|
43185
|
+
usePKCE: true
|
|
42405
43186
|
},
|
|
42406
43187
|
scopes: ["read_write"]
|
|
42407
43188
|
}
|
|
@@ -42451,14 +43232,15 @@ var quickbooksTemplate = {
|
|
|
42451
43232
|
name: "OAuth (User Authorization)",
|
|
42452
43233
|
type: "oauth",
|
|
42453
43234
|
flow: "authorization_code",
|
|
42454
|
-
description: "Standard OAuth 2.0 flow for accessing QuickBooks on behalf of a user. Create an app at developer.intuit.com",
|
|
42455
|
-
requiredFields: ["clientId", "
|
|
42456
|
-
optionalFields: ["scope"],
|
|
43235
|
+
description: "Standard OAuth 2.0 flow for accessing QuickBooks on behalf of a user. Create an app at developer.intuit.com. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43236
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43237
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42457
43238
|
defaults: {
|
|
42458
43239
|
type: "oauth",
|
|
42459
43240
|
flow: "authorization_code",
|
|
42460
43241
|
authorizationUrl: "https://appcenter.intuit.com/connect/oauth2",
|
|
42461
|
-
tokenUrl: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
|
|
43242
|
+
tokenUrl: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
|
|
43243
|
+
usePKCE: true
|
|
42462
43244
|
},
|
|
42463
43245
|
scopes: ["com.intuit.quickbooks.accounting", "com.intuit.quickbooks.payment"]
|
|
42464
43246
|
}
|
|
@@ -42493,14 +43275,15 @@ var rampTemplate = {
|
|
|
42493
43275
|
name: "OAuth (User Authorization)",
|
|
42494
43276
|
type: "oauth",
|
|
42495
43277
|
flow: "authorization_code",
|
|
42496
|
-
description: "OAuth 2.0 authorization code flow for accessing Ramp on behalf of a user",
|
|
42497
|
-
requiredFields: ["clientId", "
|
|
42498
|
-
optionalFields: ["scope"],
|
|
43278
|
+
description: "OAuth 2.0 authorization code flow for accessing Ramp on behalf of a user. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43279
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43280
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42499
43281
|
defaults: {
|
|
42500
43282
|
type: "oauth",
|
|
42501
43283
|
flow: "authorization_code",
|
|
42502
43284
|
authorizationUrl: "https://app.ramp.com/v1/authorize",
|
|
42503
|
-
tokenUrl: "https://api.ramp.com/developer/v1/token"
|
|
43285
|
+
tokenUrl: "https://api.ramp.com/developer/v1/token",
|
|
43286
|
+
usePKCE: true
|
|
42504
43287
|
},
|
|
42505
43288
|
scopes: [
|
|
42506
43289
|
"transactions:read",
|
|
@@ -42557,9 +43340,9 @@ var dropboxTemplate = {
|
|
|
42557
43340
|
name: "OAuth (User Authorization)",
|
|
42558
43341
|
type: "oauth",
|
|
42559
43342
|
flow: "authorization_code",
|
|
42560
|
-
description: "OAuth app for user authorization. Create app at dropbox.com/developers/apps",
|
|
42561
|
-
requiredFields: ["clientId", "
|
|
42562
|
-
optionalFields: ["scope"],
|
|
43343
|
+
description: "OAuth app for user authorization. Create app at dropbox.com/developers/apps. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43344
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43345
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42563
43346
|
defaults: {
|
|
42564
43347
|
type: "oauth",
|
|
42565
43348
|
flow: "authorization_code",
|
|
@@ -42596,14 +43379,15 @@ var boxTemplate = {
|
|
|
42596
43379
|
name: "OAuth (User Authorization)",
|
|
42597
43380
|
type: "oauth",
|
|
42598
43381
|
flow: "authorization_code",
|
|
42599
|
-
description: "OAuth 2.0 for user authorization. Create app at developer.box.com/console",
|
|
42600
|
-
requiredFields: ["clientId", "
|
|
42601
|
-
optionalFields: ["scope"],
|
|
43382
|
+
description: "OAuth 2.0 for user authorization. Create app at developer.box.com/console. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43383
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43384
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42602
43385
|
defaults: {
|
|
42603
43386
|
type: "oauth",
|
|
42604
43387
|
flow: "authorization_code",
|
|
42605
43388
|
authorizationUrl: "https://account.box.com/api/oauth2/authorize",
|
|
42606
|
-
tokenUrl: "https://api.box.com/oauth2/token"
|
|
43389
|
+
tokenUrl: "https://api.box.com/oauth2/token",
|
|
43390
|
+
usePKCE: true
|
|
42607
43391
|
},
|
|
42608
43392
|
scopes: ["root_readwrite", "manage_users", "manage_groups", "manage_enterprise"],
|
|
42609
43393
|
scopeDescriptions: {
|
|
@@ -42681,13 +43465,15 @@ var mailchimpTemplate = {
|
|
|
42681
43465
|
name: "OAuth (User Authorization)",
|
|
42682
43466
|
type: "oauth",
|
|
42683
43467
|
flow: "authorization_code",
|
|
42684
|
-
description: "OAuth for multi-account access. Register app at mailchimp.com/developer",
|
|
42685
|
-
requiredFields: ["clientId", "
|
|
43468
|
+
description: "OAuth for multi-account access. Register app at mailchimp.com/developer. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43469
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43470
|
+
optionalFields: ["clientSecret"],
|
|
42686
43471
|
defaults: {
|
|
42687
43472
|
type: "oauth",
|
|
42688
43473
|
flow: "authorization_code",
|
|
42689
43474
|
authorizationUrl: "https://login.mailchimp.com/oauth2/authorize",
|
|
42690
|
-
tokenUrl: "https://login.mailchimp.com/oauth2/token"
|
|
43475
|
+
tokenUrl: "https://login.mailchimp.com/oauth2/token",
|
|
43476
|
+
usePKCE: true
|
|
42691
43477
|
}
|
|
42692
43478
|
}
|
|
42693
43479
|
]
|
|
@@ -42779,14 +43565,15 @@ var pagerdutyTemplate = {
|
|
|
42779
43565
|
name: "OAuth (App Authorization)",
|
|
42780
43566
|
type: "oauth",
|
|
42781
43567
|
flow: "authorization_code",
|
|
42782
|
-
description: "OAuth app for multi-account access. Register at developer.pagerduty.com",
|
|
42783
|
-
requiredFields: ["clientId", "
|
|
42784
|
-
optionalFields: ["scope"],
|
|
43568
|
+
description: "OAuth app for multi-account access. Register at developer.pagerduty.com. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43569
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43570
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42785
43571
|
defaults: {
|
|
42786
43572
|
type: "oauth",
|
|
42787
43573
|
flow: "authorization_code",
|
|
42788
43574
|
authorizationUrl: "https://app.pagerduty.com/oauth/authorize",
|
|
42789
|
-
tokenUrl: "https://app.pagerduty.com/oauth/token"
|
|
43575
|
+
tokenUrl: "https://app.pagerduty.com/oauth/token",
|
|
43576
|
+
usePKCE: true
|
|
42790
43577
|
},
|
|
42791
43578
|
scopes: ["read", "write"],
|
|
42792
43579
|
scopeDescriptions: {
|
|
@@ -42822,14 +43609,15 @@ var sentryTemplate = {
|
|
|
42822
43609
|
name: "OAuth (Integration)",
|
|
42823
43610
|
type: "oauth",
|
|
42824
43611
|
flow: "authorization_code",
|
|
42825
|
-
description: "OAuth integration. Create at Organization Settings > Integrations",
|
|
42826
|
-
requiredFields: ["clientId", "
|
|
42827
|
-
optionalFields: ["scope"],
|
|
43612
|
+
description: "OAuth integration. Create at Organization Settings > Integrations. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43613
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43614
|
+
optionalFields: ["clientSecret", "scope"],
|
|
42828
43615
|
defaults: {
|
|
42829
43616
|
type: "oauth",
|
|
42830
43617
|
flow: "authorization_code",
|
|
42831
43618
|
authorizationUrl: "https://sentry.io/oauth/authorize/",
|
|
42832
|
-
tokenUrl: "https://sentry.io/oauth/token/"
|
|
43619
|
+
tokenUrl: "https://sentry.io/oauth/token/",
|
|
43620
|
+
usePKCE: true
|
|
42833
43621
|
},
|
|
42834
43622
|
scopes: ["project:read", "project:write", "event:read", "org:read", "member:read"],
|
|
42835
43623
|
scopeDescriptions: {
|
|
@@ -43026,14 +43814,15 @@ var zendeskTemplate = {
|
|
|
43026
43814
|
name: "OAuth (User Authorization)",
|
|
43027
43815
|
type: "oauth",
|
|
43028
43816
|
flow: "authorization_code",
|
|
43029
|
-
description: "OAuth client for user authorization. Create at Admin > Channels > API > OAuth Clients",
|
|
43030
|
-
requiredFields: ["clientId", "
|
|
43031
|
-
optionalFields: ["scope"],
|
|
43817
|
+
description: "OAuth client for user authorization. Create at Admin > Channels > API > OAuth Clients. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43818
|
+
requiredFields: ["clientId", "redirectUri", "subdomain"],
|
|
43819
|
+
optionalFields: ["clientSecret", "scope"],
|
|
43032
43820
|
defaults: {
|
|
43033
43821
|
type: "oauth",
|
|
43034
43822
|
flow: "authorization_code",
|
|
43035
43823
|
authorizationUrl: "https://{subdomain}.zendesk.com/oauth/authorizations/new",
|
|
43036
|
-
tokenUrl: "https://{subdomain}.zendesk.com/oauth/tokens"
|
|
43824
|
+
tokenUrl: "https://{subdomain}.zendesk.com/oauth/tokens",
|
|
43825
|
+
usePKCE: true
|
|
43037
43826
|
},
|
|
43038
43827
|
scopes: ["read", "write", "tickets:read", "tickets:write"],
|
|
43039
43828
|
scopeDescriptions: {
|
|
@@ -43071,13 +43860,15 @@ var intercomTemplate = {
|
|
|
43071
43860
|
name: "OAuth (App Installation)",
|
|
43072
43861
|
type: "oauth",
|
|
43073
43862
|
flow: "authorization_code",
|
|
43074
|
-
description: "OAuth for Intercom app marketplace distribution",
|
|
43075
|
-
requiredFields: ["clientId", "
|
|
43863
|
+
description: "OAuth for Intercom app marketplace distribution. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43864
|
+
requiredFields: ["clientId", "redirectUri"],
|
|
43865
|
+
optionalFields: ["clientSecret"],
|
|
43076
43866
|
defaults: {
|
|
43077
43867
|
type: "oauth",
|
|
43078
43868
|
flow: "authorization_code",
|
|
43079
43869
|
authorizationUrl: "https://app.intercom.com/oauth",
|
|
43080
|
-
tokenUrl: "https://api.intercom.io/auth/eagle/token"
|
|
43870
|
+
tokenUrl: "https://api.intercom.io/auth/eagle/token",
|
|
43871
|
+
usePKCE: true
|
|
43081
43872
|
}
|
|
43082
43873
|
}
|
|
43083
43874
|
]
|
|
@@ -43110,14 +43901,15 @@ var shopifyTemplate = {
|
|
|
43110
43901
|
name: "OAuth (Public/Custom App)",
|
|
43111
43902
|
type: "oauth",
|
|
43112
43903
|
flow: "authorization_code",
|
|
43113
|
-
description: "OAuth for public apps or per-store custom apps. Create at partners.shopify.com",
|
|
43114
|
-
requiredFields: ["clientId", "
|
|
43115
|
-
optionalFields: ["scope"],
|
|
43904
|
+
description: "OAuth for public apps or per-store custom apps. Create at partners.shopify.com. Provide clientSecret for web apps; omit for native/desktop apps (secured via PKCE).",
|
|
43905
|
+
requiredFields: ["clientId", "redirectUri", "subdomain"],
|
|
43906
|
+
optionalFields: ["clientSecret", "scope"],
|
|
43116
43907
|
defaults: {
|
|
43117
43908
|
type: "oauth",
|
|
43118
43909
|
flow: "authorization_code",
|
|
43119
43910
|
authorizationUrl: "https://{subdomain}.myshopify.com/admin/oauth/authorize",
|
|
43120
|
-
tokenUrl: "https://{subdomain}.myshopify.com/admin/oauth/access_token"
|
|
43911
|
+
tokenUrl: "https://{subdomain}.myshopify.com/admin/oauth/access_token",
|
|
43912
|
+
usePKCE: true
|
|
43121
43913
|
},
|
|
43122
43914
|
scopes: ["read_products", "write_products", "read_orders", "write_orders", "read_customers", "write_customers", "read_inventory", "write_inventory", "read_fulfillments", "write_fulfillments"],
|
|
43123
43915
|
scopeDescriptions: {
|
|
@@ -43145,6 +43937,7 @@ var allVendorTemplates = [
|
|
|
43145
43937
|
slackTemplate,
|
|
43146
43938
|
discordTemplate,
|
|
43147
43939
|
telegramTemplate,
|
|
43940
|
+
twitterTemplate,
|
|
43148
43941
|
// Development
|
|
43149
43942
|
githubTemplate,
|
|
43150
43943
|
gitlabTemplate,
|
|
@@ -43204,6 +43997,7 @@ var VENDOR_ICON_MAP = {
|
|
|
43204
43997
|
discord: "discord",
|
|
43205
43998
|
slack: "slack",
|
|
43206
43999
|
telegram: "telegram",
|
|
44000
|
+
twitter: "x",
|
|
43207
44001
|
"microsoft-teams": "microsoftteams",
|
|
43208
44002
|
// CRM
|
|
43209
44003
|
salesforce: "salesforce",
|
|
@@ -43268,6 +44062,7 @@ var FALLBACK_PLACEHOLDERS = {
|
|
|
43268
44062
|
// Communication (trademark removed)
|
|
43269
44063
|
slack: { color: "#4A154B", letter: "S" },
|
|
43270
44064
|
"microsoft-teams": { color: "#6264A7", letter: "T" },
|
|
44065
|
+
twitter: { color: "#000000", letter: "X" },
|
|
43271
44066
|
// CRM (trademark removed)
|
|
43272
44067
|
salesforce: { color: "#00A1E0", letter: "S" },
|
|
43273
44068
|
pipedrive: { color: "#1A1F26", letter: "P" },
|
|
@@ -46437,21 +47232,53 @@ registerWebTools();
|
|
|
46437
47232
|
init_Connector();
|
|
46438
47233
|
var DEFAULT_TIMEOUT = 1e4;
|
|
46439
47234
|
var DEFAULT_MAX_TIMEOUT = 3e4;
|
|
46440
|
-
function formatConnectorEntry(c) {
|
|
47235
|
+
function formatConnectorEntry(c, accountId) {
|
|
46441
47236
|
const parts = [];
|
|
46442
47237
|
const serviceOrVendor = c.serviceType ?? c.vendor ?? void 0;
|
|
46443
47238
|
if (serviceOrVendor) parts.push(`Service: ${serviceOrVendor}`);
|
|
47239
|
+
if (accountId) parts.push(`Account: "${accountId}"`);
|
|
46444
47240
|
if (c.config.description) parts.push(c.config.description);
|
|
46445
47241
|
if (c.baseURL) parts.push(`URL: ${c.baseURL}`);
|
|
47242
|
+
const label = accountId ? `"${c.name}" account "${accountId}"` : `"${c.name}"`;
|
|
46446
47243
|
const details = parts.map((p) => ` ${p}`).join("\n");
|
|
46447
|
-
return ` \u2022
|
|
47244
|
+
return ` \u2022 ${label} (${c.displayName})
|
|
46448
47245
|
${details}`;
|
|
46449
47246
|
}
|
|
46450
|
-
function
|
|
47247
|
+
function buildIdentityList(context) {
|
|
47248
|
+
const identities = context?.identities;
|
|
46451
47249
|
const registry = context?.connectorRegistry ?? Connector.asRegistry();
|
|
47250
|
+
if (identities?.length) {
|
|
47251
|
+
const entries = [];
|
|
47252
|
+
for (const id of identities) {
|
|
47253
|
+
try {
|
|
47254
|
+
const connector = registry.get(id.connector);
|
|
47255
|
+
entries.push(formatConnectorEntry(connector, id.accountId));
|
|
47256
|
+
} catch {
|
|
47257
|
+
entries.push(` \u2022 "${id.connector}"${id.accountId ? ` account "${id.accountId}"` : ""} \u2014 not available`);
|
|
47258
|
+
}
|
|
47259
|
+
}
|
|
47260
|
+
return entries.length > 0 ? entries.join("\n\n") : " No connectors registered.";
|
|
47261
|
+
}
|
|
46452
47262
|
const connectors = registry.listAll();
|
|
46453
|
-
|
|
47263
|
+
return connectors.length > 0 ? connectors.map((c) => formatConnectorEntry(c)).join("\n\n") : " No connectors registered.";
|
|
47264
|
+
}
|
|
47265
|
+
function hasAccountIds(context) {
|
|
47266
|
+
return !!context?.identities?.some((id) => id.accountId);
|
|
47267
|
+
}
|
|
47268
|
+
function generateDescription(context, maxTimeout) {
|
|
47269
|
+
const connectorList = buildIdentityList(context);
|
|
47270
|
+
const showAccountId = hasAccountIds(context);
|
|
46454
47271
|
const timeoutSec = Math.round(maxTimeout / 1e3);
|
|
47272
|
+
const accountIdParam = showAccountId ? `
|
|
47273
|
+
\u2022 accountId (optional): Account alias for multi-account connectors.
|
|
47274
|
+
Required when a connector has multiple accounts (see list below).
|
|
47275
|
+
Example: authenticatedFetch('/v1.0/me', {}, 'microsoft', 'work')` : "";
|
|
47276
|
+
const accountIdExamples = showAccountId ? `
|
|
47277
|
+
// Multi-account: specify accountId for connectors with multiple accounts
|
|
47278
|
+
const resp = await authenticatedFetch('/v1.0/me', { method: 'GET' }, 'microsoft', 'work');
|
|
47279
|
+
const profile = await resp.json();
|
|
47280
|
+
output = profile;
|
|
47281
|
+
` : "";
|
|
46455
47282
|
return `Execute JavaScript code in a secure sandbox with authenticated API access to external services.
|
|
46456
47283
|
|
|
46457
47284
|
Use this tool when you need to:
|
|
@@ -46462,7 +47289,7 @@ Use this tool when you need to:
|
|
|
46462
47289
|
|
|
46463
47290
|
SANDBOX API:
|
|
46464
47291
|
|
|
46465
|
-
1. authenticatedFetch(url, options, connectorName)
|
|
47292
|
+
1. authenticatedFetch(url, options, connectorName${showAccountId ? ", accountId?" : ""})
|
|
46466
47293
|
Makes authenticated HTTP requests using the connector's credentials.
|
|
46467
47294
|
The current user's identity (userId) is automatically included \u2014 no need to pass it.
|
|
46468
47295
|
Auth headers are added automatically \u2014 DO NOT set Authorization header manually.
|
|
@@ -46473,7 +47300,7 @@ SANDBOX API:
|
|
|
46473
47300
|
- Relative: "/user/repos" (resolved against connector's base URL)
|
|
46474
47301
|
\u2022 options: Standard fetch options { method, headers, body }
|
|
46475
47302
|
- For POST/PUT: set body to JSON.stringify(data) and headers to { 'Content-Type': 'application/json' }
|
|
46476
|
-
\u2022 connectorName: Name of a registered connector (see list below)
|
|
47303
|
+
\u2022 connectorName: Name of a registered connector (see list below)${accountIdParam}
|
|
46477
47304
|
|
|
46478
47305
|
Returns: Promise<Response>
|
|
46479
47306
|
\u2022 response.ok \u2014 true if status 200-299
|
|
@@ -46509,7 +47336,7 @@ const resp = await authenticatedFetch('/chat.postMessage', {
|
|
|
46509
47336
|
body: JSON.stringify({ channel: '#general', text: 'Hello!' })
|
|
46510
47337
|
}, 'slack');
|
|
46511
47338
|
output = await resp.json();
|
|
46512
|
-
|
|
47339
|
+
${accountIdExamples}
|
|
46513
47340
|
// Data processing (no API needed)
|
|
46514
47341
|
const items = input.data;
|
|
46515
47342
|
output = items.filter(i => i.score > 0.8).sort((a, b) => b.score - a.score);
|
|
@@ -46597,9 +47424,10 @@ async function executeInVM(code, input, timeout, logs, userId, registry) {
|
|
|
46597
47424
|
},
|
|
46598
47425
|
// Authenticated fetch — userId auto-injected from ToolContext.
|
|
46599
47426
|
// Only connectors visible in the scoped registry are accessible.
|
|
46600
|
-
|
|
47427
|
+
// Optional 4th param accountId for multi-account OAuth identities.
|
|
47428
|
+
authenticatedFetch: (url2, options, connectorName, accountId) => {
|
|
46601
47429
|
registry.get(connectorName);
|
|
46602
|
-
return authenticatedFetch(url2, options, connectorName, userId);
|
|
47430
|
+
return authenticatedFetch(url2, options, connectorName, userId, accountId);
|
|
46603
47431
|
},
|
|
46604
47432
|
// Standard fetch (no auth)
|
|
46605
47433
|
fetch: globalThis.fetch,
|
|
@@ -47287,7 +48115,8 @@ async function githubFetch(connector, endpoint, options) {
|
|
|
47287
48115
|
headers,
|
|
47288
48116
|
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
47289
48117
|
},
|
|
47290
|
-
options?.userId
|
|
48118
|
+
options?.userId,
|
|
48119
|
+
options?.accountId
|
|
47291
48120
|
);
|
|
47292
48121
|
const text = await response.text();
|
|
47293
48122
|
let data;
|
|
@@ -47369,6 +48198,7 @@ EXAMPLES:
|
|
|
47369
48198
|
},
|
|
47370
48199
|
execute: async (args, context) => {
|
|
47371
48200
|
const effectiveUserId = context?.userId ?? userId;
|
|
48201
|
+
const effectiveAccountId = context?.accountId;
|
|
47372
48202
|
const resolved = resolveRepository(args.repository, connector);
|
|
47373
48203
|
if (!resolved.success) {
|
|
47374
48204
|
return { success: false, error: resolved.error };
|
|
@@ -47380,7 +48210,7 @@ EXAMPLES:
|
|
|
47380
48210
|
const repoInfo = await githubFetch(
|
|
47381
48211
|
connector,
|
|
47382
48212
|
`/repos/${owner}/${repo}`,
|
|
47383
|
-
{ userId: effectiveUserId }
|
|
48213
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
47384
48214
|
);
|
|
47385
48215
|
ref = repoInfo.default_branch;
|
|
47386
48216
|
}
|
|
@@ -47480,6 +48310,7 @@ EXAMPLES:
|
|
|
47480
48310
|
},
|
|
47481
48311
|
execute: async (args, context) => {
|
|
47482
48312
|
const effectiveUserId = context?.userId ?? userId;
|
|
48313
|
+
const effectiveAccountId = context?.accountId;
|
|
47483
48314
|
const resolved = resolveRepository(args.repository, connector);
|
|
47484
48315
|
if (!resolved.success) {
|
|
47485
48316
|
return { success: false, error: resolved.error };
|
|
@@ -47497,6 +48328,7 @@ EXAMPLES:
|
|
|
47497
48328
|
`/search/code`,
|
|
47498
48329
|
{
|
|
47499
48330
|
userId: effectiveUserId,
|
|
48331
|
+
accountId: effectiveAccountId,
|
|
47500
48332
|
// Request text-match fragments
|
|
47501
48333
|
accept: "application/vnd.github.text-match+json",
|
|
47502
48334
|
queryParams: { q, per_page: perPage }
|
|
@@ -47585,6 +48417,7 @@ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (
|
|
|
47585
48417
|
},
|
|
47586
48418
|
execute: async (args, context) => {
|
|
47587
48419
|
const effectiveUserId = context?.userId ?? userId;
|
|
48420
|
+
const effectiveAccountId = context?.accountId;
|
|
47588
48421
|
const resolved = resolveRepository(args.repository, connector);
|
|
47589
48422
|
if (!resolved.success) {
|
|
47590
48423
|
return { success: false, error: resolved.error };
|
|
@@ -47598,7 +48431,7 @@ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (
|
|
|
47598
48431
|
const contentResp = await githubFetch(
|
|
47599
48432
|
connector,
|
|
47600
48433
|
`/repos/${owner}/${repo}/contents/${args.path}${refParam}`,
|
|
47601
|
-
{ userId: effectiveUserId }
|
|
48434
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
47602
48435
|
);
|
|
47603
48436
|
if (contentResp.type !== "file") {
|
|
47604
48437
|
return {
|
|
@@ -47615,7 +48448,7 @@ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (
|
|
|
47615
48448
|
const blob = await githubFetch(
|
|
47616
48449
|
connector,
|
|
47617
48450
|
contentResp.git_url,
|
|
47618
|
-
{ userId: effectiveUserId }
|
|
48451
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
47619
48452
|
);
|
|
47620
48453
|
fileContent = Buffer.from(blob.content, "base64").toString("utf-8");
|
|
47621
48454
|
fileSize = blob.size;
|
|
@@ -47704,6 +48537,7 @@ EXAMPLES:
|
|
|
47704
48537
|
},
|
|
47705
48538
|
execute: async (args, context) => {
|
|
47706
48539
|
const effectiveUserId = context?.userId ?? userId;
|
|
48540
|
+
const effectiveAccountId = context?.accountId;
|
|
47707
48541
|
const resolved = resolveRepository(args.repository, connector);
|
|
47708
48542
|
if (!resolved.success) {
|
|
47709
48543
|
return { success: false, error: resolved.error };
|
|
@@ -47713,7 +48547,7 @@ EXAMPLES:
|
|
|
47713
48547
|
const pr = await githubFetch(
|
|
47714
48548
|
connector,
|
|
47715
48549
|
`/repos/${owner}/${repo}/pulls/${args.pull_number}`,
|
|
47716
|
-
{ userId: effectiveUserId }
|
|
48550
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
47717
48551
|
);
|
|
47718
48552
|
return {
|
|
47719
48553
|
success: true,
|
|
@@ -47791,6 +48625,7 @@ NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent f
|
|
|
47791
48625
|
},
|
|
47792
48626
|
execute: async (args, context) => {
|
|
47793
48627
|
const effectiveUserId = context?.userId ?? userId;
|
|
48628
|
+
const effectiveAccountId = context?.accountId;
|
|
47794
48629
|
const resolved = resolveRepository(args.repository, connector);
|
|
47795
48630
|
if (!resolved.success) {
|
|
47796
48631
|
return { success: false, error: resolved.error };
|
|
@@ -47802,6 +48637,7 @@ NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent f
|
|
|
47802
48637
|
`/repos/${owner}/${repo}/pulls/${args.pull_number}/files`,
|
|
47803
48638
|
{
|
|
47804
48639
|
userId: effectiveUserId,
|
|
48640
|
+
accountId: effectiveAccountId,
|
|
47805
48641
|
queryParams: { per_page: 100 }
|
|
47806
48642
|
}
|
|
47807
48643
|
);
|
|
@@ -47874,6 +48710,7 @@ EXAMPLES:
|
|
|
47874
48710
|
},
|
|
47875
48711
|
execute: async (args, context) => {
|
|
47876
48712
|
const effectiveUserId = context?.userId ?? userId;
|
|
48713
|
+
const effectiveAccountId = context?.accountId;
|
|
47877
48714
|
const resolved = resolveRepository(args.repository, connector);
|
|
47878
48715
|
if (!resolved.success) {
|
|
47879
48716
|
return { success: false, error: resolved.error };
|
|
@@ -47881,7 +48718,7 @@ EXAMPLES:
|
|
|
47881
48718
|
const { owner, repo } = resolved.repo;
|
|
47882
48719
|
try {
|
|
47883
48720
|
const basePath = `/repos/${owner}/${repo}`;
|
|
47884
|
-
const queryOpts = { userId: effectiveUserId, queryParams: { per_page: 100 } };
|
|
48721
|
+
const queryOpts = { userId: effectiveUserId, accountId: effectiveAccountId, queryParams: { per_page: 100 } };
|
|
47885
48722
|
const [reviewComments, reviews, issueComments] = await Promise.all([
|
|
47886
48723
|
githubFetch(
|
|
47887
48724
|
connector,
|
|
@@ -48010,6 +48847,7 @@ EXAMPLES:
|
|
|
48010
48847
|
},
|
|
48011
48848
|
execute: async (args, context) => {
|
|
48012
48849
|
const effectiveUserId = context?.userId ?? userId;
|
|
48850
|
+
const effectiveAccountId = context?.accountId;
|
|
48013
48851
|
const resolved = resolveRepository(args.repository, connector);
|
|
48014
48852
|
if (!resolved.success) {
|
|
48015
48853
|
return { success: false, error: resolved.error };
|
|
@@ -48022,6 +48860,7 @@ EXAMPLES:
|
|
|
48022
48860
|
{
|
|
48023
48861
|
method: "POST",
|
|
48024
48862
|
userId: effectiveUserId,
|
|
48863
|
+
accountId: effectiveAccountId,
|
|
48025
48864
|
body: {
|
|
48026
48865
|
title: args.title,
|
|
48027
48866
|
body: args.body,
|
|
@@ -48113,7 +48952,8 @@ async function microsoftFetch(connector, endpoint, options) {
|
|
|
48113
48952
|
headers,
|
|
48114
48953
|
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
48115
48954
|
},
|
|
48116
|
-
options?.userId
|
|
48955
|
+
options?.userId,
|
|
48956
|
+
options?.accountId
|
|
48117
48957
|
);
|
|
48118
48958
|
const text = await response.text();
|
|
48119
48959
|
if (!response.ok) {
|
|
@@ -48166,7 +49006,7 @@ function isTeamsMeetingUrl(input) {
|
|
|
48166
49006
|
return false;
|
|
48167
49007
|
}
|
|
48168
49008
|
}
|
|
48169
|
-
async function resolveMeetingId(connector, input, prefix, effectiveUserId) {
|
|
49009
|
+
async function resolveMeetingId(connector, input, prefix, effectiveUserId, effectiveAccountId) {
|
|
48170
49010
|
if (!input || input.trim().length === 0) {
|
|
48171
49011
|
throw new Error("Meeting ID cannot be empty");
|
|
48172
49012
|
}
|
|
@@ -48179,6 +49019,7 @@ async function resolveMeetingId(connector, input, prefix, effectiveUserId) {
|
|
|
48179
49019
|
`${prefix}/onlineMeetings`,
|
|
48180
49020
|
{
|
|
48181
49021
|
userId: effectiveUserId,
|
|
49022
|
+
accountId: effectiveAccountId,
|
|
48182
49023
|
queryParams: { "$filter": `JoinWebUrl eq '${trimmed}'` }
|
|
48183
49024
|
}
|
|
48184
49025
|
);
|
|
@@ -48257,13 +49098,14 @@ EXAMPLES:
|
|
|
48257
49098
|
},
|
|
48258
49099
|
execute: async (args, context) => {
|
|
48259
49100
|
const effectiveUserId = context?.userId ?? userId;
|
|
49101
|
+
const effectiveAccountId = context?.accountId;
|
|
48260
49102
|
try {
|
|
48261
49103
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48262
49104
|
if (args.replyToMessageId) {
|
|
48263
49105
|
const replyDraft = await microsoftFetch(
|
|
48264
49106
|
connector,
|
|
48265
49107
|
`${prefix}/messages/${args.replyToMessageId}/createReply`,
|
|
48266
|
-
{ method: "POST", userId: effectiveUserId, body: {} }
|
|
49108
|
+
{ method: "POST", userId: effectiveUserId, accountId: effectiveAccountId, body: {} }
|
|
48267
49109
|
);
|
|
48268
49110
|
const updated = await microsoftFetch(
|
|
48269
49111
|
connector,
|
|
@@ -48271,6 +49113,7 @@ EXAMPLES:
|
|
|
48271
49113
|
{
|
|
48272
49114
|
method: "PATCH",
|
|
48273
49115
|
userId: effectiveUserId,
|
|
49116
|
+
accountId: effectiveAccountId,
|
|
48274
49117
|
body: {
|
|
48275
49118
|
subject: args.subject,
|
|
48276
49119
|
body: { contentType: "HTML", content: args.body },
|
|
@@ -48291,6 +49134,7 @@ EXAMPLES:
|
|
|
48291
49134
|
{
|
|
48292
49135
|
method: "POST",
|
|
48293
49136
|
userId: effectiveUserId,
|
|
49137
|
+
accountId: effectiveAccountId,
|
|
48294
49138
|
body: {
|
|
48295
49139
|
isDraft: true,
|
|
48296
49140
|
subject: args.subject,
|
|
@@ -48379,6 +49223,7 @@ EXAMPLES:
|
|
|
48379
49223
|
},
|
|
48380
49224
|
execute: async (args, context) => {
|
|
48381
49225
|
const effectiveUserId = context?.userId ?? userId;
|
|
49226
|
+
const effectiveAccountId = context?.accountId;
|
|
48382
49227
|
try {
|
|
48383
49228
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48384
49229
|
if (args.replyToMessageId) {
|
|
@@ -48388,6 +49233,7 @@ EXAMPLES:
|
|
|
48388
49233
|
{
|
|
48389
49234
|
method: "POST",
|
|
48390
49235
|
userId: effectiveUserId,
|
|
49236
|
+
accountId: effectiveAccountId,
|
|
48391
49237
|
body: {
|
|
48392
49238
|
message: {
|
|
48393
49239
|
toRecipients: formatRecipients(args.to),
|
|
@@ -48404,6 +49250,7 @@ EXAMPLES:
|
|
|
48404
49250
|
{
|
|
48405
49251
|
method: "POST",
|
|
48406
49252
|
userId: effectiveUserId,
|
|
49253
|
+
accountId: effectiveAccountId,
|
|
48407
49254
|
body: {
|
|
48408
49255
|
message: {
|
|
48409
49256
|
subject: args.subject,
|
|
@@ -48503,6 +49350,7 @@ EXAMPLES:
|
|
|
48503
49350
|
},
|
|
48504
49351
|
execute: async (args, context) => {
|
|
48505
49352
|
const effectiveUserId = context?.userId ?? userId;
|
|
49353
|
+
const effectiveAccountId = context?.accountId;
|
|
48506
49354
|
try {
|
|
48507
49355
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48508
49356
|
const tz = args.timeZone ?? "UTC";
|
|
@@ -48525,7 +49373,7 @@ EXAMPLES:
|
|
|
48525
49373
|
const event = await microsoftFetch(
|
|
48526
49374
|
connector,
|
|
48527
49375
|
`${prefix}/events`,
|
|
48528
|
-
{ method: "POST", userId: effectiveUserId, body: eventBody }
|
|
49376
|
+
{ method: "POST", userId: effectiveUserId, accountId: effectiveAccountId, body: eventBody }
|
|
48529
49377
|
);
|
|
48530
49378
|
return {
|
|
48531
49379
|
success: true,
|
|
@@ -48629,6 +49477,7 @@ EXAMPLES:
|
|
|
48629
49477
|
},
|
|
48630
49478
|
execute: async (args, context) => {
|
|
48631
49479
|
const effectiveUserId = context?.userId ?? userId;
|
|
49480
|
+
const effectiveAccountId = context?.accountId;
|
|
48632
49481
|
try {
|
|
48633
49482
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48634
49483
|
const tz = args.timeZone ?? "UTC";
|
|
@@ -48652,7 +49501,7 @@ EXAMPLES:
|
|
|
48652
49501
|
const event = await microsoftFetch(
|
|
48653
49502
|
connector,
|
|
48654
49503
|
`${prefix}/events/${args.eventId}`,
|
|
48655
|
-
{ method: "PATCH", userId: effectiveUserId, body: patchBody }
|
|
49504
|
+
{ method: "PATCH", userId: effectiveUserId, accountId: effectiveAccountId, body: patchBody }
|
|
48656
49505
|
);
|
|
48657
49506
|
return {
|
|
48658
49507
|
success: true,
|
|
@@ -48725,14 +49574,15 @@ EXAMPLES:
|
|
|
48725
49574
|
},
|
|
48726
49575
|
execute: async (args, context) => {
|
|
48727
49576
|
const effectiveUserId = context?.userId ?? userId;
|
|
49577
|
+
const effectiveAccountId = context?.accountId;
|
|
48728
49578
|
try {
|
|
48729
49579
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48730
|
-
const resolved = await resolveMeetingId(connector, args.meetingId, prefix, effectiveUserId);
|
|
49580
|
+
const resolved = await resolveMeetingId(connector, args.meetingId, prefix, effectiveUserId, effectiveAccountId);
|
|
48731
49581
|
const meetingId = resolved.meetingId;
|
|
48732
49582
|
const transcriptList = await microsoftFetch(
|
|
48733
49583
|
connector,
|
|
48734
49584
|
`${prefix}/onlineMeetings/${meetingId}/transcripts`,
|
|
48735
|
-
{ userId: effectiveUserId }
|
|
49585
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
48736
49586
|
);
|
|
48737
49587
|
if (!transcriptList.value || transcriptList.value.length === 0) {
|
|
48738
49588
|
return {
|
|
@@ -48745,7 +49595,8 @@ EXAMPLES:
|
|
|
48745
49595
|
const response = await connector.fetch(
|
|
48746
49596
|
contentUrl + "?$format=text/vtt",
|
|
48747
49597
|
{ method: "GET", headers: { "Accept": "text/vtt" } },
|
|
48748
|
-
effectiveUserId
|
|
49598
|
+
effectiveUserId,
|
|
49599
|
+
effectiveAccountId
|
|
48749
49600
|
);
|
|
48750
49601
|
if (!response.ok) {
|
|
48751
49602
|
const errorText = await response.text();
|
|
@@ -48837,6 +49688,7 @@ EXAMPLES:
|
|
|
48837
49688
|
},
|
|
48838
49689
|
execute: async (args, context) => {
|
|
48839
49690
|
const effectiveUserId = context?.userId ?? userId;
|
|
49691
|
+
const effectiveAccountId = context?.accountId;
|
|
48840
49692
|
try {
|
|
48841
49693
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48842
49694
|
const tz = args.timeZone ?? "UTC";
|
|
@@ -48846,6 +49698,7 @@ EXAMPLES:
|
|
|
48846
49698
|
{
|
|
48847
49699
|
method: "POST",
|
|
48848
49700
|
userId: effectiveUserId,
|
|
49701
|
+
accountId: effectiveAccountId,
|
|
48849
49702
|
body: {
|
|
48850
49703
|
attendees: formatAttendees(args.attendees),
|
|
48851
49704
|
timeConstraint: {
|
|
@@ -49774,27 +50627,42 @@ var customToolDelete = createCustomToolDelete();
|
|
|
49774
50627
|
|
|
49775
50628
|
// src/tools/custom-tools/sandboxDescription.ts
|
|
49776
50629
|
init_Connector();
|
|
49777
|
-
function formatConnectorEntry2(c) {
|
|
50630
|
+
function formatConnectorEntry2(c, accountId) {
|
|
49778
50631
|
const parts = [];
|
|
49779
50632
|
const serviceOrVendor = c.serviceType ?? c.vendor ?? void 0;
|
|
49780
50633
|
if (serviceOrVendor) parts.push(`Service: ${serviceOrVendor}`);
|
|
50634
|
+
if (accountId) parts.push(`Account: "${accountId}"`);
|
|
49781
50635
|
if (c.config.description) parts.push(c.config.description);
|
|
49782
50636
|
if (c.baseURL) parts.push(`URL: ${c.baseURL}`);
|
|
50637
|
+
const label = accountId ? `"${c.name}" account "${accountId}"` : `"${c.name}"`;
|
|
49783
50638
|
const details = parts.map((p) => ` ${p}`).join("\n");
|
|
49784
|
-
return ` \u2022
|
|
50639
|
+
return ` \u2022 ${label} (${c.displayName})
|
|
49785
50640
|
${details}`;
|
|
49786
50641
|
}
|
|
49787
50642
|
function buildConnectorList(context) {
|
|
50643
|
+
const identities = context?.identities;
|
|
49788
50644
|
const registry = context?.connectorRegistry ?? Connector.asRegistry();
|
|
50645
|
+
if (identities?.length) {
|
|
50646
|
+
const entries = [];
|
|
50647
|
+
for (const id of identities) {
|
|
50648
|
+
try {
|
|
50649
|
+
const connector = registry.get(id.connector);
|
|
50650
|
+
entries.push(formatConnectorEntry2(connector, id.accountId));
|
|
50651
|
+
} catch {
|
|
50652
|
+
entries.push(` \u2022 "${id.connector}"${id.accountId ? ` account "${id.accountId}"` : ""} \u2014 not available`);
|
|
50653
|
+
}
|
|
50654
|
+
}
|
|
50655
|
+
return entries.length > 0 ? entries.join("\n\n") : " No connectors registered.";
|
|
50656
|
+
}
|
|
49789
50657
|
const connectors = registry.listAll();
|
|
49790
50658
|
if (connectors.length === 0) {
|
|
49791
50659
|
return " No connectors registered.";
|
|
49792
50660
|
}
|
|
49793
|
-
return connectors.map(formatConnectorEntry2).join("\n\n");
|
|
50661
|
+
return connectors.map((c) => formatConnectorEntry2(c)).join("\n\n");
|
|
49794
50662
|
}
|
|
49795
50663
|
var SANDBOX_API_REFERENCE = `SANDBOX API (available inside custom tool code):
|
|
49796
50664
|
|
|
49797
|
-
1. authenticatedFetch(url, options, connectorName)
|
|
50665
|
+
1. authenticatedFetch(url, options, connectorName, accountId?)
|
|
49798
50666
|
Makes authenticated HTTP requests using the connector's credentials.
|
|
49799
50667
|
Auth headers are added automatically \u2014 DO NOT set Authorization header manually.
|
|
49800
50668
|
|
|
@@ -49805,6 +50673,7 @@ var SANDBOX_API_REFERENCE = `SANDBOX API (available inside custom tool code):
|
|
|
49805
50673
|
\u2022 options: Standard fetch options { method, headers, body }
|
|
49806
50674
|
- For POST/PUT: set body to JSON.stringify(data) and headers to { 'Content-Type': 'application/json' }
|
|
49807
50675
|
\u2022 connectorName: Name of a registered connector (see REGISTERED CONNECTORS below)
|
|
50676
|
+
\u2022 accountId (optional): Account alias for multi-account connectors (e.g., 'work', 'personal')
|
|
49808
50677
|
|
|
49809
50678
|
Returns: Promise<Response>
|
|
49810
50679
|
\u2022 response.ok \u2014 true if status 200-299
|
|
@@ -50888,6 +51757,6 @@ REMEMBER: Keep it conversational, ask one question at a time, and only output th
|
|
|
50888
51757
|
}
|
|
50889
51758
|
};
|
|
50890
51759
|
|
|
50891
|
-
export { AGENT_DEFINITION_FORMAT_VERSION, AIError, APPROVAL_STATE_VERSION, Agent, AgentContextNextGen, ApproximateTokenEstimator, BaseMediaProvider, BasePluginNextGen, BaseProvider, BaseTextProvider, BraveProvider, CONNECTOR_CONFIG_VERSION, CONTEXT_SESSION_FORMAT_VERSION, CUSTOM_TOOL_DEFINITION_VERSION, CheckpointManager, CircuitBreaker, CircuitOpenError, Connector, ConnectorConfigStore, ConnectorTools, ConsoleMetrics, ContentType, ContextOverflowError, DEFAULT_ALLOWLIST, DEFAULT_BACKOFF_CONFIG, DEFAULT_BASE_DELAY_MS, DEFAULT_CHECKPOINT_STRATEGY, DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_CONFIG2 as DEFAULT_CONFIG, DEFAULT_CONNECTOR_TIMEOUT, DEFAULT_CONTEXT_CONFIG, DEFAULT_DESKTOP_CONFIG, DEFAULT_FEATURES, DEFAULT_FILESYSTEM_CONFIG, DEFAULT_HISTORY_MANAGER_CONFIG, DEFAULT_MAX_DELAY_MS, DEFAULT_MAX_RETRIES, DEFAULT_MEMORY_CONFIG, DEFAULT_PERMISSION_CONFIG, DEFAULT_RATE_LIMITER_CONFIG, DEFAULT_RETRYABLE_STATUSES, DEFAULT_SHELL_CONFIG, DESKTOP_TOOL_NAMES, DefaultCompactionStrategy, DependencyCycleError, DocumentReader, ErrorHandler, ExecutionContext, ExternalDependencyHandler, FileAgentDefinitionStorage, FileConnectorStorage, FileContextStorage, FileCustomToolStorage, FileMediaStorage as FileMediaOutputHandler, FileMediaStorage, FilePersistentInstructionsStorage, FileRoutineDefinitionStorage, FileStorage, FileUserInfoStorage, FormatDetector, FrameworkLogger, HookManager, IMAGE_MODELS, IMAGE_MODEL_REGISTRY, ImageGeneration, InContextMemoryPluginNextGen, InMemoryAgentStateStorage, InMemoryHistoryStorage, InMemoryMetrics, InMemoryPlanStorage, InMemoryStorage, InvalidConfigError, InvalidToolArgumentsError, LLM_MODELS, LoggingPlugin, MCPClient, MCPConnectionError, MCPError, MCPProtocolError, MCPRegistry, MCPResourceError, MCPTimeoutError, MCPToolError, MEMORY_PRIORITY_VALUES, MODEL_REGISTRY, MemoryConnectorStorage, MemoryEvictionCompactor, MemoryStorage, MessageBuilder, MessageRole, ModelNotSupportedError, NoOpMetrics, NutTreeDriver, OAuthManager, ParallelTasksError, PersistentInstructionsPluginNextGen, PlanningAgent, ProviderAuthError, ProviderConfigAgent, ProviderContextLengthError, ProviderError, ProviderErrorMapper, ProviderNotFoundError, ProviderRateLimitError, RapidAPIProvider, RateLimitError, SERVICE_DEFINITIONS, SERVICE_INFO, SERVICE_URL_PATTERNS, SIMPLE_ICONS_CDN, STT_MODELS, STT_MODEL_REGISTRY, ScopedConnectorRegistry, ScrapeProvider, SearchProvider, SerperProvider, Services, SpeechToText, StorageRegistry, StrategyRegistry, StreamEventType, StreamHelpers, StreamState, SummarizeCompactor, TERMINAL_TASK_STATUSES, TTS_MODELS, TTS_MODEL_REGISTRY, TaskTimeoutError, TaskValidationError, TavilyProvider, TextToSpeech, TokenBucketRateLimiter, ToolCallState, ToolExecutionError, ToolExecutionPipeline, ToolManager, ToolNotFoundError, ToolPermissionManager, ToolRegistry, ToolTimeoutError, TruncateCompactor, UserInfoPluginNextGen, VENDORS, VENDOR_ICON_MAP, VIDEO_MODELS, VIDEO_MODEL_REGISTRY, Vendor, VideoGeneration, WorkingMemory, WorkingMemoryPluginNextGen, addJitter, allVendorTemplates, assertNotDestroyed, authenticatedFetch, backoffSequence, backoffWait, bash, buildAuthConfig, buildEndpointWithQuery, buildQueryString, calculateBackoff, calculateCost, calculateEntrySize, calculateImageCost, calculateSTTCost, calculateTTSCost, calculateVideoCost, canTaskExecute, createAgentStorage, createAuthenticatedFetch, createBashTool, createConnectorFromTemplate, createCreatePRTool, createCustomToolDelete, createCustomToolDraft, createCustomToolList, createCustomToolLoad, createCustomToolMetaTools, createCustomToolSave, createCustomToolTest, createDesktopGetCursorTool, createDesktopGetScreenSizeTool, createDesktopKeyboardKeyTool, createDesktopKeyboardTypeTool, createDesktopMouseClickTool, createDesktopMouseDragTool, createDesktopMouseMoveTool, createDesktopMouseScrollTool, createDesktopScreenshotTool, createDesktopWindowFocusTool, createDesktopWindowListTool, createDraftEmailTool, createEditFileTool, createEditMeetingTool, createEstimator, createExecuteJavaScriptTool, createFileAgentDefinitionStorage, createFileContextStorage, createFileCustomToolStorage, createFileMediaStorage, createFileRoutineDefinitionStorage, createFindMeetingSlotsTool, createGetMeetingTranscriptTool, createGetPRTool, createGitHubReadFileTool, createGlobTool, createGrepTool, createImageGenerationTool, createImageProvider, createListDirectoryTool, createMeetingTool, createMessageWithImages, createMetricsCollector, createPRCommentsTool, createPRFilesTool, createPlan, createProvider, createReadFileTool, createRoutineDefinition, createRoutineExecution, createSearchCodeTool, createSearchFilesTool, createSendEmailTool, createSpeechToTextTool, createTask, createTextMessage, createTextToSpeechTool, createVideoProvider, createVideoTools, createWriteFileTool, customToolDelete, customToolDraft, customToolList, customToolLoad, customToolSave, customToolTest, defaultDescribeCall, desktopGetCursor, desktopGetScreenSize, desktopKeyboardKey, desktopKeyboardType, desktopMouseClick, desktopMouseDrag, desktopMouseMove, desktopMouseScroll, desktopScreenshot, desktopTools, desktopWindowFocus, desktopWindowList, detectDependencyCycle, detectServiceFromURL, developerTools, documentToContent, editFile, evaluateCondition, executeRoutine, extractJSON, extractJSONField, extractNumber, findConnectorByServiceTypes, forPlan, forTasks, formatAttendees, formatPluginDisplayName, formatRecipients, generateEncryptionKey, generateSimplePlan, generateWebAPITool, getActiveImageModels, getActiveModels, getActiveSTTModels, getActiveTTSModels, getActiveVideoModels, getAllBuiltInTools, getAllServiceIds, getAllVendorLogos, getAllVendorTemplates, getBackgroundOutput, getConnectorTools, getCredentialsSetupURL, getDesktopDriver, getDocsURL, getImageModelInfo, getImageModelsByVendor, getImageModelsWithFeature, getMediaOutputHandler, getMediaStorage, getModelInfo, getModelsByVendor, getNextExecutableTasks, getRegisteredScrapeProviders, getRoutineProgress, getSTTModelInfo, getSTTModelsByVendor, getSTTModelsWithFeature, getServiceDefinition, getServiceInfo, getServicesByCategory, getTTSModelInfo, getTTSModelsByVendor, getTTSModelsWithFeature, getTaskDependencies, getToolByName, getToolCallDescription, getToolCategories, getToolRegistry, getToolsByCategory, getToolsRequiringConnector, getUserPathPrefix, getVendorAuthTemplate, getVendorColor, getVendorDefaultBaseURL, getVendorInfo, getVendorLogo, getVendorLogoCdnUrl, getVendorLogoSvg, getVendorTemplate, getVideoModelInfo, getVideoModelsByVendor, getVideoModelsWithAudio, getVideoModelsWithFeature, glob, globalErrorHandler, grep, hasClipboardImage, hasVendorLogo, hydrateCustomTool, isBlockedCommand, isErrorEvent, isExcludedExtension, isKnownService, isOutputTextDelta, isReasoningDelta, isReasoningDone, isResponseComplete, isSimpleScope, isStreamEvent, isTaskAwareScope, isTaskBlocked, isTeamsMeetingUrl, isTerminalMemoryStatus, isTerminalStatus, isToolCallArgumentsDelta, isToolCallArgumentsDone, isToolCallStart, isVendor, killBackgroundProcess, listConnectorsByServiceTypes, listDirectory, listVendorIds, listVendors, listVendorsByAuthType, listVendorsByCategory, listVendorsWithLogos, logger, mergeTextPieces, metrics, microsoftFetch, normalizeEmails, parseKeyCombo, parseRepository, readClipboardImage, readDocumentAsContent, readFile5 as readFile, registerScrapeProvider, resetDefaultDriver, resolveConnector, resolveDependencies, resolveMaxContextTokens, resolveMeetingId, resolveModelCapabilities, resolveRepository, retryWithBackoff, sanitizeToolName, scopeEquals, scopeMatches, setMediaOutputHandler, setMediaStorage, setMetricsCollector, simpleTokenEstimator, toConnectorOptions, toolRegistry, tools_exports as tools, updateTaskStatus, validatePath, writeFile5 as writeFile };
|
|
51760
|
+
export { AGENT_DEFINITION_FORMAT_VERSION, AIError, APPROVAL_STATE_VERSION, Agent, AgentContextNextGen, ApproximateTokenEstimator, BaseMediaProvider, BasePluginNextGen, BaseProvider, BaseTextProvider, BraveProvider, CONNECTOR_CONFIG_VERSION, CONTEXT_SESSION_FORMAT_VERSION, CUSTOM_TOOL_DEFINITION_VERSION, CheckpointManager, CircuitBreaker, CircuitOpenError, Connector, ConnectorConfigStore, ConnectorTools, ConsoleMetrics, ContentType, ContextOverflowError, DEFAULT_ALLOWLIST, DEFAULT_BACKOFF_CONFIG, DEFAULT_BASE_DELAY_MS, DEFAULT_CHECKPOINT_STRATEGY, DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_CONFIG2 as DEFAULT_CONFIG, DEFAULT_CONNECTOR_TIMEOUT, DEFAULT_CONTEXT_CONFIG, DEFAULT_DESKTOP_CONFIG, DEFAULT_FEATURES, DEFAULT_FILESYSTEM_CONFIG, DEFAULT_HISTORY_MANAGER_CONFIG, DEFAULT_MAX_DELAY_MS, DEFAULT_MAX_RETRIES, DEFAULT_MEMORY_CONFIG, DEFAULT_PERMISSION_CONFIG, DEFAULT_RATE_LIMITER_CONFIG, DEFAULT_RETRYABLE_STATUSES, DEFAULT_SHELL_CONFIG, DESKTOP_TOOL_NAMES, DefaultCompactionStrategy, DependencyCycleError, DocumentReader, ErrorHandler, ExecutionContext, ExternalDependencyHandler, FileAgentDefinitionStorage, FileConnectorStorage, FileContextStorage, FileCustomToolStorage, FileMediaStorage as FileMediaOutputHandler, FileMediaStorage, FilePersistentInstructionsStorage, FileRoutineDefinitionStorage, FileStorage, FileUserInfoStorage, FormatDetector, FrameworkLogger, HookManager, IMAGE_MODELS, IMAGE_MODEL_REGISTRY, ImageGeneration, InContextMemoryPluginNextGen, InMemoryAgentStateStorage, InMemoryHistoryStorage, InMemoryMetrics, InMemoryPlanStorage, InMemoryStorage, InvalidConfigError, InvalidToolArgumentsError, LLM_MODELS, LoggingPlugin, MCPClient, MCPConnectionError, MCPError, MCPProtocolError, MCPRegistry, MCPResourceError, MCPTimeoutError, MCPToolError, MEMORY_PRIORITY_VALUES, MODEL_REGISTRY, MemoryConnectorStorage, MemoryEvictionCompactor, MemoryStorage, MessageBuilder, MessageRole, ModelNotSupportedError, NoOpMetrics, NutTreeDriver, OAuthManager, ParallelTasksError, PersistentInstructionsPluginNextGen, PlanningAgent, ProviderAuthError, ProviderConfigAgent, ProviderContextLengthError, ProviderError, ProviderErrorMapper, ProviderNotFoundError, ProviderRateLimitError, ROUTINE_KEYS, RapidAPIProvider, RateLimitError, SERVICE_DEFINITIONS, SERVICE_INFO, SERVICE_URL_PATTERNS, SIMPLE_ICONS_CDN, STT_MODELS, STT_MODEL_REGISTRY, ScopedConnectorRegistry, ScrapeProvider, SearchProvider, SerperProvider, Services, SpeechToText, StorageRegistry, StrategyRegistry, StreamEventType, StreamHelpers, StreamState, SummarizeCompactor, TERMINAL_TASK_STATUSES, TTS_MODELS, TTS_MODEL_REGISTRY, TaskTimeoutError, TaskValidationError, TavilyProvider, TextToSpeech, TokenBucketRateLimiter, ToolCallState, ToolExecutionError, ToolExecutionPipeline, ToolManager, ToolNotFoundError, ToolPermissionManager, ToolRegistry, ToolTimeoutError, TruncateCompactor, UserInfoPluginNextGen, VENDORS, VENDOR_ICON_MAP, VIDEO_MODELS, VIDEO_MODEL_REGISTRY, Vendor, VideoGeneration, WorkingMemory, WorkingMemoryPluginNextGen, addJitter, allVendorTemplates, assertNotDestroyed, authenticatedFetch, backoffSequence, backoffWait, bash, buildAuthConfig, buildEndpointWithQuery, buildQueryString, calculateBackoff, calculateCost, calculateEntrySize, calculateImageCost, calculateSTTCost, calculateTTSCost, calculateVideoCost, canTaskExecute, createAgentStorage, createAuthenticatedFetch, createBashTool, createConnectorFromTemplate, createCreatePRTool, createCustomToolDelete, createCustomToolDraft, createCustomToolList, createCustomToolLoad, createCustomToolMetaTools, createCustomToolSave, createCustomToolTest, createDesktopGetCursorTool, createDesktopGetScreenSizeTool, createDesktopKeyboardKeyTool, createDesktopKeyboardTypeTool, createDesktopMouseClickTool, createDesktopMouseDragTool, createDesktopMouseMoveTool, createDesktopMouseScrollTool, createDesktopScreenshotTool, createDesktopWindowFocusTool, createDesktopWindowListTool, createDraftEmailTool, createEditFileTool, createEditMeetingTool, createEstimator, createExecuteJavaScriptTool, createFileAgentDefinitionStorage, createFileContextStorage, createFileCustomToolStorage, createFileMediaStorage, createFileRoutineDefinitionStorage, createFindMeetingSlotsTool, createGetMeetingTranscriptTool, createGetPRTool, createGitHubReadFileTool, createGlobTool, createGrepTool, createImageGenerationTool, createImageProvider, createListDirectoryTool, createMeetingTool, createMessageWithImages, createMetricsCollector, createPRCommentsTool, createPRFilesTool, createPlan, createProvider, createReadFileTool, createRoutineDefinition, createRoutineExecution, createSearchCodeTool, createSearchFilesTool, createSendEmailTool, createSpeechToTextTool, createTask, createTextMessage, createTextToSpeechTool, createVideoProvider, createVideoTools, createWriteFileTool, customToolDelete, customToolDraft, customToolList, customToolLoad, customToolSave, customToolTest, defaultDescribeCall, desktopGetCursor, desktopGetScreenSize, desktopKeyboardKey, desktopKeyboardType, desktopMouseClick, desktopMouseDrag, desktopMouseMove, desktopMouseScroll, desktopScreenshot, desktopTools, desktopWindowFocus, desktopWindowList, detectDependencyCycle, detectServiceFromURL, developerTools, documentToContent, editFile, evaluateCondition, executeRoutine, extractJSON, extractJSONField, extractNumber, findConnectorByServiceTypes, forPlan, forTasks, formatAttendees, formatPluginDisplayName, formatRecipients, generateEncryptionKey, generateSimplePlan, generateWebAPITool, getActiveImageModels, getActiveModels, getActiveSTTModels, getActiveTTSModels, getActiveVideoModels, getAllBuiltInTools, getAllServiceIds, getAllVendorLogos, getAllVendorTemplates, getBackgroundOutput, getConnectorTools, getCredentialsSetupURL, getDesktopDriver, getDocsURL, getImageModelInfo, getImageModelsByVendor, getImageModelsWithFeature, getMediaOutputHandler, getMediaStorage, getModelInfo, getModelsByVendor, getNextExecutableTasks, getRegisteredScrapeProviders, getRoutineProgress, getSTTModelInfo, getSTTModelsByVendor, getSTTModelsWithFeature, getServiceDefinition, getServiceInfo, getServicesByCategory, getTTSModelInfo, getTTSModelsByVendor, getTTSModelsWithFeature, getTaskDependencies, getToolByName, getToolCallDescription, getToolCategories, getToolRegistry, getToolsByCategory, getToolsRequiringConnector, getUserPathPrefix, getVendorAuthTemplate, getVendorColor, getVendorDefaultBaseURL, getVendorInfo, getVendorLogo, getVendorLogoCdnUrl, getVendorLogoSvg, getVendorTemplate, getVideoModelInfo, getVideoModelsByVendor, getVideoModelsWithAudio, getVideoModelsWithFeature, glob, globalErrorHandler, grep, hasClipboardImage, hasVendorLogo, hydrateCustomTool, isBlockedCommand, isErrorEvent, isExcludedExtension, isKnownService, isOutputTextDelta, isReasoningDelta, isReasoningDone, isResponseComplete, isSimpleScope, isStreamEvent, isTaskAwareScope, isTaskBlocked, isTeamsMeetingUrl, isTerminalMemoryStatus, isTerminalStatus, isToolCallArgumentsDelta, isToolCallArgumentsDone, isToolCallStart, isVendor, killBackgroundProcess, listConnectorsByServiceTypes, listDirectory, listVendorIds, listVendors, listVendorsByAuthType, listVendorsByCategory, listVendorsWithLogos, logger, mergeTextPieces, metrics, microsoftFetch, normalizeEmails, parseKeyCombo, parseRepository, readClipboardImage, readDocumentAsContent, readFile5 as readFile, registerScrapeProvider, resetDefaultDriver, resolveConnector, resolveDependencies, resolveMaxContextTokens, resolveMeetingId, resolveModelCapabilities, resolveRepository, resolveTemplates, retryWithBackoff, sanitizeToolName, scopeEquals, scopeMatches, setMediaOutputHandler, setMediaStorage, setMetricsCollector, simpleTokenEstimator, toConnectorOptions, toolRegistry, tools_exports as tools, updateTaskStatus, validatePath, writeFile5 as writeFile };
|
|
50892
51761
|
//# sourceMappingURL=index.js.map
|
|
50893
51762
|
//# sourceMappingURL=index.js.map
|