@everworker/oneringai 0.4.1 → 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 +34 -8
- package/dist/{IProvider-Br817mKc.d.cts → IProvider-B8sqUzJG.d.cts} +37 -7
- package/dist/{IProvider-BUbU5UwV.d.ts → IProvider-CxDUGl6n.d.ts} +37 -7
- package/dist/{ImageModel-zh19LiVM.d.cts → ImageModel-Ds5_6sf7.d.cts} +1 -1
- package/dist/{ImageModel-B2KUs-ps.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-CR5PHkck.d.cts → index-CEjKTeSb.d.cts} +902 -7
- package/dist/{index-Cb7N9QIj.d.ts → index-CzGnmqOs.d.ts} +902 -7
- package/dist/index.cjs +2023 -484
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +440 -908
- package/dist/index.d.ts +440 -908
- package/dist/index.js +2003 -469
- 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();
|
|
@@ -11911,6 +12083,9 @@ var ToolManager = class extends EventEmitter {
|
|
|
11911
12083
|
}
|
|
11912
12084
|
};
|
|
11913
12085
|
|
|
12086
|
+
// src/core/context-nextgen/AgentContextNextGen.ts
|
|
12087
|
+
init_Logger();
|
|
12088
|
+
|
|
11914
12089
|
// src/core/Vendor.ts
|
|
11915
12090
|
var Vendor = {
|
|
11916
12091
|
OpenAI: "openai",
|
|
@@ -13284,6 +13459,7 @@ var ContentType = /* @__PURE__ */ ((ContentType2) => {
|
|
|
13284
13459
|
ContentType2["OUTPUT_TEXT"] = "output_text";
|
|
13285
13460
|
ContentType2["TOOL_USE"] = "tool_use";
|
|
13286
13461
|
ContentType2["TOOL_RESULT"] = "tool_result";
|
|
13462
|
+
ContentType2["THINKING"] = "thinking";
|
|
13287
13463
|
return ContentType2;
|
|
13288
13464
|
})(ContentType || {});
|
|
13289
13465
|
|
|
@@ -13546,6 +13722,11 @@ var BasePluginNextGen = class {
|
|
|
13546
13722
|
}
|
|
13547
13723
|
};
|
|
13548
13724
|
|
|
13725
|
+
// src/core/context-nextgen/snapshot.ts
|
|
13726
|
+
function formatPluginDisplayName(name) {
|
|
13727
|
+
return name.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
13728
|
+
}
|
|
13729
|
+
|
|
13549
13730
|
// src/core/context-nextgen/AgentContextNextGen.ts
|
|
13550
13731
|
init_Connector();
|
|
13551
13732
|
|
|
@@ -16224,8 +16405,11 @@ var AlgorithmicCompactionStrategy = class {
|
|
|
16224
16405
|
* Emergency compaction when context exceeds threshold.
|
|
16225
16406
|
*
|
|
16226
16407
|
* Strategy:
|
|
16227
|
-
* 1. Run consolidate() first to move tool results to memory
|
|
16408
|
+
* 1. Run consolidate() first to move tool results to memory (if working memory available)
|
|
16228
16409
|
* 2. If still need space, apply rolling window (remove oldest messages)
|
|
16410
|
+
*
|
|
16411
|
+
* Gracefully degrades: if working memory plugin is not registered,
|
|
16412
|
+
* skips step 1 and only uses rolling window compaction.
|
|
16229
16413
|
*/
|
|
16230
16414
|
async compact(context, targetToFree) {
|
|
16231
16415
|
const log = [];
|
|
@@ -16238,7 +16422,7 @@ var AlgorithmicCompactionStrategy = class {
|
|
|
16238
16422
|
tokensFreed += Math.abs(consolidateResult.tokensChanged);
|
|
16239
16423
|
log.push(...consolidateResult.actions);
|
|
16240
16424
|
}
|
|
16241
|
-
|
|
16425
|
+
const remaining = targetToFree - tokensFreed;
|
|
16242
16426
|
if (remaining > 0 && context.conversation.length > 0) {
|
|
16243
16427
|
log.push(`Rolling window: need to free ~${remaining} more tokens`);
|
|
16244
16428
|
const result = await this.applyRollingWindow(context, remaining, log);
|
|
@@ -16252,8 +16436,11 @@ var AlgorithmicCompactionStrategy = class {
|
|
|
16252
16436
|
* Post-cycle consolidation.
|
|
16253
16437
|
*
|
|
16254
16438
|
* 1. Find all tool pairs in conversation
|
|
16255
|
-
* 2. Move large tool results (> threshold) to Working Memory
|
|
16439
|
+
* 2. Move large tool results (> threshold) to Working Memory (if available)
|
|
16256
16440
|
* 3. Limit remaining tool pairs to maxToolPairs
|
|
16441
|
+
*
|
|
16442
|
+
* Gracefully degrades: if working memory is not available, skips step 2
|
|
16443
|
+
* and only limits tool pairs + removes excess via rolling window.
|
|
16257
16444
|
*/
|
|
16258
16445
|
async consolidate(context) {
|
|
16259
16446
|
const log = [];
|
|
@@ -16264,23 +16451,25 @@ var AlgorithmicCompactionStrategy = class {
|
|
|
16264
16451
|
return { performed: false, tokensChanged: 0, actions: [] };
|
|
16265
16452
|
}
|
|
16266
16453
|
const indicesToRemove = [];
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
|
|
16273
|
-
|
|
16274
|
-
|
|
16275
|
-
|
|
16276
|
-
indicesToRemove.
|
|
16277
|
-
|
|
16278
|
-
|
|
16279
|
-
indicesToRemove.
|
|
16454
|
+
if (memory) {
|
|
16455
|
+
for (const pair of toolPairs) {
|
|
16456
|
+
if (pair.resultSizeBytes > this.toolResultSizeThreshold) {
|
|
16457
|
+
const key = this.generateKey(pair.toolName, pair.toolUseId);
|
|
16458
|
+
const desc = this.generateDescription(pair.toolName, pair.toolArgs);
|
|
16459
|
+
await memory.store(key, desc, pair.resultContent, {
|
|
16460
|
+
tier: "raw",
|
|
16461
|
+
priority: "normal"
|
|
16462
|
+
});
|
|
16463
|
+
if (!indicesToRemove.includes(pair.toolUseIndex)) {
|
|
16464
|
+
indicesToRemove.push(pair.toolUseIndex);
|
|
16465
|
+
}
|
|
16466
|
+
if (!indicesToRemove.includes(pair.toolResultIndex)) {
|
|
16467
|
+
indicesToRemove.push(pair.toolResultIndex);
|
|
16468
|
+
}
|
|
16469
|
+
log.push(
|
|
16470
|
+
`Moved ${pair.toolName} result (${this.formatBytes(pair.resultSizeBytes)}) to memory: ${key}`
|
|
16471
|
+
);
|
|
16280
16472
|
}
|
|
16281
|
-
log.push(
|
|
16282
|
-
`Moved ${pair.toolName} result (${this.formatBytes(pair.resultSizeBytes)}) to memory: ${key}`
|
|
16283
|
-
);
|
|
16284
16473
|
}
|
|
16285
16474
|
}
|
|
16286
16475
|
const remainingPairs = toolPairs.filter(
|
|
@@ -16309,15 +16498,12 @@ var AlgorithmicCompactionStrategy = class {
|
|
|
16309
16498
|
};
|
|
16310
16499
|
}
|
|
16311
16500
|
/**
|
|
16312
|
-
* Get the Working Memory plugin from context.
|
|
16313
|
-
*
|
|
16501
|
+
* Get the Working Memory plugin from context, or null if not available.
|
|
16502
|
+
* When null, the strategy degrades gracefully (skips memory operations).
|
|
16314
16503
|
*/
|
|
16315
16504
|
getWorkingMemory(context) {
|
|
16316
16505
|
const plugin = context.plugins.find((p) => p.name === "working_memory");
|
|
16317
|
-
|
|
16318
|
-
throw new Error("AlgorithmicCompactionStrategy requires working_memory plugin");
|
|
16319
|
-
}
|
|
16320
|
-
return plugin;
|
|
16506
|
+
return plugin ? plugin : null;
|
|
16321
16507
|
}
|
|
16322
16508
|
/**
|
|
16323
16509
|
* Find all tool_use/tool_result pairs in conversation.
|
|
@@ -16696,12 +16882,14 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16696
16882
|
_agentId;
|
|
16697
16883
|
/** User ID for multi-user scenarios */
|
|
16698
16884
|
_userId;
|
|
16699
|
-
/**
|
|
16700
|
-
|
|
16885
|
+
/** Auth identities this agent is scoped to (connector + optional accountId) */
|
|
16886
|
+
_identities;
|
|
16701
16887
|
/** Storage backend */
|
|
16702
16888
|
_storage;
|
|
16703
16889
|
/** Destroyed flag */
|
|
16704
16890
|
_destroyed = false;
|
|
16891
|
+
/** Last thinking/reasoning content from the most recent assistant response */
|
|
16892
|
+
_lastThinking = null;
|
|
16705
16893
|
/** Cached budget from last prepare() call */
|
|
16706
16894
|
_cachedBudget = null;
|
|
16707
16895
|
/** Callback for beforeCompaction hook (set by Agent) */
|
|
@@ -16735,7 +16923,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16735
16923
|
this._systemPrompt = config.systemPrompt;
|
|
16736
16924
|
this._agentId = this._config.agentId;
|
|
16737
16925
|
this._userId = config.userId;
|
|
16738
|
-
this.
|
|
16926
|
+
this._identities = config.identities;
|
|
16739
16927
|
const sessionFactory = StorageRegistry.get("sessions");
|
|
16740
16928
|
const storageCtx = StorageRegistry.getContext() ?? (config.userId ? { userId: config.userId } : void 0);
|
|
16741
16929
|
this._storage = config.storage ?? (sessionFactory ? sessionFactory(this._agentId, storageCtx) : void 0);
|
|
@@ -16789,15 +16977,16 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16789
16977
|
}
|
|
16790
16978
|
/**
|
|
16791
16979
|
* Validate that a strategy's required plugins are registered.
|
|
16792
|
-
*
|
|
16980
|
+
* Logs a warning if required plugins are missing — the strategy should degrade gracefully.
|
|
16793
16981
|
*/
|
|
16794
16982
|
validateStrategyDependencies(strategy) {
|
|
16795
16983
|
if (!strategy.requiredPlugins?.length) return;
|
|
16796
16984
|
const availablePlugins = new Set(this._plugins.keys());
|
|
16797
16985
|
const missing = strategy.requiredPlugins.filter((name) => !availablePlugins.has(name));
|
|
16798
16986
|
if (missing.length > 0) {
|
|
16799
|
-
|
|
16800
|
-
|
|
16987
|
+
logger.warn(
|
|
16988
|
+
{ strategy: strategy.name, missing, available: Array.from(availablePlugins) },
|
|
16989
|
+
`Strategy '${strategy.name}' recommends plugins that are not registered: ${missing.join(", ")}. Strategy will degrade gracefully.`
|
|
16801
16990
|
);
|
|
16802
16991
|
}
|
|
16803
16992
|
}
|
|
@@ -16806,7 +16995,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16806
16995
|
* Merges with existing ToolContext to preserve other fields (memory, signal, taskId).
|
|
16807
16996
|
*
|
|
16808
16997
|
* Connector registry resolution order:
|
|
16809
|
-
* 1. If `
|
|
16998
|
+
* 1. If `identities` is set → filtered view showing only identity connectors
|
|
16810
16999
|
* 2. If access policy + userId → scoped view via Connector.scoped()
|
|
16811
17000
|
* 3. Otherwise → full global registry
|
|
16812
17001
|
*/
|
|
@@ -16816,6 +17005,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16816
17005
|
...existing,
|
|
16817
17006
|
agentId: this._agentId,
|
|
16818
17007
|
userId: this._userId,
|
|
17008
|
+
identities: this._identities,
|
|
16819
17009
|
connectorRegistry: this.buildConnectorRegistry()
|
|
16820
17010
|
});
|
|
16821
17011
|
}
|
|
@@ -16823,13 +17013,13 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16823
17013
|
* Build the connector registry appropriate for this agent's config.
|
|
16824
17014
|
*/
|
|
16825
17015
|
buildConnectorRegistry() {
|
|
16826
|
-
if (this.
|
|
16827
|
-
const allowedSet = new Set(this.
|
|
17016
|
+
if (this._identities?.length) {
|
|
17017
|
+
const allowedSet = new Set(this._identities.map((id) => id.connector));
|
|
16828
17018
|
const base = this._userId && Connector.getAccessPolicy() ? Connector.scoped({ userId: this._userId }) : Connector.asRegistry();
|
|
16829
17019
|
return {
|
|
16830
17020
|
get: (name) => {
|
|
16831
17021
|
if (!allowedSet.has(name)) {
|
|
16832
|
-
const available =
|
|
17022
|
+
const available = [...allowedSet].filter((n) => base.has(n)).join(", ") || "none";
|
|
16833
17023
|
throw new Error(`Connector '${name}' not found. Available: ${available}`);
|
|
16834
17024
|
}
|
|
16835
17025
|
return base.get(name);
|
|
@@ -16881,13 +17071,13 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16881
17071
|
this._userId = value;
|
|
16882
17072
|
this.syncToolContext();
|
|
16883
17073
|
}
|
|
16884
|
-
/** Get the
|
|
16885
|
-
get
|
|
16886
|
-
return this.
|
|
17074
|
+
/** Get the auth identities this agent is scoped to (undefined = all visible connectors) */
|
|
17075
|
+
get identities() {
|
|
17076
|
+
return this._identities;
|
|
16887
17077
|
}
|
|
16888
|
-
/** Set
|
|
16889
|
-
set
|
|
16890
|
-
this.
|
|
17078
|
+
/** Set auth identities. Updates ToolContext.connectorRegistry and identity-aware descriptions. */
|
|
17079
|
+
set identities(value) {
|
|
17080
|
+
this._identities = value;
|
|
16891
17081
|
this.syncToolContext();
|
|
16892
17082
|
}
|
|
16893
17083
|
/** Get/set system prompt */
|
|
@@ -16913,6 +17103,13 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
16913
17103
|
get storage() {
|
|
16914
17104
|
return this._storage ?? null;
|
|
16915
17105
|
}
|
|
17106
|
+
/**
|
|
17107
|
+
* Get the last thinking/reasoning content from the most recent assistant response.
|
|
17108
|
+
* Updated on every assistant response, always available regardless of persistence setting.
|
|
17109
|
+
*/
|
|
17110
|
+
get lastThinking() {
|
|
17111
|
+
return this._lastThinking;
|
|
17112
|
+
}
|
|
16916
17113
|
/** Get max context tokens */
|
|
16917
17114
|
get maxContextTokens() {
|
|
16918
17115
|
return this._maxContextTokens;
|
|
@@ -17094,6 +17291,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
17094
17291
|
}
|
|
17095
17292
|
const id = this.generateId();
|
|
17096
17293
|
const contentArray = [];
|
|
17294
|
+
let thinkingText = null;
|
|
17097
17295
|
for (const item of output) {
|
|
17098
17296
|
if (item.type === "message" && "content" in item) {
|
|
17099
17297
|
const msg = item;
|
|
@@ -17105,12 +17303,19 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
17105
17303
|
});
|
|
17106
17304
|
} else if (c.type === "tool_use" /* TOOL_USE */) {
|
|
17107
17305
|
contentArray.push(c);
|
|
17306
|
+
} else if (c.type === "thinking" /* THINKING */) {
|
|
17307
|
+
const thinking = c;
|
|
17308
|
+
thinkingText = thinking.thinking;
|
|
17309
|
+
if (thinking.persistInHistory) {
|
|
17310
|
+
contentArray.push(c);
|
|
17311
|
+
}
|
|
17108
17312
|
}
|
|
17109
17313
|
}
|
|
17110
17314
|
} else if (item.type === "compaction" || item.type === "reasoning") {
|
|
17111
17315
|
continue;
|
|
17112
17316
|
}
|
|
17113
17317
|
}
|
|
17318
|
+
this._lastThinking = thinkingText;
|
|
17114
17319
|
if (contentArray.length > 0) {
|
|
17115
17320
|
const message = {
|
|
17116
17321
|
type: "message",
|
|
@@ -17209,6 +17414,7 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
|
|
|
17209
17414
|
*/
|
|
17210
17415
|
async prepare() {
|
|
17211
17416
|
this.assertNotDestroyed();
|
|
17417
|
+
this._lastThinking = null;
|
|
17212
17418
|
const compactionLog = [];
|
|
17213
17419
|
const toolsTokens = this.calculateToolsTokens();
|
|
17214
17420
|
const availableForContent = this._maxContextTokens - this._config.responseReserve - toolsTokens;
|
|
@@ -17421,6 +17627,8 @@ ${content}`);
|
|
|
17421
17627
|
total += this._estimateImageTokens();
|
|
17422
17628
|
}
|
|
17423
17629
|
}
|
|
17630
|
+
} else if (c.type === "thinking" /* THINKING */) {
|
|
17631
|
+
total += this._estimator.estimateTokens(c.thinking || "");
|
|
17424
17632
|
} else if (c.type === "input_image_url" /* INPUT_IMAGE_URL */) {
|
|
17425
17633
|
const imgContent = c;
|
|
17426
17634
|
const detail = imgContent.image_url?.detail;
|
|
@@ -17918,6 +18126,188 @@ ${content}`);
|
|
|
17918
18126
|
get strategy() {
|
|
17919
18127
|
return this._compactionStrategy.name;
|
|
17920
18128
|
}
|
|
18129
|
+
/**
|
|
18130
|
+
* Get a complete, serializable snapshot of the context state.
|
|
18131
|
+
*
|
|
18132
|
+
* Returns all data needed by UI "Look Inside" panels without reaching
|
|
18133
|
+
* into plugin internals. Plugin data is auto-discovered from the plugin
|
|
18134
|
+
* registry — new/custom plugins appear automatically.
|
|
18135
|
+
*
|
|
18136
|
+
* @param toolStats - Optional tool usage stats (from ToolManager.getStats())
|
|
18137
|
+
* @returns Serializable context snapshot
|
|
18138
|
+
*/
|
|
18139
|
+
async getSnapshot(toolStats) {
|
|
18140
|
+
const resolveContents = async (raw) => {
|
|
18141
|
+
const resolved = raw instanceof Promise ? await raw : raw;
|
|
18142
|
+
if (resolved instanceof Map) return Array.from(resolved.values());
|
|
18143
|
+
return resolved;
|
|
18144
|
+
};
|
|
18145
|
+
if (this._destroyed) {
|
|
18146
|
+
const emptyBudget = this._cachedBudget ?? {
|
|
18147
|
+
maxTokens: this._maxContextTokens,
|
|
18148
|
+
responseReserve: this._config.responseReserve,
|
|
18149
|
+
systemMessageTokens: 0,
|
|
18150
|
+
toolsTokens: 0,
|
|
18151
|
+
conversationTokens: 0,
|
|
18152
|
+
currentInputTokens: 0,
|
|
18153
|
+
totalUsed: 0,
|
|
18154
|
+
available: this._maxContextTokens - this._config.responseReserve,
|
|
18155
|
+
utilizationPercent: 0,
|
|
18156
|
+
breakdown: {
|
|
18157
|
+
systemPrompt: 0,
|
|
18158
|
+
persistentInstructions: 0,
|
|
18159
|
+
pluginInstructions: 0,
|
|
18160
|
+
pluginContents: {},
|
|
18161
|
+
tools: 0,
|
|
18162
|
+
conversation: 0,
|
|
18163
|
+
currentInput: 0
|
|
18164
|
+
}
|
|
18165
|
+
};
|
|
18166
|
+
return {
|
|
18167
|
+
available: false,
|
|
18168
|
+
agentId: this._agentId,
|
|
18169
|
+
model: this._config.model,
|
|
18170
|
+
features: this._config.features,
|
|
18171
|
+
budget: emptyBudget,
|
|
18172
|
+
strategy: this._compactionStrategy.name,
|
|
18173
|
+
messagesCount: 0,
|
|
18174
|
+
toolCallsCount: 0,
|
|
18175
|
+
systemPrompt: null,
|
|
18176
|
+
plugins: [],
|
|
18177
|
+
tools: []
|
|
18178
|
+
};
|
|
18179
|
+
}
|
|
18180
|
+
const budget = await this.calculateBudget();
|
|
18181
|
+
const plugins = [];
|
|
18182
|
+
for (const plugin of this._plugins.values()) {
|
|
18183
|
+
let formattedContent = null;
|
|
18184
|
+
try {
|
|
18185
|
+
formattedContent = await plugin.getContent();
|
|
18186
|
+
} catch {
|
|
18187
|
+
}
|
|
18188
|
+
plugins.push({
|
|
18189
|
+
name: plugin.name,
|
|
18190
|
+
displayName: formatPluginDisplayName(plugin.name),
|
|
18191
|
+
enabled: true,
|
|
18192
|
+
tokenSize: plugin.getTokenSize(),
|
|
18193
|
+
instructionsTokenSize: plugin.getInstructionsTokenSize(),
|
|
18194
|
+
compactable: plugin.isCompactable(),
|
|
18195
|
+
contents: await resolveContents(plugin.getContents()),
|
|
18196
|
+
formattedContent
|
|
18197
|
+
});
|
|
18198
|
+
}
|
|
18199
|
+
const usageCounts = /* @__PURE__ */ new Map();
|
|
18200
|
+
if (toolStats?.mostUsed) {
|
|
18201
|
+
for (const { name, count } of toolStats.mostUsed) {
|
|
18202
|
+
usageCounts.set(name, count);
|
|
18203
|
+
}
|
|
18204
|
+
}
|
|
18205
|
+
const tools = [];
|
|
18206
|
+
for (const toolName of this._tools.list()) {
|
|
18207
|
+
const reg = this._tools.getRegistration(toolName);
|
|
18208
|
+
if (!reg) continue;
|
|
18209
|
+
tools.push({
|
|
18210
|
+
name: toolName,
|
|
18211
|
+
description: reg.tool.definition.function.description || "",
|
|
18212
|
+
enabled: reg.enabled,
|
|
18213
|
+
callCount: reg.metadata.usageCount ?? usageCounts.get(toolName) ?? 0,
|
|
18214
|
+
namespace: reg.namespace || void 0
|
|
18215
|
+
});
|
|
18216
|
+
}
|
|
18217
|
+
let toolCallsCount = 0;
|
|
18218
|
+
for (const item of this._conversation) {
|
|
18219
|
+
if (item.type === "message" && item.role === "assistant" /* ASSISTANT */) {
|
|
18220
|
+
for (const c of item.content) {
|
|
18221
|
+
if (c.type === "tool_use" /* TOOL_USE */) toolCallsCount++;
|
|
18222
|
+
}
|
|
18223
|
+
}
|
|
18224
|
+
}
|
|
18225
|
+
return {
|
|
18226
|
+
available: true,
|
|
18227
|
+
agentId: this._agentId,
|
|
18228
|
+
model: this._config.model,
|
|
18229
|
+
features: this._config.features,
|
|
18230
|
+
budget,
|
|
18231
|
+
strategy: this._compactionStrategy.name,
|
|
18232
|
+
messagesCount: this._conversation.length,
|
|
18233
|
+
toolCallsCount,
|
|
18234
|
+
systemPrompt: this._systemPrompt ?? null,
|
|
18235
|
+
plugins,
|
|
18236
|
+
tools
|
|
18237
|
+
};
|
|
18238
|
+
}
|
|
18239
|
+
/**
|
|
18240
|
+
* Get a human-readable breakdown of the prepared context.
|
|
18241
|
+
*
|
|
18242
|
+
* Calls `prepare()` internally, then maps each InputItem to a named
|
|
18243
|
+
* component with content text and token estimate. Used by "View Full Context" UIs.
|
|
18244
|
+
*
|
|
18245
|
+
* @returns View context data with components and raw text for "Copy All"
|
|
18246
|
+
*/
|
|
18247
|
+
async getViewContext() {
|
|
18248
|
+
if (this._destroyed) {
|
|
18249
|
+
return { available: false, components: [], totalTokens: 0, rawContext: "" };
|
|
18250
|
+
}
|
|
18251
|
+
const { input, budget } = await this.prepare();
|
|
18252
|
+
const components = [];
|
|
18253
|
+
let rawParts = [];
|
|
18254
|
+
for (const item of input) {
|
|
18255
|
+
if (item.type === "compaction") {
|
|
18256
|
+
components.push({
|
|
18257
|
+
name: "Compaction Block",
|
|
18258
|
+
content: "[Compacted content]",
|
|
18259
|
+
tokenEstimate: 0
|
|
18260
|
+
});
|
|
18261
|
+
continue;
|
|
18262
|
+
}
|
|
18263
|
+
const msg = item;
|
|
18264
|
+
const roleName = msg.role === "developer" /* DEVELOPER */ ? "System Message" : msg.role === "user" /* USER */ ? "User Message" : "Assistant Message";
|
|
18265
|
+
for (const block of msg.content) {
|
|
18266
|
+
let name = roleName;
|
|
18267
|
+
let text = "";
|
|
18268
|
+
switch (block.type) {
|
|
18269
|
+
case "input_text" /* INPUT_TEXT */:
|
|
18270
|
+
text = block.text;
|
|
18271
|
+
break;
|
|
18272
|
+
case "output_text" /* OUTPUT_TEXT */:
|
|
18273
|
+
text = block.text;
|
|
18274
|
+
break;
|
|
18275
|
+
case "tool_use" /* TOOL_USE */:
|
|
18276
|
+
name = `Tool Call: ${block.name}`;
|
|
18277
|
+
text = `${block.name}(${block.arguments})`;
|
|
18278
|
+
break;
|
|
18279
|
+
case "tool_result" /* TOOL_RESULT */:
|
|
18280
|
+
name = `Tool Result: ${block.tool_use_id}`;
|
|
18281
|
+
text = typeof block.content === "string" ? block.content : JSON.stringify(block.content, null, 2);
|
|
18282
|
+
if (block.error) text = `[Error] ${block.error}
|
|
18283
|
+
${text}`;
|
|
18284
|
+
break;
|
|
18285
|
+
case "input_image_url" /* INPUT_IMAGE_URL */:
|
|
18286
|
+
name = "Image Input";
|
|
18287
|
+
text = `[Image: ${block.image_url.url.substring(0, 100)}...]`;
|
|
18288
|
+
break;
|
|
18289
|
+
case "input_file" /* INPUT_FILE */:
|
|
18290
|
+
name = "File Input";
|
|
18291
|
+
text = `[File: ${block.file_id}]`;
|
|
18292
|
+
break;
|
|
18293
|
+
case "thinking" /* THINKING */:
|
|
18294
|
+
name = "Thinking";
|
|
18295
|
+
text = block.thinking || "";
|
|
18296
|
+
break;
|
|
18297
|
+
}
|
|
18298
|
+
const tokenEstimate = this._estimator.estimateTokens(text);
|
|
18299
|
+
components.push({ name, content: text, tokenEstimate });
|
|
18300
|
+
rawParts.push(`--- ${name} ---
|
|
18301
|
+
${text}`);
|
|
18302
|
+
}
|
|
18303
|
+
}
|
|
18304
|
+
return {
|
|
18305
|
+
available: true,
|
|
18306
|
+
components,
|
|
18307
|
+
totalTokens: budget.totalUsed,
|
|
18308
|
+
rawContext: rawParts.join("\n\n")
|
|
18309
|
+
};
|
|
18310
|
+
}
|
|
17921
18311
|
// ============================================================================
|
|
17922
18312
|
// Utilities
|
|
17923
18313
|
// ============================================================================
|
|
@@ -18176,6 +18566,13 @@ var BaseTextProvider = class extends BaseProvider {
|
|
|
18176
18566
|
}
|
|
18177
18567
|
return textParts.join("\n");
|
|
18178
18568
|
}
|
|
18569
|
+
/**
|
|
18570
|
+
* List available models from the provider's API.
|
|
18571
|
+
* Default returns empty array; providers override when they have SDK support.
|
|
18572
|
+
*/
|
|
18573
|
+
async listModels() {
|
|
18574
|
+
return [];
|
|
18575
|
+
}
|
|
18179
18576
|
/**
|
|
18180
18577
|
* Clean up provider resources (circuit breaker listeners, etc.)
|
|
18181
18578
|
* Should be called when the provider is no longer needed.
|
|
@@ -18328,12 +18725,21 @@ var OpenAIResponsesConverter = class {
|
|
|
18328
18725
|
} else if (item.type === "reasoning") {
|
|
18329
18726
|
const reasoning = item;
|
|
18330
18727
|
if (reasoning.summary) {
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
}
|
|
18728
|
+
let summaryText;
|
|
18729
|
+
if (typeof reasoning.summary === "string") {
|
|
18730
|
+
summaryText = reasoning.summary;
|
|
18731
|
+
} else if (Array.isArray(reasoning.summary)) {
|
|
18732
|
+
summaryText = reasoning.summary.map((s) => s.text || "").filter(Boolean).join("\n");
|
|
18733
|
+
} else {
|
|
18734
|
+
summaryText = "";
|
|
18735
|
+
}
|
|
18736
|
+
if (summaryText) {
|
|
18737
|
+
content.push({
|
|
18738
|
+
type: "thinking" /* THINKING */,
|
|
18739
|
+
thinking: summaryText,
|
|
18740
|
+
persistInHistory: false
|
|
18741
|
+
});
|
|
18742
|
+
}
|
|
18337
18743
|
}
|
|
18338
18744
|
}
|
|
18339
18745
|
}
|
|
@@ -18356,10 +18762,20 @@ var OpenAIResponsesConverter = class {
|
|
|
18356
18762
|
}
|
|
18357
18763
|
],
|
|
18358
18764
|
output_text: outputText,
|
|
18765
|
+
// Extract thinking text from content for convenience field
|
|
18766
|
+
...(() => {
|
|
18767
|
+
const thinkingTexts = content.filter((c) => c.type === "thinking" /* THINKING */).map((c) => c.thinking).filter(Boolean);
|
|
18768
|
+
return thinkingTexts.length > 0 ? { thinking: thinkingTexts.join("\n") } : {};
|
|
18769
|
+
})(),
|
|
18359
18770
|
usage: {
|
|
18360
18771
|
input_tokens: response.usage?.input_tokens || 0,
|
|
18361
18772
|
output_tokens: response.usage?.output_tokens || 0,
|
|
18362
|
-
total_tokens: response.usage?.total_tokens || 0
|
|
18773
|
+
total_tokens: response.usage?.total_tokens || 0,
|
|
18774
|
+
...response.usage?.output_tokens_details?.reasoning_tokens != null && {
|
|
18775
|
+
output_tokens_details: {
|
|
18776
|
+
reasoning_tokens: response.usage.output_tokens_details.reasoning_tokens
|
|
18777
|
+
}
|
|
18778
|
+
}
|
|
18363
18779
|
}
|
|
18364
18780
|
};
|
|
18365
18781
|
}
|
|
@@ -18464,6 +18880,8 @@ var StreamEventType = /* @__PURE__ */ ((StreamEventType2) => {
|
|
|
18464
18880
|
StreamEventType2["TOOL_EXECUTION_START"] = "response.tool_execution.start";
|
|
18465
18881
|
StreamEventType2["TOOL_EXECUTION_DONE"] = "response.tool_execution.done";
|
|
18466
18882
|
StreamEventType2["ITERATION_COMPLETE"] = "response.iteration.complete";
|
|
18883
|
+
StreamEventType2["REASONING_DELTA"] = "response.reasoning.delta";
|
|
18884
|
+
StreamEventType2["REASONING_DONE"] = "response.reasoning.done";
|
|
18467
18885
|
StreamEventType2["RESPONSE_COMPLETE"] = "response.complete";
|
|
18468
18886
|
StreamEventType2["ERROR"] = "response.error";
|
|
18469
18887
|
return StreamEventType2;
|
|
@@ -18483,6 +18901,12 @@ function isToolCallArgumentsDelta(event) {
|
|
|
18483
18901
|
function isToolCallArgumentsDone(event) {
|
|
18484
18902
|
return event.type === "response.tool_call_arguments.done" /* TOOL_CALL_ARGUMENTS_DONE */;
|
|
18485
18903
|
}
|
|
18904
|
+
function isReasoningDelta(event) {
|
|
18905
|
+
return event.type === "response.reasoning.delta" /* REASONING_DELTA */;
|
|
18906
|
+
}
|
|
18907
|
+
function isReasoningDone(event) {
|
|
18908
|
+
return event.type === "response.reasoning.done" /* REASONING_DONE */;
|
|
18909
|
+
}
|
|
18486
18910
|
function isResponseComplete(event) {
|
|
18487
18911
|
return event.type === "response.complete" /* RESPONSE_COMPLETE */;
|
|
18488
18912
|
}
|
|
@@ -18500,6 +18924,8 @@ var OpenAIResponsesStreamConverter = class {
|
|
|
18500
18924
|
let sequenceNumber = 0;
|
|
18501
18925
|
const activeItems = /* @__PURE__ */ new Map();
|
|
18502
18926
|
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
18927
|
+
const reasoningBuffers = /* @__PURE__ */ new Map();
|
|
18928
|
+
const reasoningDoneEmitted = /* @__PURE__ */ new Set();
|
|
18503
18929
|
for await (const event of stream) {
|
|
18504
18930
|
if (process.env.DEBUG_OPENAI) {
|
|
18505
18931
|
console.error("[DEBUG] Responses API event:", event.type);
|
|
@@ -18521,6 +18947,12 @@ var OpenAIResponsesStreamConverter = class {
|
|
|
18521
18947
|
activeItems.set(addedEvent.output_index.toString(), {
|
|
18522
18948
|
type: item.type
|
|
18523
18949
|
});
|
|
18950
|
+
if (item.type === "reasoning") {
|
|
18951
|
+
activeItems.set(addedEvent.output_index.toString(), {
|
|
18952
|
+
type: "reasoning"
|
|
18953
|
+
});
|
|
18954
|
+
reasoningBuffers.set(addedEvent.output_index.toString(), []);
|
|
18955
|
+
}
|
|
18524
18956
|
if (item.type === "function_call") {
|
|
18525
18957
|
const functionCall = item;
|
|
18526
18958
|
const toolCallId = functionCall.call_id;
|
|
@@ -18578,9 +19010,53 @@ var OpenAIResponsesStreamConverter = class {
|
|
|
18578
19010
|
}
|
|
18579
19011
|
break;
|
|
18580
19012
|
}
|
|
19013
|
+
case "response.reasoning_summary_text.delta":
|
|
19014
|
+
case "response.reasoning_text.delta": {
|
|
19015
|
+
const reasoningEvent = event;
|
|
19016
|
+
const outputIdx = reasoningEvent.output_index?.toString();
|
|
19017
|
+
const buffer = outputIdx ? reasoningBuffers.get(outputIdx) : void 0;
|
|
19018
|
+
if (buffer) {
|
|
19019
|
+
buffer.push(reasoningEvent.delta || "");
|
|
19020
|
+
}
|
|
19021
|
+
yield {
|
|
19022
|
+
type: "response.reasoning.delta" /* REASONING_DELTA */,
|
|
19023
|
+
response_id: responseId,
|
|
19024
|
+
item_id: reasoningEvent.item_id || `reasoning_${responseId}`,
|
|
19025
|
+
delta: reasoningEvent.delta || "",
|
|
19026
|
+
sequence_number: sequenceNumber++
|
|
19027
|
+
};
|
|
19028
|
+
break;
|
|
19029
|
+
}
|
|
19030
|
+
case "response.reasoning_text.done": {
|
|
19031
|
+
const doneEvent = event;
|
|
19032
|
+
const outputIdx = doneEvent.output_index.toString();
|
|
19033
|
+
const rBuf = reasoningBuffers.get(outputIdx);
|
|
19034
|
+
const thinkingText = rBuf ? rBuf.join("") : doneEvent.text || "";
|
|
19035
|
+
reasoningDoneEmitted.add(outputIdx);
|
|
19036
|
+
yield {
|
|
19037
|
+
type: "response.reasoning.done" /* REASONING_DONE */,
|
|
19038
|
+
response_id: responseId,
|
|
19039
|
+
item_id: doneEvent.item_id || `reasoning_${responseId}`,
|
|
19040
|
+
thinking: thinkingText
|
|
19041
|
+
};
|
|
19042
|
+
break;
|
|
19043
|
+
}
|
|
18581
19044
|
case "response.output_item.done": {
|
|
18582
19045
|
const doneEvent = event;
|
|
18583
19046
|
const item = doneEvent.item;
|
|
19047
|
+
if (item.type === "reasoning") {
|
|
19048
|
+
const outputIdx = doneEvent.output_index.toString();
|
|
19049
|
+
if (!reasoningDoneEmitted.has(outputIdx)) {
|
|
19050
|
+
const rBuf = reasoningBuffers.get(outputIdx);
|
|
19051
|
+
const thinkingText = rBuf ? rBuf.join("") : "";
|
|
19052
|
+
yield {
|
|
19053
|
+
type: "response.reasoning.done" /* REASONING_DONE */,
|
|
19054
|
+
response_id: responseId,
|
|
19055
|
+
item_id: item.id || `reasoning_${responseId}`,
|
|
19056
|
+
thinking: thinkingText
|
|
19057
|
+
};
|
|
19058
|
+
}
|
|
19059
|
+
}
|
|
18584
19060
|
if (item.type === "function_call") {
|
|
18585
19061
|
const functionCall = item;
|
|
18586
19062
|
const buffer = toolCallBuffers.get(functionCall.call_id);
|
|
@@ -18612,7 +19088,12 @@ var OpenAIResponsesStreamConverter = class {
|
|
|
18612
19088
|
usage: {
|
|
18613
19089
|
input_tokens: response.usage?.input_tokens || 0,
|
|
18614
19090
|
output_tokens: response.usage?.output_tokens || 0,
|
|
18615
|
-
total_tokens: response.usage?.total_tokens || 0
|
|
19091
|
+
total_tokens: response.usage?.total_tokens || 0,
|
|
19092
|
+
...response.usage?.output_tokens_details?.reasoning_tokens != null && {
|
|
19093
|
+
output_tokens_details: {
|
|
19094
|
+
reasoning_tokens: response.usage.output_tokens_details.reasoning_tokens
|
|
19095
|
+
}
|
|
19096
|
+
}
|
|
18616
19097
|
},
|
|
18617
19098
|
iterations: 1
|
|
18618
19099
|
};
|
|
@@ -18653,6 +19134,26 @@ function resolveMaxContextTokens(model, fallback) {
|
|
|
18653
19134
|
return info ? info.features.input.tokens : fallback;
|
|
18654
19135
|
}
|
|
18655
19136
|
|
|
19137
|
+
// src/infrastructure/providers/shared/validateThinkingConfig.ts
|
|
19138
|
+
function validateThinkingConfig(thinking) {
|
|
19139
|
+
if (!thinking.enabled) return;
|
|
19140
|
+
if (thinking.budgetTokens !== void 0) {
|
|
19141
|
+
if (typeof thinking.budgetTokens !== "number" || thinking.budgetTokens < 1) {
|
|
19142
|
+
throw new Error(
|
|
19143
|
+
`Invalid thinking budgetTokens: ${thinking.budgetTokens}. Must be a positive number.`
|
|
19144
|
+
);
|
|
19145
|
+
}
|
|
19146
|
+
}
|
|
19147
|
+
if (thinking.effort !== void 0) {
|
|
19148
|
+
const validEfforts = ["low", "medium", "high"];
|
|
19149
|
+
if (!validEfforts.includes(thinking.effort)) {
|
|
19150
|
+
throw new Error(
|
|
19151
|
+
`Invalid thinking effort: '${thinking.effort}'. Must be one of: ${validEfforts.join(", ")}`
|
|
19152
|
+
);
|
|
19153
|
+
}
|
|
19154
|
+
}
|
|
19155
|
+
}
|
|
19156
|
+
|
|
18656
19157
|
// src/infrastructure/providers/openai/OpenAITextProvider.ts
|
|
18657
19158
|
var OpenAITextProvider = class extends BaseTextProvider {
|
|
18658
19159
|
name = "openai";
|
|
@@ -18720,6 +19221,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
|
|
|
18720
19221
|
},
|
|
18721
19222
|
...options.metadata && { metadata: options.metadata }
|
|
18722
19223
|
};
|
|
19224
|
+
this.applyReasoningConfig(params, options);
|
|
18723
19225
|
const response = await this.client.responses.create(params);
|
|
18724
19226
|
return this.converter.convertResponse(response);
|
|
18725
19227
|
} catch (error) {
|
|
@@ -18761,6 +19263,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
|
|
|
18761
19263
|
...options.metadata && { metadata: options.metadata },
|
|
18762
19264
|
stream: true
|
|
18763
19265
|
};
|
|
19266
|
+
this.applyReasoningConfig(params, options);
|
|
18764
19267
|
const stream = await this.client.responses.create(params);
|
|
18765
19268
|
yield* this.streamConverter.convertStream(stream);
|
|
18766
19269
|
} catch (error) {
|
|
@@ -18782,6 +19285,27 @@ var OpenAITextProvider = class extends BaseTextProvider {
|
|
|
18782
19285
|
maxOutputTokens: 16384
|
|
18783
19286
|
});
|
|
18784
19287
|
}
|
|
19288
|
+
/**
|
|
19289
|
+
* List available models from the OpenAI API
|
|
19290
|
+
*/
|
|
19291
|
+
async listModels() {
|
|
19292
|
+
const models = [];
|
|
19293
|
+
for await (const model of this.client.models.list()) {
|
|
19294
|
+
models.push(model.id);
|
|
19295
|
+
}
|
|
19296
|
+
return models.sort();
|
|
19297
|
+
}
|
|
19298
|
+
/**
|
|
19299
|
+
* Apply reasoning config from unified thinking option to request params
|
|
19300
|
+
*/
|
|
19301
|
+
applyReasoningConfig(params, options) {
|
|
19302
|
+
if (options.thinking?.enabled) {
|
|
19303
|
+
validateThinkingConfig(options.thinking);
|
|
19304
|
+
params.reasoning = {
|
|
19305
|
+
effort: options.thinking.effort || "medium"
|
|
19306
|
+
};
|
|
19307
|
+
}
|
|
19308
|
+
}
|
|
18785
19309
|
/**
|
|
18786
19310
|
* Handle OpenAI-specific errors
|
|
18787
19311
|
*/
|
|
@@ -18824,6 +19348,7 @@ function buildLLMResponse(options) {
|
|
|
18824
19348
|
}
|
|
18825
19349
|
];
|
|
18826
19350
|
const outputText = extractTextFromContent(content);
|
|
19351
|
+
const thinking = extractThinkingFromContent(content);
|
|
18827
19352
|
return {
|
|
18828
19353
|
id: responseId,
|
|
18829
19354
|
object: "response",
|
|
@@ -18832,6 +19357,7 @@ function buildLLMResponse(options) {
|
|
|
18832
19357
|
model,
|
|
18833
19358
|
output,
|
|
18834
19359
|
output_text: outputText,
|
|
19360
|
+
...thinking && { thinking },
|
|
18835
19361
|
usage: {
|
|
18836
19362
|
input_tokens: usage.inputTokens,
|
|
18837
19363
|
output_tokens: usage.outputTokens,
|
|
@@ -18844,6 +19370,10 @@ function extractTextFromContent(content) {
|
|
|
18844
19370
|
(c) => c.type === "output_text" /* OUTPUT_TEXT */
|
|
18845
19371
|
).map((c) => c.text).join("\n");
|
|
18846
19372
|
}
|
|
19373
|
+
function extractThinkingFromContent(content) {
|
|
19374
|
+
const thinkingTexts = content.filter((c) => c.type === "thinking" /* THINKING */).map((c) => c.thinking).filter(Boolean);
|
|
19375
|
+
return thinkingTexts.length > 0 ? thinkingTexts.join("\n") : void 0;
|
|
19376
|
+
}
|
|
18847
19377
|
function createTextContent(text) {
|
|
18848
19378
|
return {
|
|
18849
19379
|
type: "output_text" /* OUTPUT_TEXT */,
|
|
@@ -19093,7 +19623,15 @@ var AnthropicConverter = class extends BaseConverter {
|
|
|
19093
19623
|
if (tools && tools.length > 0) {
|
|
19094
19624
|
params.tools = tools;
|
|
19095
19625
|
}
|
|
19096
|
-
if (options.
|
|
19626
|
+
if (options.thinking?.enabled) {
|
|
19627
|
+
validateThinkingConfig(options.thinking);
|
|
19628
|
+
const budgetTokens = options.thinking.budgetTokens || 1e4;
|
|
19629
|
+
params.thinking = {
|
|
19630
|
+
type: "enabled",
|
|
19631
|
+
budget_tokens: budgetTokens
|
|
19632
|
+
};
|
|
19633
|
+
params.temperature = 1;
|
|
19634
|
+
} else if (options.temperature !== void 0) {
|
|
19097
19635
|
params.temperature = options.temperature;
|
|
19098
19636
|
}
|
|
19099
19637
|
return params;
|
|
@@ -19139,6 +19677,14 @@ var AnthropicConverter = class extends BaseConverter {
|
|
|
19139
19677
|
content.push(this.createText(block.text));
|
|
19140
19678
|
} else if (block.type === "tool_use") {
|
|
19141
19679
|
content.push(this.createToolUse(block.id, block.name, block.input));
|
|
19680
|
+
} else if (block.type === "thinking") {
|
|
19681
|
+
const thinkingBlock = block;
|
|
19682
|
+
content.push({
|
|
19683
|
+
type: "thinking" /* THINKING */,
|
|
19684
|
+
thinking: thinkingBlock.thinking || "",
|
|
19685
|
+
signature: thinkingBlock.signature,
|
|
19686
|
+
persistInHistory: true
|
|
19687
|
+
});
|
|
19142
19688
|
}
|
|
19143
19689
|
}
|
|
19144
19690
|
return content;
|
|
@@ -19217,6 +19763,17 @@ var AnthropicConverter = class extends BaseConverter {
|
|
|
19217
19763
|
});
|
|
19218
19764
|
break;
|
|
19219
19765
|
}
|
|
19766
|
+
case "thinking" /* THINKING */: {
|
|
19767
|
+
const thinkingContent = c;
|
|
19768
|
+
if (thinkingContent.signature) {
|
|
19769
|
+
blocks.push({
|
|
19770
|
+
type: "thinking",
|
|
19771
|
+
thinking: thinkingContent.thinking,
|
|
19772
|
+
signature: thinkingContent.signature
|
|
19773
|
+
});
|
|
19774
|
+
}
|
|
19775
|
+
break;
|
|
19776
|
+
}
|
|
19220
19777
|
}
|
|
19221
19778
|
}
|
|
19222
19779
|
if (blocks.length === 1 && blocks[0]?.type === "text") {
|
|
@@ -19349,6 +19906,8 @@ var BaseStreamConverter = class {
|
|
|
19349
19906
|
usage = { inputTokens: 0, outputTokens: 0 };
|
|
19350
19907
|
/** Buffers for accumulating tool call arguments */
|
|
19351
19908
|
toolCallBuffers = /* @__PURE__ */ new Map();
|
|
19909
|
+
/** Buffer for accumulating reasoning/thinking content */
|
|
19910
|
+
reasoningBuffer = "";
|
|
19352
19911
|
// ==========================================================================
|
|
19353
19912
|
// Public API
|
|
19354
19913
|
// ==========================================================================
|
|
@@ -19383,6 +19942,7 @@ var BaseStreamConverter = class {
|
|
|
19383
19942
|
this.sequenceNumber = 0;
|
|
19384
19943
|
this.usage = { inputTokens: 0, outputTokens: 0 };
|
|
19385
19944
|
this.toolCallBuffers.clear();
|
|
19945
|
+
this.reasoningBuffer = "";
|
|
19386
19946
|
}
|
|
19387
19947
|
/**
|
|
19388
19948
|
* Reset converter state for a new stream
|
|
@@ -19437,6 +19997,33 @@ var BaseStreamConverter = class {
|
|
|
19437
19997
|
sequence_number: this.nextSequence()
|
|
19438
19998
|
};
|
|
19439
19999
|
}
|
|
20000
|
+
/**
|
|
20001
|
+
* Create REASONING_DELTA event and accumulate reasoning buffer
|
|
20002
|
+
*/
|
|
20003
|
+
emitReasoningDelta(delta, itemId) {
|
|
20004
|
+
this.reasoningBuffer += delta;
|
|
20005
|
+
return {
|
|
20006
|
+
type: "response.reasoning.delta" /* REASONING_DELTA */,
|
|
20007
|
+
response_id: this.responseId,
|
|
20008
|
+
item_id: itemId || `reasoning_${this.responseId}`,
|
|
20009
|
+
delta,
|
|
20010
|
+
sequence_number: this.nextSequence()
|
|
20011
|
+
};
|
|
20012
|
+
}
|
|
20013
|
+
/**
|
|
20014
|
+
* Create REASONING_DONE event with accumulated reasoning
|
|
20015
|
+
*/
|
|
20016
|
+
emitReasoningDone(itemId) {
|
|
20017
|
+
const id = itemId || `reasoning_${this.responseId}`;
|
|
20018
|
+
const thinking = this.reasoningBuffer;
|
|
20019
|
+
this.reasoningBuffer = "";
|
|
20020
|
+
return {
|
|
20021
|
+
type: "response.reasoning.done" /* REASONING_DONE */,
|
|
20022
|
+
response_id: this.responseId,
|
|
20023
|
+
item_id: id,
|
|
20024
|
+
thinking
|
|
20025
|
+
};
|
|
20026
|
+
}
|
|
19440
20027
|
/**
|
|
19441
20028
|
* Create TOOL_CALL_START event
|
|
19442
20029
|
*/
|
|
@@ -19581,7 +20168,10 @@ var AnthropicStreamConverter = class extends BaseStreamConverter {
|
|
|
19581
20168
|
handleContentBlockStart(event) {
|
|
19582
20169
|
const index = event.index;
|
|
19583
20170
|
const block = event.content_block;
|
|
19584
|
-
if (block.type === "
|
|
20171
|
+
if (block.type === "thinking") {
|
|
20172
|
+
this.contentBlockIndex.set(index, { type: "thinking" });
|
|
20173
|
+
return [];
|
|
20174
|
+
} else if (block.type === "text") {
|
|
19585
20175
|
this.contentBlockIndex.set(index, { type: "text" });
|
|
19586
20176
|
return [];
|
|
19587
20177
|
} else if (block.type === "tool_use") {
|
|
@@ -19602,7 +20192,12 @@ var AnthropicStreamConverter = class extends BaseStreamConverter {
|
|
|
19602
20192
|
const delta = event.delta;
|
|
19603
20193
|
const blockInfo = this.contentBlockIndex.get(index);
|
|
19604
20194
|
if (!blockInfo) return [];
|
|
19605
|
-
if (delta.type === "
|
|
20195
|
+
if (delta.type === "thinking_delta") {
|
|
20196
|
+
const thinkingDelta = delta;
|
|
20197
|
+
return [
|
|
20198
|
+
this.emitReasoningDelta(thinkingDelta.thinking || "", `thinking_${this.responseId}`)
|
|
20199
|
+
];
|
|
20200
|
+
} else if (delta.type === "text_delta") {
|
|
19606
20201
|
return [
|
|
19607
20202
|
this.emitTextDelta(delta.text, {
|
|
19608
20203
|
itemId: `msg_${this.responseId}`,
|
|
@@ -19622,6 +20217,9 @@ var AnthropicStreamConverter = class extends BaseStreamConverter {
|
|
|
19622
20217
|
const index = event.index;
|
|
19623
20218
|
const blockInfo = this.contentBlockIndex.get(index);
|
|
19624
20219
|
if (!blockInfo) return [];
|
|
20220
|
+
if (blockInfo.type === "thinking") {
|
|
20221
|
+
return [this.emitReasoningDone(`thinking_${this.responseId}`)];
|
|
20222
|
+
}
|
|
19625
20223
|
if (blockInfo.type === "tool_use") {
|
|
19626
20224
|
return [this.emitToolCallArgsDone(blockInfo.id || "", blockInfo.name)];
|
|
19627
20225
|
}
|
|
@@ -19720,6 +20318,16 @@ var AnthropicTextProvider = class extends BaseTextProvider {
|
|
|
19720
20318
|
caps.supportsJSONSchema = false;
|
|
19721
20319
|
return caps;
|
|
19722
20320
|
}
|
|
20321
|
+
/**
|
|
20322
|
+
* List available models from the Anthropic API
|
|
20323
|
+
*/
|
|
20324
|
+
async listModels() {
|
|
20325
|
+
const models = [];
|
|
20326
|
+
for await (const model of this.client.models.list()) {
|
|
20327
|
+
models.push(model.id);
|
|
20328
|
+
}
|
|
20329
|
+
return models.sort();
|
|
20330
|
+
}
|
|
19723
20331
|
/**
|
|
19724
20332
|
* Handle Anthropic-specific errors
|
|
19725
20333
|
*/
|
|
@@ -19898,6 +20506,11 @@ var GoogleConverter = class {
|
|
|
19898
20506
|
request.generationConfig.thinkingConfig = {
|
|
19899
20507
|
thinkingLevel: options.vendorOptions.thinkingLevel
|
|
19900
20508
|
};
|
|
20509
|
+
} else if (options.thinking?.enabled) {
|
|
20510
|
+
validateThinkingConfig(options.thinking);
|
|
20511
|
+
request.generationConfig.thinkingConfig = {
|
|
20512
|
+
thinkingBudget: options.thinking.budgetTokens || 8192
|
|
20513
|
+
};
|
|
19901
20514
|
}
|
|
19902
20515
|
if (tools && tools.length > 0) {
|
|
19903
20516
|
request.generationConfig.allowCodeExecution = false;
|
|
@@ -20113,7 +20726,13 @@ var GoogleConverter = class {
|
|
|
20113
20726
|
convertGeminiPartsToContent(parts) {
|
|
20114
20727
|
const content = [];
|
|
20115
20728
|
for (const part of parts) {
|
|
20116
|
-
if ("text" in part && part.text) {
|
|
20729
|
+
if ("thought" in part && part.thought === true && "text" in part && part.text) {
|
|
20730
|
+
content.push({
|
|
20731
|
+
type: "thinking" /* THINKING */,
|
|
20732
|
+
thinking: part.text,
|
|
20733
|
+
persistInHistory: false
|
|
20734
|
+
});
|
|
20735
|
+
} else if ("text" in part && part.text) {
|
|
20117
20736
|
content.push(createTextContent(part.text));
|
|
20118
20737
|
} else if ("functionCall" in part && part.functionCall) {
|
|
20119
20738
|
const toolId = generateToolCallId("google");
|
|
@@ -20191,6 +20810,8 @@ var GoogleStreamConverter = class {
|
|
|
20191
20810
|
isFirst = true;
|
|
20192
20811
|
toolCallBuffers = /* @__PURE__ */ new Map();
|
|
20193
20812
|
hadToolCalls = false;
|
|
20813
|
+
reasoningBuffer = "";
|
|
20814
|
+
wasThinking = false;
|
|
20194
20815
|
// External storage for thought signatures (shared with GoogleConverter)
|
|
20195
20816
|
thoughtSignatureStorage = null;
|
|
20196
20817
|
// External storage for tool call ID → name mapping (shared with GoogleConverter)
|
|
@@ -20218,6 +20839,8 @@ var GoogleStreamConverter = class {
|
|
|
20218
20839
|
this.isFirst = true;
|
|
20219
20840
|
this.toolCallBuffers.clear();
|
|
20220
20841
|
this.hadToolCalls = false;
|
|
20842
|
+
this.reasoningBuffer = "";
|
|
20843
|
+
this.wasThinking = false;
|
|
20221
20844
|
let lastUsage = {
|
|
20222
20845
|
input_tokens: 0,
|
|
20223
20846
|
output_tokens: 0,
|
|
@@ -20243,6 +20866,16 @@ var GoogleStreamConverter = class {
|
|
|
20243
20866
|
yield event;
|
|
20244
20867
|
}
|
|
20245
20868
|
}
|
|
20869
|
+
if (this.wasThinking && this.reasoningBuffer) {
|
|
20870
|
+
yield {
|
|
20871
|
+
type: "response.reasoning.done" /* REASONING_DONE */,
|
|
20872
|
+
response_id: this.responseId,
|
|
20873
|
+
item_id: `thinking_${this.responseId}`,
|
|
20874
|
+
thinking: this.reasoningBuffer
|
|
20875
|
+
};
|
|
20876
|
+
this.reasoningBuffer = "";
|
|
20877
|
+
this.wasThinking = false;
|
|
20878
|
+
}
|
|
20246
20879
|
if (this.toolCallBuffers.size > 0) {
|
|
20247
20880
|
for (const [toolCallId, buffer] of this.toolCallBuffers) {
|
|
20248
20881
|
yield {
|
|
@@ -20282,7 +20915,28 @@ var GoogleStreamConverter = class {
|
|
|
20282
20915
|
const candidate = chunk.candidates?.[0];
|
|
20283
20916
|
if (!candidate?.content?.parts) return events;
|
|
20284
20917
|
for (const part of candidate.content.parts) {
|
|
20285
|
-
|
|
20918
|
+
const isThought = "thought" in part && part.thought === true;
|
|
20919
|
+
if (isThought && part.text) {
|
|
20920
|
+
this.wasThinking = true;
|
|
20921
|
+
this.reasoningBuffer += part.text;
|
|
20922
|
+
events.push({
|
|
20923
|
+
type: "response.reasoning.delta" /* REASONING_DELTA */,
|
|
20924
|
+
response_id: this.responseId,
|
|
20925
|
+
item_id: `thinking_${this.responseId}`,
|
|
20926
|
+
delta: part.text,
|
|
20927
|
+
sequence_number: this.sequenceNumber++
|
|
20928
|
+
});
|
|
20929
|
+
} else if (part.text) {
|
|
20930
|
+
if (this.wasThinking) {
|
|
20931
|
+
this.wasThinking = false;
|
|
20932
|
+
events.push({
|
|
20933
|
+
type: "response.reasoning.done" /* REASONING_DONE */,
|
|
20934
|
+
response_id: this.responseId,
|
|
20935
|
+
item_id: `thinking_${this.responseId}`,
|
|
20936
|
+
thinking: this.reasoningBuffer
|
|
20937
|
+
});
|
|
20938
|
+
this.reasoningBuffer = "";
|
|
20939
|
+
}
|
|
20286
20940
|
events.push({
|
|
20287
20941
|
type: "response.output_text.delta" /* OUTPUT_TEXT_DELTA */,
|
|
20288
20942
|
response_id: this.responseId,
|
|
@@ -20381,6 +21035,8 @@ var GoogleStreamConverter = class {
|
|
|
20381
21035
|
this.isFirst = true;
|
|
20382
21036
|
this.toolCallBuffers.clear();
|
|
20383
21037
|
this.hadToolCalls = false;
|
|
21038
|
+
this.reasoningBuffer = "";
|
|
21039
|
+
this.wasThinking = false;
|
|
20384
21040
|
}
|
|
20385
21041
|
/**
|
|
20386
21042
|
* Reset converter state for a new stream
|
|
@@ -20510,6 +21166,18 @@ var GoogleTextProvider = class extends BaseTextProvider {
|
|
|
20510
21166
|
maxOutputTokens: 65536
|
|
20511
21167
|
});
|
|
20512
21168
|
}
|
|
21169
|
+
/**
|
|
21170
|
+
* List available models from the Google Gemini API
|
|
21171
|
+
*/
|
|
21172
|
+
async listModels() {
|
|
21173
|
+
const models = [];
|
|
21174
|
+
const pager = await this.client.models.list();
|
|
21175
|
+
for await (const model of pager) {
|
|
21176
|
+
const name = model.name?.replace(/^models\//, "") ?? "";
|
|
21177
|
+
if (name) models.push(name);
|
|
21178
|
+
}
|
|
21179
|
+
return models.sort();
|
|
21180
|
+
}
|
|
20513
21181
|
/**
|
|
20514
21182
|
* Handle Google-specific errors
|
|
20515
21183
|
*/
|
|
@@ -20617,6 +21285,18 @@ var VertexAITextProvider = class extends BaseTextProvider {
|
|
|
20617
21285
|
maxOutputTokens: 65536
|
|
20618
21286
|
});
|
|
20619
21287
|
}
|
|
21288
|
+
/**
|
|
21289
|
+
* List available models from the Vertex AI API
|
|
21290
|
+
*/
|
|
21291
|
+
async listModels() {
|
|
21292
|
+
const models = [];
|
|
21293
|
+
const pager = await this.client.models.list();
|
|
21294
|
+
for await (const model of pager) {
|
|
21295
|
+
const name = model.name?.replace(/^models\//, "") ?? "";
|
|
21296
|
+
if (name) models.push(name);
|
|
21297
|
+
}
|
|
21298
|
+
return models.sort();
|
|
21299
|
+
}
|
|
20620
21300
|
/**
|
|
20621
21301
|
* Handle Vertex AI-specific errors
|
|
20622
21302
|
*/
|
|
@@ -20662,6 +21342,23 @@ var GenericOpenAIProvider = class extends OpenAITextProvider {
|
|
|
20662
21342
|
};
|
|
20663
21343
|
}
|
|
20664
21344
|
}
|
|
21345
|
+
/**
|
|
21346
|
+
* Override API key validation for generic providers.
|
|
21347
|
+
* Services like Ollama don't require authentication, so accept any key including mock/placeholder keys.
|
|
21348
|
+
*/
|
|
21349
|
+
validateApiKey() {
|
|
21350
|
+
return { isValid: true };
|
|
21351
|
+
}
|
|
21352
|
+
/**
|
|
21353
|
+
* Override listModels for error safety — some OpenAI-compatible APIs may not support /v1/models
|
|
21354
|
+
*/
|
|
21355
|
+
async listModels() {
|
|
21356
|
+
try {
|
|
21357
|
+
return await super.listModels();
|
|
21358
|
+
} catch {
|
|
21359
|
+
return [];
|
|
21360
|
+
}
|
|
21361
|
+
}
|
|
20665
21362
|
/**
|
|
20666
21363
|
* Override model capabilities for generic providers (registry-driven with conservative defaults)
|
|
20667
21364
|
*/
|
|
@@ -20859,7 +21556,7 @@ var BaseAgent = class extends EventEmitter {
|
|
|
20859
21556
|
model: config.model,
|
|
20860
21557
|
agentId: config.name,
|
|
20861
21558
|
userId: config.userId,
|
|
20862
|
-
|
|
21559
|
+
identities: config.identities,
|
|
20863
21560
|
// Include storage and sessionId if session config is provided
|
|
20864
21561
|
storage: config.session?.storage,
|
|
20865
21562
|
// Thread tool execution timeout to ToolManager
|
|
@@ -21029,16 +21726,16 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21029
21726
|
this._agentContext.userId = value;
|
|
21030
21727
|
}
|
|
21031
21728
|
/**
|
|
21032
|
-
* Get the
|
|
21729
|
+
* Get the auth identities this agent is scoped to (undefined = all visible connectors).
|
|
21033
21730
|
*/
|
|
21034
|
-
get
|
|
21035
|
-
return this._agentContext.
|
|
21731
|
+
get identities() {
|
|
21732
|
+
return this._agentContext.identities;
|
|
21036
21733
|
}
|
|
21037
21734
|
/**
|
|
21038
|
-
*
|
|
21735
|
+
* Set auth identities at runtime. Updates ToolContext.connectorRegistry and tool descriptions.
|
|
21039
21736
|
*/
|
|
21040
|
-
set
|
|
21041
|
-
this._agentContext.
|
|
21737
|
+
set identities(value) {
|
|
21738
|
+
this._agentContext.identities = value;
|
|
21042
21739
|
}
|
|
21043
21740
|
/**
|
|
21044
21741
|
* Permission management. Returns ToolPermissionManager for approval control.
|
|
@@ -21050,9 +21747,12 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21050
21747
|
/**
|
|
21051
21748
|
* Add a tool to the agent.
|
|
21052
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.)
|
|
21053
21753
|
*/
|
|
21054
|
-
addTool(tool) {
|
|
21055
|
-
this._agentContext.tools.register(tool);
|
|
21754
|
+
addTool(tool, options) {
|
|
21755
|
+
this._agentContext.tools.register(tool, options);
|
|
21056
21756
|
if (tool.permission) {
|
|
21057
21757
|
this._permissionManager.setToolConfig(tool.definition.function.name, tool.permission);
|
|
21058
21758
|
}
|
|
@@ -21092,7 +21792,34 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21092
21792
|
*/
|
|
21093
21793
|
getEnabledToolDefinitions() {
|
|
21094
21794
|
const toolContext = this._agentContext.tools.getToolContext();
|
|
21095
|
-
|
|
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;
|
|
21096
21823
|
if (tool.descriptionFactory) {
|
|
21097
21824
|
const dynamicDescription = tool.descriptionFactory(toolContext);
|
|
21098
21825
|
return {
|
|
@@ -21106,6 +21833,34 @@ var BaseAgent = class extends EventEmitter {
|
|
|
21106
21833
|
return tool.definition;
|
|
21107
21834
|
});
|
|
21108
21835
|
}
|
|
21836
|
+
// ===== Model Discovery =====
|
|
21837
|
+
/**
|
|
21838
|
+
* List available models from the provider's API.
|
|
21839
|
+
* Useful for discovering models dynamically (e.g., Ollama local models).
|
|
21840
|
+
*/
|
|
21841
|
+
async listModels() {
|
|
21842
|
+
return this._provider.listModels();
|
|
21843
|
+
}
|
|
21844
|
+
// ===== Snapshot / Inspection =====
|
|
21845
|
+
/**
|
|
21846
|
+
* Get a complete, serializable snapshot of the agent's context state.
|
|
21847
|
+
*
|
|
21848
|
+
* Convenience method that auto-wires tool usage stats from ToolManager.
|
|
21849
|
+
* Used by UI "Look Inside" panels.
|
|
21850
|
+
*/
|
|
21851
|
+
async getSnapshot() {
|
|
21852
|
+
const stats = this._agentContext.tools.getStats();
|
|
21853
|
+
return this._agentContext.getSnapshot({ mostUsed: stats.mostUsed });
|
|
21854
|
+
}
|
|
21855
|
+
/**
|
|
21856
|
+
* Get a human-readable breakdown of the prepared context.
|
|
21857
|
+
*
|
|
21858
|
+
* Convenience method that delegates to AgentContextNextGen.
|
|
21859
|
+
* Used by "View Full Context" UI panels.
|
|
21860
|
+
*/
|
|
21861
|
+
async getViewContext() {
|
|
21862
|
+
return this._agentContext.getViewContext();
|
|
21863
|
+
}
|
|
21109
21864
|
// ===== Direct LLM Access (Bypasses AgentContext) =====
|
|
21110
21865
|
/**
|
|
21111
21866
|
* Get the provider for LLM calls.
|
|
@@ -21869,6 +22624,8 @@ var StreamState = class {
|
|
|
21869
22624
|
createdAt;
|
|
21870
22625
|
// Text accumulation: item_id -> text chunks
|
|
21871
22626
|
textBuffers;
|
|
22627
|
+
// Reasoning accumulation: item_id -> reasoning chunks
|
|
22628
|
+
reasoningBuffers;
|
|
21872
22629
|
// Tool call accumulation: tool_call_id -> buffer
|
|
21873
22630
|
toolCallBuffers;
|
|
21874
22631
|
// Completed tool calls
|
|
@@ -21890,6 +22647,7 @@ var StreamState = class {
|
|
|
21890
22647
|
this.model = model;
|
|
21891
22648
|
this.createdAt = createdAt || Date.now();
|
|
21892
22649
|
this.textBuffers = /* @__PURE__ */ new Map();
|
|
22650
|
+
this.reasoningBuffers = /* @__PURE__ */ new Map();
|
|
21893
22651
|
this.toolCallBuffers = /* @__PURE__ */ new Map();
|
|
21894
22652
|
this.completedToolCalls = [];
|
|
21895
22653
|
this.toolResults = /* @__PURE__ */ new Map();
|
|
@@ -21933,6 +22691,39 @@ var StreamState = class {
|
|
|
21933
22691
|
}
|
|
21934
22692
|
return allText.join("");
|
|
21935
22693
|
}
|
|
22694
|
+
/**
|
|
22695
|
+
* Accumulate reasoning delta for a specific item
|
|
22696
|
+
*/
|
|
22697
|
+
accumulateReasoningDelta(itemId, delta) {
|
|
22698
|
+
if (!this.reasoningBuffers.has(itemId)) {
|
|
22699
|
+
this.reasoningBuffers.set(itemId, []);
|
|
22700
|
+
}
|
|
22701
|
+
this.reasoningBuffers.get(itemId).push(delta);
|
|
22702
|
+
this.totalChunks++;
|
|
22703
|
+
}
|
|
22704
|
+
/**
|
|
22705
|
+
* Get complete accumulated reasoning for an item
|
|
22706
|
+
*/
|
|
22707
|
+
getCompleteReasoning(itemId) {
|
|
22708
|
+
const chunks = this.reasoningBuffers.get(itemId);
|
|
22709
|
+
return chunks ? chunks.join("") : "";
|
|
22710
|
+
}
|
|
22711
|
+
/**
|
|
22712
|
+
* Get all accumulated reasoning (all items concatenated)
|
|
22713
|
+
*/
|
|
22714
|
+
getAllReasoning() {
|
|
22715
|
+
const allReasoning = [];
|
|
22716
|
+
for (const chunks of this.reasoningBuffers.values()) {
|
|
22717
|
+
allReasoning.push(chunks.join(""));
|
|
22718
|
+
}
|
|
22719
|
+
return allReasoning.join("");
|
|
22720
|
+
}
|
|
22721
|
+
/**
|
|
22722
|
+
* Check if stream has any accumulated reasoning
|
|
22723
|
+
*/
|
|
22724
|
+
hasReasoning() {
|
|
22725
|
+
return this.reasoningBuffers.size > 0;
|
|
22726
|
+
}
|
|
21936
22727
|
/**
|
|
21937
22728
|
* Start accumulating tool call arguments
|
|
21938
22729
|
*/
|
|
@@ -22101,6 +22892,7 @@ var StreamState = class {
|
|
|
22101
22892
|
*/
|
|
22102
22893
|
clear() {
|
|
22103
22894
|
this.textBuffers.clear();
|
|
22895
|
+
this.reasoningBuffers.clear();
|
|
22104
22896
|
this.toolCallBuffers.clear();
|
|
22105
22897
|
this.completedToolCalls = [];
|
|
22106
22898
|
this.toolResults.clear();
|
|
@@ -22114,6 +22906,7 @@ var StreamState = class {
|
|
|
22114
22906
|
model: this.model,
|
|
22115
22907
|
createdAt: this.createdAt,
|
|
22116
22908
|
textBuffers: new Map(this.textBuffers),
|
|
22909
|
+
reasoningBuffers: new Map(this.reasoningBuffers),
|
|
22117
22910
|
toolCallBuffers: new Map(this.toolCallBuffers),
|
|
22118
22911
|
completedToolCalls: [...this.completedToolCalls],
|
|
22119
22912
|
toolResults: new Map(this.toolResults),
|
|
@@ -22543,6 +23336,20 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
22543
23336
|
_addStreamingAssistantMessage(streamState, toolCalls) {
|
|
22544
23337
|
const assistantText = streamState.getAllText();
|
|
22545
23338
|
const assistantContent = [];
|
|
23339
|
+
if (streamState.hasReasoning()) {
|
|
23340
|
+
const reasoning = streamState.getAllReasoning();
|
|
23341
|
+
if (reasoning) {
|
|
23342
|
+
const isAnthropic = this.connector.vendor === Vendor.Anthropic;
|
|
23343
|
+
assistantContent.push({
|
|
23344
|
+
type: "thinking" /* THINKING */,
|
|
23345
|
+
thinking: reasoning,
|
|
23346
|
+
// Streaming doesn't carry Anthropic signatures, so signature is undefined here.
|
|
23347
|
+
// Non-streaming responses (via convertResponse) capture signatures correctly.
|
|
23348
|
+
signature: void 0,
|
|
23349
|
+
persistInHistory: isAnthropic
|
|
23350
|
+
});
|
|
23351
|
+
}
|
|
23352
|
+
}
|
|
22546
23353
|
if (assistantText && assistantText.trim()) {
|
|
22547
23354
|
assistantContent.push({
|
|
22548
23355
|
type: "output_text" /* OUTPUT_TEXT */,
|
|
@@ -22781,6 +23588,7 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
22781
23588
|
tools: this.getEnabledToolDefinitions(),
|
|
22782
23589
|
tool_choice: "auto",
|
|
22783
23590
|
temperature: this._config.temperature,
|
|
23591
|
+
thinking: this._config.thinking,
|
|
22784
23592
|
vendorOptions: this._config.vendorOptions
|
|
22785
23593
|
};
|
|
22786
23594
|
const beforeLLM = await this.hookManager.executeHooks("before:llm", {
|
|
@@ -22846,6 +23654,7 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
22846
23654
|
tools: this.getEnabledToolDefinitions(),
|
|
22847
23655
|
tool_choice: "auto",
|
|
22848
23656
|
temperature: this._config.temperature,
|
|
23657
|
+
thinking: this._config.thinking,
|
|
22849
23658
|
vendorOptions: this._config.vendorOptions
|
|
22850
23659
|
};
|
|
22851
23660
|
await this.hookManager.executeHooks("before:llm", {
|
|
@@ -22863,7 +23672,9 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
22863
23672
|
});
|
|
22864
23673
|
try {
|
|
22865
23674
|
for await (const event of this._provider.streamGenerate(generateOptions)) {
|
|
22866
|
-
if (event
|
|
23675
|
+
if (isReasoningDelta(event)) {
|
|
23676
|
+
streamState.accumulateReasoningDelta(event.item_id, event.delta);
|
|
23677
|
+
} else if (event.type === "response.output_text.delta" /* OUTPUT_TEXT_DELTA */) {
|
|
22867
23678
|
streamState.accumulateTextDelta(event.item_id, event.delta);
|
|
22868
23679
|
} else if (event.type === "response.tool_call.start" /* TOOL_CALL_START */) {
|
|
22869
23680
|
streamState.startToolCall(event.tool_call_id, event.tool_name);
|
|
@@ -23393,6 +24204,7 @@ function createTask(input) {
|
|
|
23393
24204
|
suggestedTools: input.suggestedTools,
|
|
23394
24205
|
validation: input.validation,
|
|
23395
24206
|
expectedOutput: input.expectedOutput,
|
|
24207
|
+
controlFlow: input.controlFlow,
|
|
23396
24208
|
attempts: 0,
|
|
23397
24209
|
maxAttempts: input.maxAttempts ?? 3,
|
|
23398
24210
|
createdAt: now,
|
|
@@ -23645,6 +24457,7 @@ function createRoutineDefinition(input) {
|
|
|
23645
24457
|
instructions: input.instructions,
|
|
23646
24458
|
concurrency: input.concurrency,
|
|
23647
24459
|
allowDynamicTasks: input.allowDynamicTasks ?? false,
|
|
24460
|
+
parameters: input.parameters,
|
|
23648
24461
|
tags: input.tags,
|
|
23649
24462
|
author: input.author,
|
|
23650
24463
|
createdAt: now,
|
|
@@ -23860,6 +24673,321 @@ function extractNumber(text, patterns = [
|
|
|
23860
24673
|
|
|
23861
24674
|
// src/core/routineRunner.ts
|
|
23862
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
|
|
23863
24991
|
function defaultSystemPrompt(definition) {
|
|
23864
24992
|
const parts = [];
|
|
23865
24993
|
if (definition.instructions) {
|
|
@@ -23988,6 +25116,14 @@ async function collectValidationContext(agent, responseText) {
|
|
|
23988
25116
|
toolCallLog
|
|
23989
25117
|
};
|
|
23990
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
|
+
}
|
|
23991
25127
|
function estimateTokens(text) {
|
|
23992
25128
|
return Math.ceil(text.length / 4);
|
|
23993
25129
|
}
|
|
@@ -24031,32 +25167,42 @@ function buildPlanOverview(execution, definition, currentTaskId) {
|
|
|
24031
25167
|
}
|
|
24032
25168
|
return parts.join("\n");
|
|
24033
25169
|
}
|
|
24034
|
-
async function
|
|
24035
|
-
const icmPlugin = agent.context.getPlugin("in_context_memory");
|
|
24036
|
-
const wmPlugin = agent.context.memory;
|
|
24037
|
-
if (!icmPlugin && !wmPlugin) {
|
|
24038
|
-
logger.warn("injectRoutineContext: No ICM or WM plugin available \u2014 skipping context injection");
|
|
24039
|
-
return;
|
|
24040
|
-
}
|
|
24041
|
-
const planOverview = buildPlanOverview(execution, definition, currentTask.id);
|
|
24042
|
-
if (icmPlugin) {
|
|
24043
|
-
icmPlugin.set("__routine_plan", "Routine plan overview with task statuses", planOverview, "high");
|
|
24044
|
-
}
|
|
25170
|
+
async function cleanupMemoryKeys(icmPlugin, wmPlugin, config) {
|
|
24045
25171
|
if (icmPlugin) {
|
|
24046
25172
|
for (const entry of icmPlugin.list()) {
|
|
24047
|
-
|
|
24048
|
-
|
|
24049
|
-
}
|
|
25173
|
+
const shouldDelete = config.icmPrefixes.some((p) => entry.key.startsWith(p)) || (config.icmExactKeys?.includes(entry.key) ?? false);
|
|
25174
|
+
if (shouldDelete) icmPlugin.delete(entry.key);
|
|
24050
25175
|
}
|
|
24051
25176
|
}
|
|
24052
25177
|
if (wmPlugin) {
|
|
24053
25178
|
const { entries: wmEntries } = await wmPlugin.query();
|
|
24054
25179
|
for (const entry of wmEntries) {
|
|
24055
|
-
if (
|
|
25180
|
+
if (config.wmPrefixes.some((p) => entry.key.startsWith(p))) {
|
|
24056
25181
|
await wmPlugin.delete(entry.key);
|
|
24057
25182
|
}
|
|
24058
25183
|
}
|
|
24059
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);
|
|
24060
25206
|
if (currentTask.dependsOn.length === 0) return;
|
|
24061
25207
|
const inContextDeps = [];
|
|
24062
25208
|
const workingMemoryDeps = [];
|
|
@@ -24065,7 +25211,7 @@ async function injectRoutineContext(agent, execution, definition, currentTask) {
|
|
|
24065
25211
|
if (!depTask?.result?.output) continue;
|
|
24066
25212
|
const output = typeof depTask.result.output === "string" ? depTask.result.output : JSON.stringify(depTask.result.output);
|
|
24067
25213
|
const tokens = estimateTokens(output);
|
|
24068
|
-
const depKey =
|
|
25214
|
+
const depKey = `${ROUTINE_KEYS.DEP_RESULT_PREFIX}${depId}`;
|
|
24069
25215
|
const depLabel = `Result from task "${depTask.name}"`;
|
|
24070
25216
|
if (tokens < 5e3 && icmPlugin) {
|
|
24071
25217
|
icmPlugin.set(depKey, depLabel, output, "high");
|
|
@@ -24087,27 +25233,12 @@ async function injectRoutineContext(agent, execution, definition, currentTask) {
|
|
|
24087
25233
|
if (workingMemoryDeps.length > 0) {
|
|
24088
25234
|
summaryParts.push(`In working memory (use memory_retrieve): ${workingMemoryDeps.join(", ")}`);
|
|
24089
25235
|
}
|
|
24090
|
-
icmPlugin.set(
|
|
25236
|
+
icmPlugin.set(ROUTINE_KEYS.DEPS, "Dependency results location guide", summaryParts.join("\n"), "high");
|
|
24091
25237
|
}
|
|
24092
25238
|
}
|
|
24093
25239
|
async function cleanupRoutineContext(agent) {
|
|
24094
|
-
const icmPlugin = agent
|
|
24095
|
-
|
|
24096
|
-
if (icmPlugin) {
|
|
24097
|
-
for (const entry of icmPlugin.list()) {
|
|
24098
|
-
if (entry.key.startsWith("__routine_") || entry.key.startsWith("__dep_result_")) {
|
|
24099
|
-
icmPlugin.delete(entry.key);
|
|
24100
|
-
}
|
|
24101
|
-
}
|
|
24102
|
-
}
|
|
24103
|
-
if (wmPlugin) {
|
|
24104
|
-
const { entries: wmEntries } = await wmPlugin.query();
|
|
24105
|
-
for (const entry of wmEntries) {
|
|
24106
|
-
if (entry.key.startsWith("__dep_result_") || entry.key.startsWith("findings/__dep_result_")) {
|
|
24107
|
-
await wmPlugin.delete(entry.key);
|
|
24108
|
-
}
|
|
24109
|
-
}
|
|
24110
|
-
}
|
|
25240
|
+
const { icmPlugin, wmPlugin } = getPlugins(agent);
|
|
25241
|
+
await cleanupMemoryKeys(icmPlugin, wmPlugin, FULL_CLEANUP_CONFIG);
|
|
24111
25242
|
}
|
|
24112
25243
|
async function validateTaskCompletion(agent, task, responseText, validationPromptBuilder) {
|
|
24113
25244
|
const hasExplicitValidation = task.validation?.skipReflection === false && task.validation?.completionCriteria && task.validation.completionCriteria.length > 0;
|
|
@@ -24156,11 +25287,13 @@ async function executeRoutine(options) {
|
|
|
24156
25287
|
onTaskFailed,
|
|
24157
25288
|
onTaskValidation,
|
|
24158
25289
|
hooks,
|
|
24159
|
-
prompts
|
|
25290
|
+
prompts,
|
|
25291
|
+
inputs: rawInputs
|
|
24160
25292
|
} = options;
|
|
24161
25293
|
if (!existingAgent && (!connector || !model)) {
|
|
24162
25294
|
throw new Error("executeRoutine requires either `agent` or both `connector` and `model`");
|
|
24163
25295
|
}
|
|
25296
|
+
const resolvedInputs = validateAndResolveInputs(definition.parameters, rawInputs);
|
|
24164
25297
|
const ownsAgent = !existingAgent;
|
|
24165
25298
|
const log = logger.child({ routine: definition.name });
|
|
24166
25299
|
const execution = createRoutineExecution(definition);
|
|
@@ -24245,7 +25378,7 @@ async function executeRoutine(options) {
|
|
|
24245
25378
|
execution.lastUpdatedAt = Date.now();
|
|
24246
25379
|
onTaskStarted?.(execution.plan.tasks[taskIndex], execution);
|
|
24247
25380
|
let taskCompleted = false;
|
|
24248
|
-
const maxTaskIterations = task.execution?.maxIterations ??
|
|
25381
|
+
const maxTaskIterations = task.execution?.maxIterations ?? 50;
|
|
24249
25382
|
const iterationLimiter = async (ctx) => {
|
|
24250
25383
|
if (ctx.iteration >= maxTaskIterations) {
|
|
24251
25384
|
agent.cancel(`Task "${task.name}" exceeded max iterations (${maxTaskIterations})`);
|
|
@@ -24253,85 +25386,115 @@ async function executeRoutine(options) {
|
|
|
24253
25386
|
return { shouldPause: false };
|
|
24254
25387
|
};
|
|
24255
25388
|
agent.registerHook("pause:check", iterationLimiter);
|
|
24256
|
-
|
|
24257
|
-
|
|
24258
|
-
|
|
24259
|
-
|
|
24260
|
-
|
|
24261
|
-
|
|
24262
|
-
|
|
24263
|
-
|
|
24264
|
-
|
|
24265
|
-
|
|
24266
|
-
|
|
24267
|
-
|
|
24268
|
-
|
|
24269
|
-
|
|
24270
|
-
|
|
24271
|
-
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "completed");
|
|
24272
|
-
execution.plan.tasks[taskIndex].result = {
|
|
24273
|
-
success: true,
|
|
24274
|
-
output: responseText,
|
|
24275
|
-
validationScore: validationResult.completionScore,
|
|
24276
|
-
validationExplanation: validationResult.explanation
|
|
24277
|
-
};
|
|
24278
|
-
taskCompleted = true;
|
|
24279
|
-
log.info(
|
|
24280
|
-
{ taskName: getTask().name, score: validationResult.completionScore },
|
|
24281
|
-
"Task completed"
|
|
24282
|
-
);
|
|
24283
|
-
execution.progress = getRoutineProgress(execution);
|
|
24284
|
-
execution.lastUpdatedAt = Date.now();
|
|
24285
|
-
onTaskComplete?.(execution.plan.tasks[taskIndex], execution);
|
|
24286
|
-
} else {
|
|
24287
|
-
log.warn(
|
|
24288
|
-
{
|
|
24289
|
-
taskName: getTask().name,
|
|
24290
|
-
score: validationResult.completionScore,
|
|
24291
|
-
attempt: getTask().attempts,
|
|
24292
|
-
maxAttempts: getTask().maxAttempts
|
|
24293
|
-
},
|
|
24294
|
-
"Task validation failed"
|
|
24295
|
-
);
|
|
24296
|
-
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 {
|
|
24297
25404
|
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "failed");
|
|
24298
|
-
execution.plan.tasks[taskIndex].result = {
|
|
24299
|
-
success: false,
|
|
24300
|
-
error: validationResult.explanation,
|
|
24301
|
-
validationScore: validationResult.completionScore,
|
|
24302
|
-
validationExplanation: validationResult.explanation
|
|
24303
|
-
};
|
|
24304
|
-
break;
|
|
25405
|
+
execution.plan.tasks[taskIndex].result = { success: false, error: cfResult.error };
|
|
24305
25406
|
}
|
|
24306
|
-
|
|
24307
|
-
|
|
24308
|
-
|
|
24309
|
-
const errorMessage = error.message;
|
|
24310
|
-
log.error({ taskName: getTask().name, error: errorMessage }, "Task execution error");
|
|
24311
|
-
if (getTask().attempts >= getTask().maxAttempts) {
|
|
25407
|
+
} catch (error) {
|
|
25408
|
+
const errorMessage = error.message;
|
|
25409
|
+
log.error({ taskName: getTask().name, error: errorMessage }, "Control flow error");
|
|
24312
25410
|
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "failed");
|
|
24313
|
-
execution.plan.tasks[taskIndex].result = {
|
|
24314
|
-
|
|
24315
|
-
|
|
24316
|
-
|
|
24317
|
-
|
|
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
|
+
}
|
|
24318
25478
|
}
|
|
24319
|
-
execution.plan.tasks[taskIndex] = updateTaskStatus(getTask(), "in_progress");
|
|
24320
25479
|
}
|
|
24321
|
-
|
|
24322
|
-
|
|
24323
|
-
execution.progress = getRoutineProgress(execution);
|
|
24324
|
-
execution.lastUpdatedAt = Date.now();
|
|
24325
|
-
onTaskFailed?.(execution.plan.tasks[taskIndex], execution);
|
|
24326
|
-
if (failureMode === "fail-fast") {
|
|
24327
|
-
execution.status = "failed";
|
|
24328
|
-
execution.error = `Task "${getTask().name}" failed after ${getTask().attempts} attempt(s)`;
|
|
24329
|
-
execution.completedAt = Date.now();
|
|
25480
|
+
if (!taskCompleted) {
|
|
25481
|
+
execution.progress = getRoutineProgress(execution);
|
|
24330
25482
|
execution.lastUpdatedAt = Date.now();
|
|
24331
|
-
|
|
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 {
|
|
24332
25496
|
}
|
|
24333
25497
|
}
|
|
24334
|
-
agent.unregisterHook("pause:check", iterationLimiter);
|
|
24335
25498
|
agent.clearConversation("task-boundary");
|
|
24336
25499
|
nextTasks = getNextExecutableTasks(execution.plan);
|
|
24337
25500
|
}
|
|
@@ -24359,16 +25522,22 @@ async function executeRoutine(options) {
|
|
|
24359
25522
|
} finally {
|
|
24360
25523
|
try {
|
|
24361
25524
|
await cleanupRoutineContext(agent);
|
|
24362
|
-
} catch {
|
|
25525
|
+
} catch (e) {
|
|
25526
|
+
log.debug({ error: e.message }, "Failed to clean up routine context");
|
|
24363
25527
|
}
|
|
24364
25528
|
for (const { name, hook } of registeredHooks) {
|
|
24365
25529
|
try {
|
|
24366
25530
|
agent.unregisterHook(name, hook);
|
|
24367
|
-
} catch {
|
|
25531
|
+
} catch (e) {
|
|
25532
|
+
log.debug({ hookName: name, error: e.message }, "Failed to unregister hook");
|
|
24368
25533
|
}
|
|
24369
25534
|
}
|
|
24370
25535
|
if (ownsAgent) {
|
|
24371
|
-
|
|
25536
|
+
try {
|
|
25537
|
+
agent.destroy();
|
|
25538
|
+
} catch (e) {
|
|
25539
|
+
log.debug({ error: e.message }, "Failed to destroy agent");
|
|
25540
|
+
}
|
|
24372
25541
|
}
|
|
24373
25542
|
}
|
|
24374
25543
|
}
|
|
@@ -31175,7 +32344,7 @@ var TextToSpeech = class _TextToSpeech {
|
|
|
31175
32344
|
*/
|
|
31176
32345
|
async toFile(text, filePath, options) {
|
|
31177
32346
|
const response = await this.synthesize(text, options);
|
|
31178
|
-
await
|
|
32347
|
+
await fs17.writeFile(filePath, response.audio);
|
|
31179
32348
|
}
|
|
31180
32349
|
// ======================== Introspection Methods ========================
|
|
31181
32350
|
/**
|
|
@@ -31523,7 +32692,7 @@ var SpeechToText = class _SpeechToText {
|
|
|
31523
32692
|
* @param options - Optional transcription parameters
|
|
31524
32693
|
*/
|
|
31525
32694
|
async transcribeFile(filePath, options) {
|
|
31526
|
-
const audio = await
|
|
32695
|
+
const audio = await fs17.readFile(filePath);
|
|
31527
32696
|
return this.transcribe(audio, options);
|
|
31528
32697
|
}
|
|
31529
32698
|
/**
|
|
@@ -38266,10 +39435,10 @@ var FileMediaStorage = class {
|
|
|
38266
39435
|
}
|
|
38267
39436
|
async save(data, metadata) {
|
|
38268
39437
|
const dir = metadata.userId ? path2.join(this.outputDir, metadata.userId) : this.outputDir;
|
|
38269
|
-
await
|
|
39438
|
+
await fs17.mkdir(dir, { recursive: true });
|
|
38270
39439
|
const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
|
|
38271
39440
|
const filePath = path2.join(dir, filename);
|
|
38272
|
-
await
|
|
39441
|
+
await fs17.writeFile(filePath, data);
|
|
38273
39442
|
const format = metadata.format.toLowerCase();
|
|
38274
39443
|
const mimeType = MIME_TYPES2[format] ?? "application/octet-stream";
|
|
38275
39444
|
return {
|
|
@@ -38280,7 +39449,7 @@ var FileMediaStorage = class {
|
|
|
38280
39449
|
}
|
|
38281
39450
|
async read(location) {
|
|
38282
39451
|
try {
|
|
38283
|
-
return await
|
|
39452
|
+
return await fs17.readFile(location);
|
|
38284
39453
|
} catch (err) {
|
|
38285
39454
|
if (err.code === "ENOENT") {
|
|
38286
39455
|
return null;
|
|
@@ -38290,7 +39459,7 @@ var FileMediaStorage = class {
|
|
|
38290
39459
|
}
|
|
38291
39460
|
async delete(location) {
|
|
38292
39461
|
try {
|
|
38293
|
-
await
|
|
39462
|
+
await fs17.unlink(location);
|
|
38294
39463
|
} catch (err) {
|
|
38295
39464
|
if (err.code === "ENOENT") {
|
|
38296
39465
|
return;
|
|
@@ -38300,7 +39469,7 @@ var FileMediaStorage = class {
|
|
|
38300
39469
|
}
|
|
38301
39470
|
async exists(location) {
|
|
38302
39471
|
try {
|
|
38303
|
-
await
|
|
39472
|
+
await fs17.access(location);
|
|
38304
39473
|
return true;
|
|
38305
39474
|
} catch {
|
|
38306
39475
|
return false;
|
|
@@ -38309,11 +39478,11 @@ var FileMediaStorage = class {
|
|
|
38309
39478
|
async list(options) {
|
|
38310
39479
|
await this.ensureDir();
|
|
38311
39480
|
let entries = [];
|
|
38312
|
-
const files = await
|
|
39481
|
+
const files = await fs17.readdir(this.outputDir);
|
|
38313
39482
|
for (const file of files) {
|
|
38314
39483
|
const filePath = path2.join(this.outputDir, file);
|
|
38315
39484
|
try {
|
|
38316
|
-
const stat6 = await
|
|
39485
|
+
const stat6 = await fs17.stat(filePath);
|
|
38317
39486
|
if (!stat6.isFile()) continue;
|
|
38318
39487
|
const ext = path2.extname(file).slice(1).toLowerCase();
|
|
38319
39488
|
const mimeType = MIME_TYPES2[ext] ?? "application/octet-stream";
|
|
@@ -38353,7 +39522,7 @@ var FileMediaStorage = class {
|
|
|
38353
39522
|
}
|
|
38354
39523
|
async ensureDir() {
|
|
38355
39524
|
if (!this.initialized) {
|
|
38356
|
-
await
|
|
39525
|
+
await fs17.mkdir(this.outputDir, { recursive: true });
|
|
38357
39526
|
this.initialized = true;
|
|
38358
39527
|
}
|
|
38359
39528
|
}
|
|
@@ -38888,6 +40057,42 @@ var StreamHelpers = class {
|
|
|
38888
40057
|
}
|
|
38889
40058
|
return chunks.join("");
|
|
38890
40059
|
}
|
|
40060
|
+
/**
|
|
40061
|
+
* Get only reasoning/thinking deltas from stream
|
|
40062
|
+
* Filters out all other event types
|
|
40063
|
+
*/
|
|
40064
|
+
static async *thinkingOnly(stream) {
|
|
40065
|
+
for await (const event of stream) {
|
|
40066
|
+
if (isReasoningDelta(event)) {
|
|
40067
|
+
yield event.delta;
|
|
40068
|
+
}
|
|
40069
|
+
}
|
|
40070
|
+
}
|
|
40071
|
+
/**
|
|
40072
|
+
* Get both text and thinking deltas from stream
|
|
40073
|
+
* Yields tagged objects so consumers can distinguish them
|
|
40074
|
+
*/
|
|
40075
|
+
static async *textAndThinking(stream) {
|
|
40076
|
+
for await (const event of stream) {
|
|
40077
|
+
if (isOutputTextDelta(event)) {
|
|
40078
|
+
yield { type: "text", delta: event.delta };
|
|
40079
|
+
} else if (isReasoningDelta(event)) {
|
|
40080
|
+
yield { type: "thinking", delta: event.delta };
|
|
40081
|
+
}
|
|
40082
|
+
}
|
|
40083
|
+
}
|
|
40084
|
+
/**
|
|
40085
|
+
* Accumulate all thinking/reasoning content from stream into a single string
|
|
40086
|
+
*/
|
|
40087
|
+
static async accumulateThinking(stream) {
|
|
40088
|
+
const chunks = [];
|
|
40089
|
+
for await (const event of stream) {
|
|
40090
|
+
if (isReasoningDelta(event)) {
|
|
40091
|
+
chunks.push(event.delta);
|
|
40092
|
+
}
|
|
40093
|
+
}
|
|
40094
|
+
return chunks.join("");
|
|
40095
|
+
}
|
|
38891
40096
|
/**
|
|
38892
40097
|
* Buffer stream events into batches
|
|
38893
40098
|
*/
|
|
@@ -38947,6 +40152,11 @@ var StreamHelpers = class {
|
|
|
38947
40152
|
case "response.output_text.delta" /* OUTPUT_TEXT_DELTA */:
|
|
38948
40153
|
state.accumulateTextDelta(event.item_id, event.delta);
|
|
38949
40154
|
break;
|
|
40155
|
+
case "response.reasoning.delta" /* REASONING_DELTA */:
|
|
40156
|
+
state.accumulateReasoningDelta(event.item_id, event.delta);
|
|
40157
|
+
break;
|
|
40158
|
+
case "response.reasoning.done" /* REASONING_DONE */:
|
|
40159
|
+
break;
|
|
38950
40160
|
case "response.tool_call.start" /* TOOL_CALL_START */:
|
|
38951
40161
|
state.startToolCall(event.tool_call_id, event.tool_name);
|
|
38952
40162
|
break;
|
|
@@ -38977,21 +40187,36 @@ var StreamHelpers = class {
|
|
|
38977
40187
|
*/
|
|
38978
40188
|
static reconstructLLMResponse(state) {
|
|
38979
40189
|
const output = [];
|
|
40190
|
+
const contentParts = [];
|
|
40191
|
+
let thinkingText;
|
|
40192
|
+
if (state.hasReasoning()) {
|
|
40193
|
+
const reasoning = state.getAllReasoning();
|
|
40194
|
+
if (reasoning) {
|
|
40195
|
+
thinkingText = reasoning;
|
|
40196
|
+
contentParts.push({
|
|
40197
|
+
type: "thinking" /* THINKING */,
|
|
40198
|
+
thinking: reasoning,
|
|
40199
|
+
persistInHistory: false
|
|
40200
|
+
// Vendor-agnostic default; caller can adjust
|
|
40201
|
+
});
|
|
40202
|
+
}
|
|
40203
|
+
}
|
|
38980
40204
|
if (state.hasText()) {
|
|
38981
40205
|
const textContent = state.getAllText();
|
|
38982
40206
|
if (textContent) {
|
|
38983
|
-
|
|
38984
|
-
type: "
|
|
38985
|
-
|
|
38986
|
-
content: [
|
|
38987
|
-
{
|
|
38988
|
-
type: "output_text" /* OUTPUT_TEXT */,
|
|
38989
|
-
text: textContent
|
|
38990
|
-
}
|
|
38991
|
-
]
|
|
40207
|
+
contentParts.push({
|
|
40208
|
+
type: "output_text" /* OUTPUT_TEXT */,
|
|
40209
|
+
text: textContent
|
|
38992
40210
|
});
|
|
38993
40211
|
}
|
|
38994
40212
|
}
|
|
40213
|
+
if (contentParts.length > 0) {
|
|
40214
|
+
output.push({
|
|
40215
|
+
type: "message",
|
|
40216
|
+
role: "assistant" /* ASSISTANT */,
|
|
40217
|
+
content: contentParts
|
|
40218
|
+
});
|
|
40219
|
+
}
|
|
38995
40220
|
const toolCalls = state.getCompletedToolCalls();
|
|
38996
40221
|
if (toolCalls.length > 0) {
|
|
38997
40222
|
const toolUseContent = toolCalls.map((tc) => ({
|
|
@@ -39020,6 +40245,7 @@ var StreamHelpers = class {
|
|
|
39020
40245
|
model: state.model,
|
|
39021
40246
|
output,
|
|
39022
40247
|
output_text: outputText,
|
|
40248
|
+
thinking: thinkingText,
|
|
39023
40249
|
usage: state.usage
|
|
39024
40250
|
};
|
|
39025
40251
|
}
|
|
@@ -39148,6 +40374,15 @@ var SERVICE_DEFINITIONS = [
|
|
|
39148
40374
|
baseURL: "https://api.telegram.org",
|
|
39149
40375
|
docsURL: "https://core.telegram.org/bots/api"
|
|
39150
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
|
+
},
|
|
39151
40386
|
// ============ Development & Project Management ============
|
|
39152
40387
|
{
|
|
39153
40388
|
id: "github",
|
|
@@ -39635,19 +40870,30 @@ var ConnectorTools = class {
|
|
|
39635
40870
|
*/
|
|
39636
40871
|
static for(connectorOrName, userId, options) {
|
|
39637
40872
|
const connector = this.resolveConnector(connectorOrName, options?.registry);
|
|
40873
|
+
const accountId = options?.accountId;
|
|
39638
40874
|
const tools = [];
|
|
40875
|
+
const namePrefix = accountId ? `${sanitizeToolName(connector.name)}_${sanitizeToolName(accountId)}` : sanitizeToolName(connector.name);
|
|
39639
40876
|
if (connector.baseURL) {
|
|
39640
|
-
|
|
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
|
+
}));
|
|
39641
40884
|
}
|
|
39642
40885
|
const serviceType = this.detectService(connector);
|
|
39643
40886
|
if (serviceType && this.factories.has(serviceType)) {
|
|
39644
40887
|
const factory = this.factories.get(serviceType);
|
|
39645
40888
|
const serviceTools = factory(connector, userId);
|
|
39646
40889
|
for (const tool of serviceTools) {
|
|
39647
|
-
tool.definition.function.name = `${
|
|
40890
|
+
tool.definition.function.name = `${namePrefix}_${tool.definition.function.name}`;
|
|
39648
40891
|
}
|
|
39649
40892
|
tools.push(...serviceTools);
|
|
39650
40893
|
}
|
|
40894
|
+
if (accountId) {
|
|
40895
|
+
return tools.map((tool) => this.bindAccountId(tool, accountId));
|
|
40896
|
+
}
|
|
39651
40897
|
return tools;
|
|
39652
40898
|
}
|
|
39653
40899
|
/**
|
|
@@ -39797,6 +41043,56 @@ var ConnectorTools = class {
|
|
|
39797
41043
|
}
|
|
39798
41044
|
return connectorOrName;
|
|
39799
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
|
+
}
|
|
39800
41096
|
static createGenericAPITool(connector, options) {
|
|
39801
41097
|
const toolName = options?.toolName ?? `${sanitizeToolName(connector.name)}_api`;
|
|
39802
41098
|
const userId = options?.userId;
|
|
@@ -39838,6 +41134,7 @@ var ConnectorTools = class {
|
|
|
39838
41134
|
},
|
|
39839
41135
|
execute: async (args, context) => {
|
|
39840
41136
|
const effectiveUserId = context?.userId ?? userId;
|
|
41137
|
+
const effectiveAccountId = context?.accountId;
|
|
39841
41138
|
let url2 = args.endpoint;
|
|
39842
41139
|
if (args.queryParams && Object.keys(args.queryParams).length > 0) {
|
|
39843
41140
|
const params = new URLSearchParams();
|
|
@@ -39870,7 +41167,8 @@ var ConnectorTools = class {
|
|
|
39870
41167
|
},
|
|
39871
41168
|
body: bodyStr
|
|
39872
41169
|
},
|
|
39873
|
-
effectiveUserId
|
|
41170
|
+
effectiveUserId,
|
|
41171
|
+
effectiveAccountId
|
|
39874
41172
|
);
|
|
39875
41173
|
const text = await response.text();
|
|
39876
41174
|
let data;
|
|
@@ -39931,8 +41229,8 @@ var FileStorage = class {
|
|
|
39931
41229
|
}
|
|
39932
41230
|
async ensureDirectory() {
|
|
39933
41231
|
try {
|
|
39934
|
-
await
|
|
39935
|
-
await
|
|
41232
|
+
await fs17.mkdir(this.directory, { recursive: true });
|
|
41233
|
+
await fs17.chmod(this.directory, 448);
|
|
39936
41234
|
} catch (error) {
|
|
39937
41235
|
}
|
|
39938
41236
|
}
|
|
@@ -39946,24 +41244,27 @@ var FileStorage = class {
|
|
|
39946
41244
|
async storeToken(key, token) {
|
|
39947
41245
|
await this.ensureDirectory();
|
|
39948
41246
|
const filePath = this.getFilePath(key);
|
|
39949
|
-
const
|
|
41247
|
+
const tokenWithKey = { ...token, _storageKey: key };
|
|
41248
|
+
const plaintext = JSON.stringify(tokenWithKey);
|
|
39950
41249
|
const encrypted = encrypt(plaintext, this.encryptionKey);
|
|
39951
|
-
await
|
|
39952
|
-
await
|
|
41250
|
+
await fs17.writeFile(filePath, encrypted, "utf8");
|
|
41251
|
+
await fs17.chmod(filePath, 384);
|
|
39953
41252
|
}
|
|
39954
41253
|
async getToken(key) {
|
|
39955
41254
|
const filePath = this.getFilePath(key);
|
|
39956
41255
|
try {
|
|
39957
|
-
const encrypted = await
|
|
41256
|
+
const encrypted = await fs17.readFile(filePath, "utf8");
|
|
39958
41257
|
const decrypted = decrypt(encrypted, this.encryptionKey);
|
|
39959
|
-
|
|
41258
|
+
const parsed = JSON.parse(decrypted);
|
|
41259
|
+
const { _storageKey, ...token } = parsed;
|
|
41260
|
+
return token;
|
|
39960
41261
|
} catch (error) {
|
|
39961
41262
|
if (error.code === "ENOENT") {
|
|
39962
41263
|
return null;
|
|
39963
41264
|
}
|
|
39964
41265
|
console.error("Failed to read/decrypt token file:", error);
|
|
39965
41266
|
try {
|
|
39966
|
-
await
|
|
41267
|
+
await fs17.unlink(filePath);
|
|
39967
41268
|
} catch {
|
|
39968
41269
|
}
|
|
39969
41270
|
return null;
|
|
@@ -39972,7 +41273,7 @@ var FileStorage = class {
|
|
|
39972
41273
|
async deleteToken(key) {
|
|
39973
41274
|
const filePath = this.getFilePath(key);
|
|
39974
41275
|
try {
|
|
39975
|
-
await
|
|
41276
|
+
await fs17.unlink(filePath);
|
|
39976
41277
|
} catch (error) {
|
|
39977
41278
|
if (error.code !== "ENOENT") {
|
|
39978
41279
|
throw error;
|
|
@@ -39982,18 +41283,44 @@ var FileStorage = class {
|
|
|
39982
41283
|
async hasToken(key) {
|
|
39983
41284
|
const filePath = this.getFilePath(key);
|
|
39984
41285
|
try {
|
|
39985
|
-
await
|
|
41286
|
+
await fs17.access(filePath);
|
|
39986
41287
|
return true;
|
|
39987
41288
|
} catch {
|
|
39988
41289
|
return false;
|
|
39989
41290
|
}
|
|
39990
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
|
+
}
|
|
39991
41318
|
/**
|
|
39992
41319
|
* List all token keys (for debugging)
|
|
39993
41320
|
*/
|
|
39994
41321
|
async listTokens() {
|
|
39995
41322
|
try {
|
|
39996
|
-
const files = await
|
|
41323
|
+
const files = await fs17.readdir(this.directory);
|
|
39997
41324
|
return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
|
|
39998
41325
|
} catch {
|
|
39999
41326
|
return [];
|
|
@@ -40004,10 +41331,10 @@ var FileStorage = class {
|
|
|
40004
41331
|
*/
|
|
40005
41332
|
async clearAll() {
|
|
40006
41333
|
try {
|
|
40007
|
-
const files = await
|
|
41334
|
+
const files = await fs17.readdir(this.directory);
|
|
40008
41335
|
const tokenFiles = files.filter((f) => f.endsWith(".token"));
|
|
40009
41336
|
await Promise.all(
|
|
40010
|
-
tokenFiles.map((f) =>
|
|
41337
|
+
tokenFiles.map((f) => fs17.unlink(path2.join(this.directory, f)).catch(() => {
|
|
40011
41338
|
}))
|
|
40012
41339
|
);
|
|
40013
41340
|
} catch {
|
|
@@ -40017,14 +41344,14 @@ var FileStorage = class {
|
|
|
40017
41344
|
|
|
40018
41345
|
// src/connectors/authenticatedFetch.ts
|
|
40019
41346
|
init_Connector();
|
|
40020
|
-
async function authenticatedFetch(url2, options, authProvider, userId) {
|
|
41347
|
+
async function authenticatedFetch(url2, options, authProvider, userId, accountId) {
|
|
40021
41348
|
const connector = Connector.get(authProvider);
|
|
40022
|
-
return connector.fetch(url2.toString(), options, userId);
|
|
41349
|
+
return connector.fetch(url2.toString(), options, userId, accountId);
|
|
40023
41350
|
}
|
|
40024
|
-
function createAuthenticatedFetch(authProvider, userId) {
|
|
41351
|
+
function createAuthenticatedFetch(authProvider, userId, accountId) {
|
|
40025
41352
|
const connector = Connector.get(authProvider);
|
|
40026
41353
|
return async (url2, options) => {
|
|
40027
|
-
return connector.fetch(url2.toString(), options, userId);
|
|
41354
|
+
return connector.fetch(url2.toString(), options, userId, accountId);
|
|
40028
41355
|
};
|
|
40029
41356
|
}
|
|
40030
41357
|
|
|
@@ -40455,14 +41782,14 @@ var FileConnectorStorage = class {
|
|
|
40455
41782
|
await this.ensureDirectory();
|
|
40456
41783
|
const filePath = this.getFilePath(name);
|
|
40457
41784
|
const json = JSON.stringify(stored, null, 2);
|
|
40458
|
-
await
|
|
40459
|
-
await
|
|
41785
|
+
await fs17.writeFile(filePath, json, "utf8");
|
|
41786
|
+
await fs17.chmod(filePath, 384);
|
|
40460
41787
|
await this.updateIndex(name, "add");
|
|
40461
41788
|
}
|
|
40462
41789
|
async get(name) {
|
|
40463
41790
|
const filePath = this.getFilePath(name);
|
|
40464
41791
|
try {
|
|
40465
|
-
const json = await
|
|
41792
|
+
const json = await fs17.readFile(filePath, "utf8");
|
|
40466
41793
|
return JSON.parse(json);
|
|
40467
41794
|
} catch (error) {
|
|
40468
41795
|
const err = error;
|
|
@@ -40475,7 +41802,7 @@ var FileConnectorStorage = class {
|
|
|
40475
41802
|
async delete(name) {
|
|
40476
41803
|
const filePath = this.getFilePath(name);
|
|
40477
41804
|
try {
|
|
40478
|
-
await
|
|
41805
|
+
await fs17.unlink(filePath);
|
|
40479
41806
|
await this.updateIndex(name, "remove");
|
|
40480
41807
|
return true;
|
|
40481
41808
|
} catch (error) {
|
|
@@ -40489,7 +41816,7 @@ var FileConnectorStorage = class {
|
|
|
40489
41816
|
async has(name) {
|
|
40490
41817
|
const filePath = this.getFilePath(name);
|
|
40491
41818
|
try {
|
|
40492
|
-
await
|
|
41819
|
+
await fs17.access(filePath);
|
|
40493
41820
|
return true;
|
|
40494
41821
|
} catch {
|
|
40495
41822
|
return false;
|
|
@@ -40515,13 +41842,13 @@ var FileConnectorStorage = class {
|
|
|
40515
41842
|
*/
|
|
40516
41843
|
async clear() {
|
|
40517
41844
|
try {
|
|
40518
|
-
const files = await
|
|
41845
|
+
const files = await fs17.readdir(this.directory);
|
|
40519
41846
|
const connectorFiles = files.filter(
|
|
40520
41847
|
(f) => f.endsWith(".connector.json") || f === "_index.json"
|
|
40521
41848
|
);
|
|
40522
41849
|
await Promise.all(
|
|
40523
41850
|
connectorFiles.map(
|
|
40524
|
-
(f) =>
|
|
41851
|
+
(f) => fs17.unlink(path2.join(this.directory, f)).catch(() => {
|
|
40525
41852
|
})
|
|
40526
41853
|
)
|
|
40527
41854
|
);
|
|
@@ -40548,8 +41875,8 @@ var FileConnectorStorage = class {
|
|
|
40548
41875
|
async ensureDirectory() {
|
|
40549
41876
|
if (this.initialized) return;
|
|
40550
41877
|
try {
|
|
40551
|
-
await
|
|
40552
|
-
await
|
|
41878
|
+
await fs17.mkdir(this.directory, { recursive: true });
|
|
41879
|
+
await fs17.chmod(this.directory, 448);
|
|
40553
41880
|
this.initialized = true;
|
|
40554
41881
|
} catch {
|
|
40555
41882
|
this.initialized = true;
|
|
@@ -40560,7 +41887,7 @@ var FileConnectorStorage = class {
|
|
|
40560
41887
|
*/
|
|
40561
41888
|
async loadIndex() {
|
|
40562
41889
|
try {
|
|
40563
|
-
const json = await
|
|
41890
|
+
const json = await fs17.readFile(this.indexPath, "utf8");
|
|
40564
41891
|
return JSON.parse(json);
|
|
40565
41892
|
} catch {
|
|
40566
41893
|
return { connectors: {} };
|
|
@@ -40578,8 +41905,8 @@ var FileConnectorStorage = class {
|
|
|
40578
41905
|
delete index.connectors[hash];
|
|
40579
41906
|
}
|
|
40580
41907
|
const json = JSON.stringify(index, null, 2);
|
|
40581
|
-
await
|
|
40582
|
-
await
|
|
41908
|
+
await fs17.writeFile(this.indexPath, json, "utf8");
|
|
41909
|
+
await fs17.chmod(this.indexPath, 384);
|
|
40583
41910
|
}
|
|
40584
41911
|
};
|
|
40585
41912
|
|
|
@@ -40802,14 +42129,15 @@ var microsoftTemplate = {
|
|
|
40802
42129
|
name: "OAuth (Delegated Permissions)",
|
|
40803
42130
|
type: "oauth",
|
|
40804
42131
|
flow: "authorization_code",
|
|
40805
|
-
description: "User signs in with Microsoft account. Best for accessing user data (mail, calendar, files)",
|
|
40806
|
-
requiredFields: ["clientId", "
|
|
40807
|
-
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"],
|
|
40808
42135
|
defaults: {
|
|
40809
42136
|
type: "oauth",
|
|
40810
42137
|
flow: "authorization_code",
|
|
40811
42138
|
authorizationUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize",
|
|
40812
|
-
tokenUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token"
|
|
42139
|
+
tokenUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token",
|
|
42140
|
+
usePKCE: true
|
|
40813
42141
|
},
|
|
40814
42142
|
scopes: [
|
|
40815
42143
|
"User.Read",
|
|
@@ -40895,14 +42223,15 @@ var googleTemplate = {
|
|
|
40895
42223
|
name: "OAuth (User Consent)",
|
|
40896
42224
|
type: "oauth",
|
|
40897
42225
|
flow: "authorization_code",
|
|
40898
|
-
description: "User logs in with Google account. Best for accessing user data (Drive, Gmail, Calendar)",
|
|
40899
|
-
requiredFields: ["clientId", "
|
|
40900
|
-
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"],
|
|
40901
42229
|
defaults: {
|
|
40902
42230
|
type: "oauth",
|
|
40903
42231
|
flow: "authorization_code",
|
|
40904
42232
|
authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
40905
|
-
tokenUrl: "https://oauth2.googleapis.com/token"
|
|
42233
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
42234
|
+
usePKCE: true
|
|
40906
42235
|
},
|
|
40907
42236
|
scopes: [
|
|
40908
42237
|
"https://www.googleapis.com/auth/drive",
|
|
@@ -40981,14 +42310,15 @@ var slackTemplate = {
|
|
|
40981
42310
|
name: "OAuth (User Token)",
|
|
40982
42311
|
type: "oauth",
|
|
40983
42312
|
flow: "authorization_code",
|
|
40984
|
-
description: "Distributed app - users authorize via Slack OAuth",
|
|
40985
|
-
requiredFields: ["clientId", "
|
|
40986
|
-
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"],
|
|
40987
42316
|
defaults: {
|
|
40988
42317
|
type: "oauth",
|
|
40989
42318
|
flow: "authorization_code",
|
|
40990
42319
|
authorizationUrl: "https://slack.com/oauth/v2/authorize",
|
|
40991
|
-
tokenUrl: "https://slack.com/api/oauth.v2.access"
|
|
42320
|
+
tokenUrl: "https://slack.com/api/oauth.v2.access",
|
|
42321
|
+
usePKCE: true
|
|
40992
42322
|
},
|
|
40993
42323
|
scopes: ["chat:write", "channels:read", "users:read", "im:write", "groups:read", "files:read", "files:write", "reactions:read", "reactions:write", "team:read"],
|
|
40994
42324
|
scopeDescriptions: {
|
|
@@ -41034,14 +42364,15 @@ var discordTemplate = {
|
|
|
41034
42364
|
name: "OAuth (User Token)",
|
|
41035
42365
|
type: "oauth",
|
|
41036
42366
|
flow: "authorization_code",
|
|
41037
|
-
description: "OAuth2 for user authorization - users grant permissions to your app",
|
|
41038
|
-
requiredFields: ["clientId", "
|
|
41039
|
-
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"],
|
|
41040
42370
|
defaults: {
|
|
41041
42371
|
type: "oauth",
|
|
41042
42372
|
flow: "authorization_code",
|
|
41043
42373
|
authorizationUrl: "https://discord.com/api/oauth2/authorize",
|
|
41044
|
-
tokenUrl: "https://discord.com/api/oauth2/token"
|
|
42374
|
+
tokenUrl: "https://discord.com/api/oauth2/token",
|
|
42375
|
+
usePKCE: true
|
|
41045
42376
|
},
|
|
41046
42377
|
scopes: ["identify", "email", "guilds", "guilds.members.read", "messages.read", "bot", "connections"],
|
|
41047
42378
|
scopeDescriptions: {
|
|
@@ -41083,6 +42414,92 @@ var telegramTemplate = {
|
|
|
41083
42414
|
]
|
|
41084
42415
|
};
|
|
41085
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
|
+
|
|
41086
42503
|
// src/connectors/vendors/templates/github.ts
|
|
41087
42504
|
var githubTemplate = {
|
|
41088
42505
|
id: "github",
|
|
@@ -41110,14 +42527,15 @@ var githubTemplate = {
|
|
|
41110
42527
|
name: "OAuth App (User Authorization)",
|
|
41111
42528
|
type: "oauth",
|
|
41112
42529
|
flow: "authorization_code",
|
|
41113
|
-
description: "User logs in via GitHub and grants permissions to your app",
|
|
41114
|
-
requiredFields: ["clientId", "
|
|
41115
|
-
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"],
|
|
41116
42533
|
defaults: {
|
|
41117
42534
|
type: "oauth",
|
|
41118
42535
|
flow: "authorization_code",
|
|
41119
42536
|
authorizationUrl: "https://github.com/login/oauth/authorize",
|
|
41120
|
-
tokenUrl: "https://github.com/login/oauth/access_token"
|
|
42537
|
+
tokenUrl: "https://github.com/login/oauth/access_token",
|
|
42538
|
+
usePKCE: true
|
|
41121
42539
|
},
|
|
41122
42540
|
scopes: ["repo", "read:user", "user:email", "read:org", "workflow", "gist", "notifications", "delete_repo", "admin:org"],
|
|
41123
42541
|
scopeDescriptions: {
|
|
@@ -41176,14 +42594,15 @@ var gitlabTemplate = {
|
|
|
41176
42594
|
name: "OAuth (User Authorization)",
|
|
41177
42595
|
type: "oauth",
|
|
41178
42596
|
flow: "authorization_code",
|
|
41179
|
-
description: "OAuth2 application for user authorization",
|
|
41180
|
-
requiredFields: ["clientId", "
|
|
41181
|
-
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"],
|
|
41182
42600
|
defaults: {
|
|
41183
42601
|
type: "oauth",
|
|
41184
42602
|
flow: "authorization_code",
|
|
41185
42603
|
authorizationUrl: "https://gitlab.com/oauth/authorize",
|
|
41186
|
-
tokenUrl: "https://gitlab.com/oauth/token"
|
|
42604
|
+
tokenUrl: "https://gitlab.com/oauth/token",
|
|
42605
|
+
usePKCE: true
|
|
41187
42606
|
},
|
|
41188
42607
|
scopes: ["api", "read_user", "read_repository", "write_repository"],
|
|
41189
42608
|
scopeDescriptions: {
|
|
@@ -41224,14 +42643,15 @@ var jiraTemplate = {
|
|
|
41224
42643
|
name: "OAuth 2.0 (3LO)",
|
|
41225
42644
|
type: "oauth",
|
|
41226
42645
|
flow: "authorization_code",
|
|
41227
|
-
description: "Three-legged OAuth for user authorization. Create app at developer.atlassian.com",
|
|
41228
|
-
requiredFields: ["clientId", "
|
|
41229
|
-
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"],
|
|
41230
42649
|
defaults: {
|
|
41231
42650
|
type: "oauth",
|
|
41232
42651
|
flow: "authorization_code",
|
|
41233
42652
|
authorizationUrl: "https://auth.atlassian.com/authorize",
|
|
41234
|
-
tokenUrl: "https://auth.atlassian.com/oauth/token"
|
|
42653
|
+
tokenUrl: "https://auth.atlassian.com/oauth/token",
|
|
42654
|
+
usePKCE: true
|
|
41235
42655
|
},
|
|
41236
42656
|
scopes: ["read:jira-work", "write:jira-work", "read:jira-user", "manage:jira-project", "manage:jira-configuration"],
|
|
41237
42657
|
scopeDescriptions: {
|
|
@@ -41271,14 +42691,15 @@ var confluenceTemplate = {
|
|
|
41271
42691
|
name: "OAuth 2.0 (3LO)",
|
|
41272
42692
|
type: "oauth",
|
|
41273
42693
|
flow: "authorization_code",
|
|
41274
|
-
description: "Three-legged OAuth for user authorization",
|
|
41275
|
-
requiredFields: ["clientId", "
|
|
41276
|
-
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"],
|
|
41277
42697
|
defaults: {
|
|
41278
42698
|
type: "oauth",
|
|
41279
42699
|
flow: "authorization_code",
|
|
41280
42700
|
authorizationUrl: "https://auth.atlassian.com/authorize",
|
|
41281
|
-
tokenUrl: "https://auth.atlassian.com/oauth/token"
|
|
42701
|
+
tokenUrl: "https://auth.atlassian.com/oauth/token",
|
|
42702
|
+
usePKCE: true
|
|
41282
42703
|
},
|
|
41283
42704
|
scopes: ["read:confluence-content.all", "write:confluence-content", "read:confluence-space.summary", "write:confluence-space", "read:confluence-user"],
|
|
41284
42705
|
scopeDescriptions: {
|
|
@@ -41317,14 +42738,15 @@ var bitbucketTemplate = {
|
|
|
41317
42738
|
name: "OAuth Consumer",
|
|
41318
42739
|
type: "oauth",
|
|
41319
42740
|
flow: "authorization_code",
|
|
41320
|
-
description: "OAuth consumer for user authorization. Create at Workspace Settings > OAuth consumers",
|
|
41321
|
-
requiredFields: ["clientId", "
|
|
41322
|
-
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"],
|
|
41323
42744
|
defaults: {
|
|
41324
42745
|
type: "oauth",
|
|
41325
42746
|
flow: "authorization_code",
|
|
41326
42747
|
authorizationUrl: "https://bitbucket.org/site/oauth2/authorize",
|
|
41327
|
-
tokenUrl: "https://bitbucket.org/site/oauth2/access_token"
|
|
42748
|
+
tokenUrl: "https://bitbucket.org/site/oauth2/access_token",
|
|
42749
|
+
usePKCE: true
|
|
41328
42750
|
},
|
|
41329
42751
|
scopes: ["repository", "repository:write", "pullrequest", "pullrequest:write", "account", "pipeline", "wiki"],
|
|
41330
42752
|
scopeDescriptions: {
|
|
@@ -41366,14 +42788,15 @@ var trelloTemplate = {
|
|
|
41366
42788
|
name: "OAuth 1.0a",
|
|
41367
42789
|
type: "oauth",
|
|
41368
42790
|
flow: "authorization_code",
|
|
41369
|
-
description: "OAuth 1.0a for user authorization (legacy)",
|
|
41370
|
-
requiredFields: ["clientId", "
|
|
41371
|
-
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"],
|
|
41372
42794
|
defaults: {
|
|
41373
42795
|
type: "oauth",
|
|
41374
42796
|
flow: "authorization_code",
|
|
41375
42797
|
authorizationUrl: "https://trello.com/1/authorize",
|
|
41376
|
-
tokenUrl: "https://trello.com/1/OAuthGetAccessToken"
|
|
42798
|
+
tokenUrl: "https://trello.com/1/OAuthGetAccessToken",
|
|
42799
|
+
usePKCE: true
|
|
41377
42800
|
},
|
|
41378
42801
|
scopes: ["read", "write", "account"],
|
|
41379
42802
|
scopeDescriptions: {
|
|
@@ -41413,14 +42836,15 @@ var linearTemplate = {
|
|
|
41413
42836
|
name: "OAuth (User Authorization)",
|
|
41414
42837
|
type: "oauth",
|
|
41415
42838
|
flow: "authorization_code",
|
|
41416
|
-
description: "OAuth application for user authorization. Create at Settings > API > OAuth applications",
|
|
41417
|
-
requiredFields: ["clientId", "
|
|
41418
|
-
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"],
|
|
41419
42842
|
defaults: {
|
|
41420
42843
|
type: "oauth",
|
|
41421
42844
|
flow: "authorization_code",
|
|
41422
42845
|
authorizationUrl: "https://linear.app/oauth/authorize",
|
|
41423
|
-
tokenUrl: "https://api.linear.app/oauth/token"
|
|
42846
|
+
tokenUrl: "https://api.linear.app/oauth/token",
|
|
42847
|
+
usePKCE: true
|
|
41424
42848
|
},
|
|
41425
42849
|
scopes: ["read", "write", "issues:create", "comments:create"]
|
|
41426
42850
|
}
|
|
@@ -41454,14 +42878,15 @@ var asanaTemplate = {
|
|
|
41454
42878
|
name: "OAuth (User Authorization)",
|
|
41455
42879
|
type: "oauth",
|
|
41456
42880
|
flow: "authorization_code",
|
|
41457
|
-
description: "OAuth application for user authorization. Create at developer console",
|
|
41458
|
-
requiredFields: ["clientId", "
|
|
41459
|
-
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"],
|
|
41460
42884
|
defaults: {
|
|
41461
42885
|
type: "oauth",
|
|
41462
42886
|
flow: "authorization_code",
|
|
41463
42887
|
authorizationUrl: "https://app.asana.com/-/oauth_authorize",
|
|
41464
|
-
tokenUrl: "https://app.asana.com/-/oauth_token"
|
|
42888
|
+
tokenUrl: "https://app.asana.com/-/oauth_token",
|
|
42889
|
+
usePKCE: true
|
|
41465
42890
|
},
|
|
41466
42891
|
scopes: ["default"]
|
|
41467
42892
|
}
|
|
@@ -41495,14 +42920,15 @@ var notionTemplate = {
|
|
|
41495
42920
|
name: "Public Integration (OAuth)",
|
|
41496
42921
|
type: "oauth",
|
|
41497
42922
|
flow: "authorization_code",
|
|
41498
|
-
description: "Public integration for multi-workspace access",
|
|
41499
|
-
requiredFields: ["clientId", "
|
|
41500
|
-
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"],
|
|
41501
42926
|
defaults: {
|
|
41502
42927
|
type: "oauth",
|
|
41503
42928
|
flow: "authorization_code",
|
|
41504
42929
|
authorizationUrl: "https://api.notion.com/v1/oauth/authorize",
|
|
41505
|
-
tokenUrl: "https://api.notion.com/v1/oauth/token"
|
|
42930
|
+
tokenUrl: "https://api.notion.com/v1/oauth/token",
|
|
42931
|
+
usePKCE: true
|
|
41506
42932
|
}
|
|
41507
42933
|
}
|
|
41508
42934
|
]
|
|
@@ -41535,9 +42961,9 @@ var airtableTemplate = {
|
|
|
41535
42961
|
name: "OAuth (User Authorization)",
|
|
41536
42962
|
type: "oauth",
|
|
41537
42963
|
flow: "authorization_code",
|
|
41538
|
-
description: "OAuth integration for multi-user access. Register at airtable.com/create/oauth",
|
|
41539
|
-
requiredFields: ["clientId", "
|
|
41540
|
-
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"],
|
|
41541
42967
|
defaults: {
|
|
41542
42968
|
type: "oauth",
|
|
41543
42969
|
flow: "authorization_code",
|
|
@@ -41566,14 +42992,15 @@ var salesforceTemplate = {
|
|
|
41566
42992
|
name: "OAuth (User Authorization)",
|
|
41567
42993
|
type: "oauth",
|
|
41568
42994
|
flow: "authorization_code",
|
|
41569
|
-
description: "User logs in via Salesforce. Create Connected App in Setup",
|
|
41570
|
-
requiredFields: ["clientId", "
|
|
41571
|
-
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"],
|
|
41572
42998
|
defaults: {
|
|
41573
42999
|
type: "oauth",
|
|
41574
43000
|
flow: "authorization_code",
|
|
41575
43001
|
authorizationUrl: "https://login.salesforce.com/services/oauth2/authorize",
|
|
41576
|
-
tokenUrl: "https://login.salesforce.com/services/oauth2/token"
|
|
43002
|
+
tokenUrl: "https://login.salesforce.com/services/oauth2/token",
|
|
43003
|
+
usePKCE: true
|
|
41577
43004
|
},
|
|
41578
43005
|
scopes: ["api", "refresh_token", "offline_access", "chatter_api", "wave_api", "full"],
|
|
41579
43006
|
scopeDescriptions: {
|
|
@@ -41629,14 +43056,15 @@ var hubspotTemplate = {
|
|
|
41629
43056
|
name: "OAuth (User Authorization)",
|
|
41630
43057
|
type: "oauth",
|
|
41631
43058
|
flow: "authorization_code",
|
|
41632
|
-
description: "Public app OAuth for multi-portal access. Create app at developers.hubspot.com",
|
|
41633
|
-
requiredFields: ["clientId", "
|
|
41634
|
-
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"],
|
|
41635
43062
|
defaults: {
|
|
41636
43063
|
type: "oauth",
|
|
41637
43064
|
flow: "authorization_code",
|
|
41638
43065
|
authorizationUrl: "https://app.hubspot.com/oauth/authorize",
|
|
41639
|
-
tokenUrl: "https://api.hubapi.com/oauth/v1/token"
|
|
43066
|
+
tokenUrl: "https://api.hubapi.com/oauth/v1/token",
|
|
43067
|
+
usePKCE: true
|
|
41640
43068
|
},
|
|
41641
43069
|
scopes: [
|
|
41642
43070
|
"crm.objects.contacts.read",
|
|
@@ -41658,6 +43086,22 @@ var hubspotTemplate = {
|
|
|
41658
43086
|
"tickets": "Read and write support tickets",
|
|
41659
43087
|
"e-commerce": "Access e-commerce data (products, line items)"
|
|
41660
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
|
+
}
|
|
41661
43105
|
}
|
|
41662
43106
|
]
|
|
41663
43107
|
};
|
|
@@ -41689,14 +43133,15 @@ var pipedriveTemplate = {
|
|
|
41689
43133
|
name: "OAuth (App Authorization)",
|
|
41690
43134
|
type: "oauth",
|
|
41691
43135
|
flow: "authorization_code",
|
|
41692
|
-
description: "OAuth app for marketplace distribution. Create at developers.pipedrive.com",
|
|
41693
|
-
requiredFields: ["clientId", "
|
|
41694
|
-
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"],
|
|
41695
43139
|
defaults: {
|
|
41696
43140
|
type: "oauth",
|
|
41697
43141
|
flow: "authorization_code",
|
|
41698
43142
|
authorizationUrl: "https://oauth.pipedrive.com/oauth/authorize",
|
|
41699
|
-
tokenUrl: "https://oauth.pipedrive.com/oauth/token"
|
|
43143
|
+
tokenUrl: "https://oauth.pipedrive.com/oauth/token",
|
|
43144
|
+
usePKCE: true
|
|
41700
43145
|
}
|
|
41701
43146
|
}
|
|
41702
43147
|
]
|
|
@@ -41729,14 +43174,15 @@ var stripeTemplate = {
|
|
|
41729
43174
|
name: "OAuth (Stripe Connect)",
|
|
41730
43175
|
type: "oauth",
|
|
41731
43176
|
flow: "authorization_code",
|
|
41732
|
-
description: "Stripe Connect for marketplace platforms. Requires Connect setup in dashboard",
|
|
41733
|
-
requiredFields: ["clientId", "
|
|
41734
|
-
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"],
|
|
41735
43180
|
defaults: {
|
|
41736
43181
|
type: "oauth",
|
|
41737
43182
|
flow: "authorization_code",
|
|
41738
43183
|
authorizationUrl: "https://connect.stripe.com/oauth/authorize",
|
|
41739
|
-
tokenUrl: "https://connect.stripe.com/oauth/token"
|
|
43184
|
+
tokenUrl: "https://connect.stripe.com/oauth/token",
|
|
43185
|
+
usePKCE: true
|
|
41740
43186
|
},
|
|
41741
43187
|
scopes: ["read_write"]
|
|
41742
43188
|
}
|
|
@@ -41786,14 +43232,15 @@ var quickbooksTemplate = {
|
|
|
41786
43232
|
name: "OAuth (User Authorization)",
|
|
41787
43233
|
type: "oauth",
|
|
41788
43234
|
flow: "authorization_code",
|
|
41789
|
-
description: "Standard OAuth 2.0 flow for accessing QuickBooks on behalf of a user. Create an app at developer.intuit.com",
|
|
41790
|
-
requiredFields: ["clientId", "
|
|
41791
|
-
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"],
|
|
41792
43238
|
defaults: {
|
|
41793
43239
|
type: "oauth",
|
|
41794
43240
|
flow: "authorization_code",
|
|
41795
43241
|
authorizationUrl: "https://appcenter.intuit.com/connect/oauth2",
|
|
41796
|
-
tokenUrl: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
|
|
43242
|
+
tokenUrl: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
|
|
43243
|
+
usePKCE: true
|
|
41797
43244
|
},
|
|
41798
43245
|
scopes: ["com.intuit.quickbooks.accounting", "com.intuit.quickbooks.payment"]
|
|
41799
43246
|
}
|
|
@@ -41828,14 +43275,15 @@ var rampTemplate = {
|
|
|
41828
43275
|
name: "OAuth (User Authorization)",
|
|
41829
43276
|
type: "oauth",
|
|
41830
43277
|
flow: "authorization_code",
|
|
41831
|
-
description: "OAuth 2.0 authorization code flow for accessing Ramp on behalf of a user",
|
|
41832
|
-
requiredFields: ["clientId", "
|
|
41833
|
-
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"],
|
|
41834
43281
|
defaults: {
|
|
41835
43282
|
type: "oauth",
|
|
41836
43283
|
flow: "authorization_code",
|
|
41837
43284
|
authorizationUrl: "https://app.ramp.com/v1/authorize",
|
|
41838
|
-
tokenUrl: "https://api.ramp.com/developer/v1/token"
|
|
43285
|
+
tokenUrl: "https://api.ramp.com/developer/v1/token",
|
|
43286
|
+
usePKCE: true
|
|
41839
43287
|
},
|
|
41840
43288
|
scopes: [
|
|
41841
43289
|
"transactions:read",
|
|
@@ -41892,9 +43340,9 @@ var dropboxTemplate = {
|
|
|
41892
43340
|
name: "OAuth (User Authorization)",
|
|
41893
43341
|
type: "oauth",
|
|
41894
43342
|
flow: "authorization_code",
|
|
41895
|
-
description: "OAuth app for user authorization. Create app at dropbox.com/developers/apps",
|
|
41896
|
-
requiredFields: ["clientId", "
|
|
41897
|
-
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"],
|
|
41898
43346
|
defaults: {
|
|
41899
43347
|
type: "oauth",
|
|
41900
43348
|
flow: "authorization_code",
|
|
@@ -41931,14 +43379,15 @@ var boxTemplate = {
|
|
|
41931
43379
|
name: "OAuth (User Authorization)",
|
|
41932
43380
|
type: "oauth",
|
|
41933
43381
|
flow: "authorization_code",
|
|
41934
|
-
description: "OAuth 2.0 for user authorization. Create app at developer.box.com/console",
|
|
41935
|
-
requiredFields: ["clientId", "
|
|
41936
|
-
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"],
|
|
41937
43385
|
defaults: {
|
|
41938
43386
|
type: "oauth",
|
|
41939
43387
|
flow: "authorization_code",
|
|
41940
43388
|
authorizationUrl: "https://account.box.com/api/oauth2/authorize",
|
|
41941
|
-
tokenUrl: "https://api.box.com/oauth2/token"
|
|
43389
|
+
tokenUrl: "https://api.box.com/oauth2/token",
|
|
43390
|
+
usePKCE: true
|
|
41942
43391
|
},
|
|
41943
43392
|
scopes: ["root_readwrite", "manage_users", "manage_groups", "manage_enterprise"],
|
|
41944
43393
|
scopeDescriptions: {
|
|
@@ -42016,13 +43465,15 @@ var mailchimpTemplate = {
|
|
|
42016
43465
|
name: "OAuth (User Authorization)",
|
|
42017
43466
|
type: "oauth",
|
|
42018
43467
|
flow: "authorization_code",
|
|
42019
|
-
description: "OAuth for multi-account access. Register app at mailchimp.com/developer",
|
|
42020
|
-
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"],
|
|
42021
43471
|
defaults: {
|
|
42022
43472
|
type: "oauth",
|
|
42023
43473
|
flow: "authorization_code",
|
|
42024
43474
|
authorizationUrl: "https://login.mailchimp.com/oauth2/authorize",
|
|
42025
|
-
tokenUrl: "https://login.mailchimp.com/oauth2/token"
|
|
43475
|
+
tokenUrl: "https://login.mailchimp.com/oauth2/token",
|
|
43476
|
+
usePKCE: true
|
|
42026
43477
|
}
|
|
42027
43478
|
}
|
|
42028
43479
|
]
|
|
@@ -42114,14 +43565,15 @@ var pagerdutyTemplate = {
|
|
|
42114
43565
|
name: "OAuth (App Authorization)",
|
|
42115
43566
|
type: "oauth",
|
|
42116
43567
|
flow: "authorization_code",
|
|
42117
|
-
description: "OAuth app for multi-account access. Register at developer.pagerduty.com",
|
|
42118
|
-
requiredFields: ["clientId", "
|
|
42119
|
-
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"],
|
|
42120
43571
|
defaults: {
|
|
42121
43572
|
type: "oauth",
|
|
42122
43573
|
flow: "authorization_code",
|
|
42123
43574
|
authorizationUrl: "https://app.pagerduty.com/oauth/authorize",
|
|
42124
|
-
tokenUrl: "https://app.pagerduty.com/oauth/token"
|
|
43575
|
+
tokenUrl: "https://app.pagerduty.com/oauth/token",
|
|
43576
|
+
usePKCE: true
|
|
42125
43577
|
},
|
|
42126
43578
|
scopes: ["read", "write"],
|
|
42127
43579
|
scopeDescriptions: {
|
|
@@ -42157,14 +43609,15 @@ var sentryTemplate = {
|
|
|
42157
43609
|
name: "OAuth (Integration)",
|
|
42158
43610
|
type: "oauth",
|
|
42159
43611
|
flow: "authorization_code",
|
|
42160
|
-
description: "OAuth integration. Create at Organization Settings > Integrations",
|
|
42161
|
-
requiredFields: ["clientId", "
|
|
42162
|
-
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"],
|
|
42163
43615
|
defaults: {
|
|
42164
43616
|
type: "oauth",
|
|
42165
43617
|
flow: "authorization_code",
|
|
42166
43618
|
authorizationUrl: "https://sentry.io/oauth/authorize/",
|
|
42167
|
-
tokenUrl: "https://sentry.io/oauth/token/"
|
|
43619
|
+
tokenUrl: "https://sentry.io/oauth/token/",
|
|
43620
|
+
usePKCE: true
|
|
42168
43621
|
},
|
|
42169
43622
|
scopes: ["project:read", "project:write", "event:read", "org:read", "member:read"],
|
|
42170
43623
|
scopeDescriptions: {
|
|
@@ -42361,14 +43814,15 @@ var zendeskTemplate = {
|
|
|
42361
43814
|
name: "OAuth (User Authorization)",
|
|
42362
43815
|
type: "oauth",
|
|
42363
43816
|
flow: "authorization_code",
|
|
42364
|
-
description: "OAuth client for user authorization. Create at Admin > Channels > API > OAuth Clients",
|
|
42365
|
-
requiredFields: ["clientId", "
|
|
42366
|
-
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"],
|
|
42367
43820
|
defaults: {
|
|
42368
43821
|
type: "oauth",
|
|
42369
43822
|
flow: "authorization_code",
|
|
42370
43823
|
authorizationUrl: "https://{subdomain}.zendesk.com/oauth/authorizations/new",
|
|
42371
|
-
tokenUrl: "https://{subdomain}.zendesk.com/oauth/tokens"
|
|
43824
|
+
tokenUrl: "https://{subdomain}.zendesk.com/oauth/tokens",
|
|
43825
|
+
usePKCE: true
|
|
42372
43826
|
},
|
|
42373
43827
|
scopes: ["read", "write", "tickets:read", "tickets:write"],
|
|
42374
43828
|
scopeDescriptions: {
|
|
@@ -42406,13 +43860,15 @@ var intercomTemplate = {
|
|
|
42406
43860
|
name: "OAuth (App Installation)",
|
|
42407
43861
|
type: "oauth",
|
|
42408
43862
|
flow: "authorization_code",
|
|
42409
|
-
description: "OAuth for Intercom app marketplace distribution",
|
|
42410
|
-
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"],
|
|
42411
43866
|
defaults: {
|
|
42412
43867
|
type: "oauth",
|
|
42413
43868
|
flow: "authorization_code",
|
|
42414
43869
|
authorizationUrl: "https://app.intercom.com/oauth",
|
|
42415
|
-
tokenUrl: "https://api.intercom.io/auth/eagle/token"
|
|
43870
|
+
tokenUrl: "https://api.intercom.io/auth/eagle/token",
|
|
43871
|
+
usePKCE: true
|
|
42416
43872
|
}
|
|
42417
43873
|
}
|
|
42418
43874
|
]
|
|
@@ -42445,14 +43901,15 @@ var shopifyTemplate = {
|
|
|
42445
43901
|
name: "OAuth (Public/Custom App)",
|
|
42446
43902
|
type: "oauth",
|
|
42447
43903
|
flow: "authorization_code",
|
|
42448
|
-
description: "OAuth for public apps or per-store custom apps. Create at partners.shopify.com",
|
|
42449
|
-
requiredFields: ["clientId", "
|
|
42450
|
-
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"],
|
|
42451
43907
|
defaults: {
|
|
42452
43908
|
type: "oauth",
|
|
42453
43909
|
flow: "authorization_code",
|
|
42454
43910
|
authorizationUrl: "https://{subdomain}.myshopify.com/admin/oauth/authorize",
|
|
42455
|
-
tokenUrl: "https://{subdomain}.myshopify.com/admin/oauth/access_token"
|
|
43911
|
+
tokenUrl: "https://{subdomain}.myshopify.com/admin/oauth/access_token",
|
|
43912
|
+
usePKCE: true
|
|
42456
43913
|
},
|
|
42457
43914
|
scopes: ["read_products", "write_products", "read_orders", "write_orders", "read_customers", "write_customers", "read_inventory", "write_inventory", "read_fulfillments", "write_fulfillments"],
|
|
42458
43915
|
scopeDescriptions: {
|
|
@@ -42480,6 +43937,7 @@ var allVendorTemplates = [
|
|
|
42480
43937
|
slackTemplate,
|
|
42481
43938
|
discordTemplate,
|
|
42482
43939
|
telegramTemplate,
|
|
43940
|
+
twitterTemplate,
|
|
42483
43941
|
// Development
|
|
42484
43942
|
githubTemplate,
|
|
42485
43943
|
gitlabTemplate,
|
|
@@ -42539,6 +43997,7 @@ var VENDOR_ICON_MAP = {
|
|
|
42539
43997
|
discord: "discord",
|
|
42540
43998
|
slack: "slack",
|
|
42541
43999
|
telegram: "telegram",
|
|
44000
|
+
twitter: "x",
|
|
42542
44001
|
"microsoft-teams": "microsoftteams",
|
|
42543
44002
|
// CRM
|
|
42544
44003
|
salesforce: "salesforce",
|
|
@@ -42603,6 +44062,7 @@ var FALLBACK_PLACEHOLDERS = {
|
|
|
42603
44062
|
// Communication (trademark removed)
|
|
42604
44063
|
slack: { color: "#4A154B", letter: "S" },
|
|
42605
44064
|
"microsoft-teams": { color: "#6264A7", letter: "T" },
|
|
44065
|
+
twitter: { color: "#000000", letter: "X" },
|
|
42606
44066
|
// CRM (trademark removed)
|
|
42607
44067
|
salesforce: { color: "#00A1E0", letter: "S" },
|
|
42608
44068
|
pipedrive: { color: "#1A1F26", letter: "P" },
|
|
@@ -45772,21 +47232,53 @@ registerWebTools();
|
|
|
45772
47232
|
init_Connector();
|
|
45773
47233
|
var DEFAULT_TIMEOUT = 1e4;
|
|
45774
47234
|
var DEFAULT_MAX_TIMEOUT = 3e4;
|
|
45775
|
-
function formatConnectorEntry(c) {
|
|
47235
|
+
function formatConnectorEntry(c, accountId) {
|
|
45776
47236
|
const parts = [];
|
|
45777
47237
|
const serviceOrVendor = c.serviceType ?? c.vendor ?? void 0;
|
|
45778
47238
|
if (serviceOrVendor) parts.push(`Service: ${serviceOrVendor}`);
|
|
47239
|
+
if (accountId) parts.push(`Account: "${accountId}"`);
|
|
45779
47240
|
if (c.config.description) parts.push(c.config.description);
|
|
45780
47241
|
if (c.baseURL) parts.push(`URL: ${c.baseURL}`);
|
|
47242
|
+
const label = accountId ? `"${c.name}" account "${accountId}"` : `"${c.name}"`;
|
|
45781
47243
|
const details = parts.map((p) => ` ${p}`).join("\n");
|
|
45782
|
-
return ` \u2022
|
|
47244
|
+
return ` \u2022 ${label} (${c.displayName})
|
|
45783
47245
|
${details}`;
|
|
45784
47246
|
}
|
|
45785
|
-
function
|
|
47247
|
+
function buildIdentityList(context) {
|
|
47248
|
+
const identities = context?.identities;
|
|
45786
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
|
+
}
|
|
45787
47262
|
const connectors = registry.listAll();
|
|
45788
|
-
|
|
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);
|
|
45789
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
|
+
` : "";
|
|
45790
47282
|
return `Execute JavaScript code in a secure sandbox with authenticated API access to external services.
|
|
45791
47283
|
|
|
45792
47284
|
Use this tool when you need to:
|
|
@@ -45797,7 +47289,7 @@ Use this tool when you need to:
|
|
|
45797
47289
|
|
|
45798
47290
|
SANDBOX API:
|
|
45799
47291
|
|
|
45800
|
-
1. authenticatedFetch(url, options, connectorName)
|
|
47292
|
+
1. authenticatedFetch(url, options, connectorName${showAccountId ? ", accountId?" : ""})
|
|
45801
47293
|
Makes authenticated HTTP requests using the connector's credentials.
|
|
45802
47294
|
The current user's identity (userId) is automatically included \u2014 no need to pass it.
|
|
45803
47295
|
Auth headers are added automatically \u2014 DO NOT set Authorization header manually.
|
|
@@ -45808,7 +47300,7 @@ SANDBOX API:
|
|
|
45808
47300
|
- Relative: "/user/repos" (resolved against connector's base URL)
|
|
45809
47301
|
\u2022 options: Standard fetch options { method, headers, body }
|
|
45810
47302
|
- For POST/PUT: set body to JSON.stringify(data) and headers to { 'Content-Type': 'application/json' }
|
|
45811
|
-
\u2022 connectorName: Name of a registered connector (see list below)
|
|
47303
|
+
\u2022 connectorName: Name of a registered connector (see list below)${accountIdParam}
|
|
45812
47304
|
|
|
45813
47305
|
Returns: Promise<Response>
|
|
45814
47306
|
\u2022 response.ok \u2014 true if status 200-299
|
|
@@ -45844,7 +47336,7 @@ const resp = await authenticatedFetch('/chat.postMessage', {
|
|
|
45844
47336
|
body: JSON.stringify({ channel: '#general', text: 'Hello!' })
|
|
45845
47337
|
}, 'slack');
|
|
45846
47338
|
output = await resp.json();
|
|
45847
|
-
|
|
47339
|
+
${accountIdExamples}
|
|
45848
47340
|
// Data processing (no API needed)
|
|
45849
47341
|
const items = input.data;
|
|
45850
47342
|
output = items.filter(i => i.score > 0.8).sort((a, b) => b.score - a.score);
|
|
@@ -45932,9 +47424,10 @@ async function executeInVM(code, input, timeout, logs, userId, registry) {
|
|
|
45932
47424
|
},
|
|
45933
47425
|
// Authenticated fetch — userId auto-injected from ToolContext.
|
|
45934
47426
|
// Only connectors visible in the scoped registry are accessible.
|
|
45935
|
-
|
|
47427
|
+
// Optional 4th param accountId for multi-account OAuth identities.
|
|
47428
|
+
authenticatedFetch: (url2, options, connectorName, accountId) => {
|
|
45936
47429
|
registry.get(connectorName);
|
|
45937
|
-
return authenticatedFetch(url2, options, connectorName, userId);
|
|
47430
|
+
return authenticatedFetch(url2, options, connectorName, userId, accountId);
|
|
45938
47431
|
},
|
|
45939
47432
|
// Standard fetch (no auth)
|
|
45940
47433
|
fetch: globalThis.fetch,
|
|
@@ -46622,7 +48115,8 @@ async function githubFetch(connector, endpoint, options) {
|
|
|
46622
48115
|
headers,
|
|
46623
48116
|
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
46624
48117
|
},
|
|
46625
|
-
options?.userId
|
|
48118
|
+
options?.userId,
|
|
48119
|
+
options?.accountId
|
|
46626
48120
|
);
|
|
46627
48121
|
const text = await response.text();
|
|
46628
48122
|
let data;
|
|
@@ -46704,6 +48198,7 @@ EXAMPLES:
|
|
|
46704
48198
|
},
|
|
46705
48199
|
execute: async (args, context) => {
|
|
46706
48200
|
const effectiveUserId = context?.userId ?? userId;
|
|
48201
|
+
const effectiveAccountId = context?.accountId;
|
|
46707
48202
|
const resolved = resolveRepository(args.repository, connector);
|
|
46708
48203
|
if (!resolved.success) {
|
|
46709
48204
|
return { success: false, error: resolved.error };
|
|
@@ -46715,7 +48210,7 @@ EXAMPLES:
|
|
|
46715
48210
|
const repoInfo = await githubFetch(
|
|
46716
48211
|
connector,
|
|
46717
48212
|
`/repos/${owner}/${repo}`,
|
|
46718
|
-
{ userId: effectiveUserId }
|
|
48213
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
46719
48214
|
);
|
|
46720
48215
|
ref = repoInfo.default_branch;
|
|
46721
48216
|
}
|
|
@@ -46815,6 +48310,7 @@ EXAMPLES:
|
|
|
46815
48310
|
},
|
|
46816
48311
|
execute: async (args, context) => {
|
|
46817
48312
|
const effectiveUserId = context?.userId ?? userId;
|
|
48313
|
+
const effectiveAccountId = context?.accountId;
|
|
46818
48314
|
const resolved = resolveRepository(args.repository, connector);
|
|
46819
48315
|
if (!resolved.success) {
|
|
46820
48316
|
return { success: false, error: resolved.error };
|
|
@@ -46832,6 +48328,7 @@ EXAMPLES:
|
|
|
46832
48328
|
`/search/code`,
|
|
46833
48329
|
{
|
|
46834
48330
|
userId: effectiveUserId,
|
|
48331
|
+
accountId: effectiveAccountId,
|
|
46835
48332
|
// Request text-match fragments
|
|
46836
48333
|
accept: "application/vnd.github.text-match+json",
|
|
46837
48334
|
queryParams: { q, per_page: perPage }
|
|
@@ -46920,6 +48417,7 @@ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (
|
|
|
46920
48417
|
},
|
|
46921
48418
|
execute: async (args, context) => {
|
|
46922
48419
|
const effectiveUserId = context?.userId ?? userId;
|
|
48420
|
+
const effectiveAccountId = context?.accountId;
|
|
46923
48421
|
const resolved = resolveRepository(args.repository, connector);
|
|
46924
48422
|
if (!resolved.success) {
|
|
46925
48423
|
return { success: false, error: resolved.error };
|
|
@@ -46933,7 +48431,7 @@ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (
|
|
|
46933
48431
|
const contentResp = await githubFetch(
|
|
46934
48432
|
connector,
|
|
46935
48433
|
`/repos/${owner}/${repo}/contents/${args.path}${refParam}`,
|
|
46936
|
-
{ userId: effectiveUserId }
|
|
48434
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
46937
48435
|
);
|
|
46938
48436
|
if (contentResp.type !== "file") {
|
|
46939
48437
|
return {
|
|
@@ -46950,7 +48448,7 @@ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (
|
|
|
46950
48448
|
const blob = await githubFetch(
|
|
46951
48449
|
connector,
|
|
46952
48450
|
contentResp.git_url,
|
|
46953
|
-
{ userId: effectiveUserId }
|
|
48451
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
46954
48452
|
);
|
|
46955
48453
|
fileContent = Buffer.from(blob.content, "base64").toString("utf-8");
|
|
46956
48454
|
fileSize = blob.size;
|
|
@@ -47039,6 +48537,7 @@ EXAMPLES:
|
|
|
47039
48537
|
},
|
|
47040
48538
|
execute: async (args, context) => {
|
|
47041
48539
|
const effectiveUserId = context?.userId ?? userId;
|
|
48540
|
+
const effectiveAccountId = context?.accountId;
|
|
47042
48541
|
const resolved = resolveRepository(args.repository, connector);
|
|
47043
48542
|
if (!resolved.success) {
|
|
47044
48543
|
return { success: false, error: resolved.error };
|
|
@@ -47048,7 +48547,7 @@ EXAMPLES:
|
|
|
47048
48547
|
const pr = await githubFetch(
|
|
47049
48548
|
connector,
|
|
47050
48549
|
`/repos/${owner}/${repo}/pulls/${args.pull_number}`,
|
|
47051
|
-
{ userId: effectiveUserId }
|
|
48550
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
47052
48551
|
);
|
|
47053
48552
|
return {
|
|
47054
48553
|
success: true,
|
|
@@ -47126,6 +48625,7 @@ NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent f
|
|
|
47126
48625
|
},
|
|
47127
48626
|
execute: async (args, context) => {
|
|
47128
48627
|
const effectiveUserId = context?.userId ?? userId;
|
|
48628
|
+
const effectiveAccountId = context?.accountId;
|
|
47129
48629
|
const resolved = resolveRepository(args.repository, connector);
|
|
47130
48630
|
if (!resolved.success) {
|
|
47131
48631
|
return { success: false, error: resolved.error };
|
|
@@ -47137,6 +48637,7 @@ NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent f
|
|
|
47137
48637
|
`/repos/${owner}/${repo}/pulls/${args.pull_number}/files`,
|
|
47138
48638
|
{
|
|
47139
48639
|
userId: effectiveUserId,
|
|
48640
|
+
accountId: effectiveAccountId,
|
|
47140
48641
|
queryParams: { per_page: 100 }
|
|
47141
48642
|
}
|
|
47142
48643
|
);
|
|
@@ -47209,6 +48710,7 @@ EXAMPLES:
|
|
|
47209
48710
|
},
|
|
47210
48711
|
execute: async (args, context) => {
|
|
47211
48712
|
const effectiveUserId = context?.userId ?? userId;
|
|
48713
|
+
const effectiveAccountId = context?.accountId;
|
|
47212
48714
|
const resolved = resolveRepository(args.repository, connector);
|
|
47213
48715
|
if (!resolved.success) {
|
|
47214
48716
|
return { success: false, error: resolved.error };
|
|
@@ -47216,7 +48718,7 @@ EXAMPLES:
|
|
|
47216
48718
|
const { owner, repo } = resolved.repo;
|
|
47217
48719
|
try {
|
|
47218
48720
|
const basePath = `/repos/${owner}/${repo}`;
|
|
47219
|
-
const queryOpts = { userId: effectiveUserId, queryParams: { per_page: 100 } };
|
|
48721
|
+
const queryOpts = { userId: effectiveUserId, accountId: effectiveAccountId, queryParams: { per_page: 100 } };
|
|
47220
48722
|
const [reviewComments, reviews, issueComments] = await Promise.all([
|
|
47221
48723
|
githubFetch(
|
|
47222
48724
|
connector,
|
|
@@ -47345,6 +48847,7 @@ EXAMPLES:
|
|
|
47345
48847
|
},
|
|
47346
48848
|
execute: async (args, context) => {
|
|
47347
48849
|
const effectiveUserId = context?.userId ?? userId;
|
|
48850
|
+
const effectiveAccountId = context?.accountId;
|
|
47348
48851
|
const resolved = resolveRepository(args.repository, connector);
|
|
47349
48852
|
if (!resolved.success) {
|
|
47350
48853
|
return { success: false, error: resolved.error };
|
|
@@ -47357,6 +48860,7 @@ EXAMPLES:
|
|
|
47357
48860
|
{
|
|
47358
48861
|
method: "POST",
|
|
47359
48862
|
userId: effectiveUserId,
|
|
48863
|
+
accountId: effectiveAccountId,
|
|
47360
48864
|
body: {
|
|
47361
48865
|
title: args.title,
|
|
47362
48866
|
body: args.body,
|
|
@@ -47448,7 +48952,8 @@ async function microsoftFetch(connector, endpoint, options) {
|
|
|
47448
48952
|
headers,
|
|
47449
48953
|
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
47450
48954
|
},
|
|
47451
|
-
options?.userId
|
|
48955
|
+
options?.userId,
|
|
48956
|
+
options?.accountId
|
|
47452
48957
|
);
|
|
47453
48958
|
const text = await response.text();
|
|
47454
48959
|
if (!response.ok) {
|
|
@@ -47501,7 +49006,7 @@ function isTeamsMeetingUrl(input) {
|
|
|
47501
49006
|
return false;
|
|
47502
49007
|
}
|
|
47503
49008
|
}
|
|
47504
|
-
async function resolveMeetingId(connector, input, prefix, effectiveUserId) {
|
|
49009
|
+
async function resolveMeetingId(connector, input, prefix, effectiveUserId, effectiveAccountId) {
|
|
47505
49010
|
if (!input || input.trim().length === 0) {
|
|
47506
49011
|
throw new Error("Meeting ID cannot be empty");
|
|
47507
49012
|
}
|
|
@@ -47514,6 +49019,7 @@ async function resolveMeetingId(connector, input, prefix, effectiveUserId) {
|
|
|
47514
49019
|
`${prefix}/onlineMeetings`,
|
|
47515
49020
|
{
|
|
47516
49021
|
userId: effectiveUserId,
|
|
49022
|
+
accountId: effectiveAccountId,
|
|
47517
49023
|
queryParams: { "$filter": `JoinWebUrl eq '${trimmed}'` }
|
|
47518
49024
|
}
|
|
47519
49025
|
);
|
|
@@ -47592,13 +49098,14 @@ EXAMPLES:
|
|
|
47592
49098
|
},
|
|
47593
49099
|
execute: async (args, context) => {
|
|
47594
49100
|
const effectiveUserId = context?.userId ?? userId;
|
|
49101
|
+
const effectiveAccountId = context?.accountId;
|
|
47595
49102
|
try {
|
|
47596
49103
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
47597
49104
|
if (args.replyToMessageId) {
|
|
47598
49105
|
const replyDraft = await microsoftFetch(
|
|
47599
49106
|
connector,
|
|
47600
49107
|
`${prefix}/messages/${args.replyToMessageId}/createReply`,
|
|
47601
|
-
{ method: "POST", userId: effectiveUserId, body: {} }
|
|
49108
|
+
{ method: "POST", userId: effectiveUserId, accountId: effectiveAccountId, body: {} }
|
|
47602
49109
|
);
|
|
47603
49110
|
const updated = await microsoftFetch(
|
|
47604
49111
|
connector,
|
|
@@ -47606,6 +49113,7 @@ EXAMPLES:
|
|
|
47606
49113
|
{
|
|
47607
49114
|
method: "PATCH",
|
|
47608
49115
|
userId: effectiveUserId,
|
|
49116
|
+
accountId: effectiveAccountId,
|
|
47609
49117
|
body: {
|
|
47610
49118
|
subject: args.subject,
|
|
47611
49119
|
body: { contentType: "HTML", content: args.body },
|
|
@@ -47626,6 +49134,7 @@ EXAMPLES:
|
|
|
47626
49134
|
{
|
|
47627
49135
|
method: "POST",
|
|
47628
49136
|
userId: effectiveUserId,
|
|
49137
|
+
accountId: effectiveAccountId,
|
|
47629
49138
|
body: {
|
|
47630
49139
|
isDraft: true,
|
|
47631
49140
|
subject: args.subject,
|
|
@@ -47714,6 +49223,7 @@ EXAMPLES:
|
|
|
47714
49223
|
},
|
|
47715
49224
|
execute: async (args, context) => {
|
|
47716
49225
|
const effectiveUserId = context?.userId ?? userId;
|
|
49226
|
+
const effectiveAccountId = context?.accountId;
|
|
47717
49227
|
try {
|
|
47718
49228
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
47719
49229
|
if (args.replyToMessageId) {
|
|
@@ -47723,6 +49233,7 @@ EXAMPLES:
|
|
|
47723
49233
|
{
|
|
47724
49234
|
method: "POST",
|
|
47725
49235
|
userId: effectiveUserId,
|
|
49236
|
+
accountId: effectiveAccountId,
|
|
47726
49237
|
body: {
|
|
47727
49238
|
message: {
|
|
47728
49239
|
toRecipients: formatRecipients(args.to),
|
|
@@ -47739,6 +49250,7 @@ EXAMPLES:
|
|
|
47739
49250
|
{
|
|
47740
49251
|
method: "POST",
|
|
47741
49252
|
userId: effectiveUserId,
|
|
49253
|
+
accountId: effectiveAccountId,
|
|
47742
49254
|
body: {
|
|
47743
49255
|
message: {
|
|
47744
49256
|
subject: args.subject,
|
|
@@ -47838,6 +49350,7 @@ EXAMPLES:
|
|
|
47838
49350
|
},
|
|
47839
49351
|
execute: async (args, context) => {
|
|
47840
49352
|
const effectiveUserId = context?.userId ?? userId;
|
|
49353
|
+
const effectiveAccountId = context?.accountId;
|
|
47841
49354
|
try {
|
|
47842
49355
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
47843
49356
|
const tz = args.timeZone ?? "UTC";
|
|
@@ -47860,7 +49373,7 @@ EXAMPLES:
|
|
|
47860
49373
|
const event = await microsoftFetch(
|
|
47861
49374
|
connector,
|
|
47862
49375
|
`${prefix}/events`,
|
|
47863
|
-
{ method: "POST", userId: effectiveUserId, body: eventBody }
|
|
49376
|
+
{ method: "POST", userId: effectiveUserId, accountId: effectiveAccountId, body: eventBody }
|
|
47864
49377
|
);
|
|
47865
49378
|
return {
|
|
47866
49379
|
success: true,
|
|
@@ -47964,6 +49477,7 @@ EXAMPLES:
|
|
|
47964
49477
|
},
|
|
47965
49478
|
execute: async (args, context) => {
|
|
47966
49479
|
const effectiveUserId = context?.userId ?? userId;
|
|
49480
|
+
const effectiveAccountId = context?.accountId;
|
|
47967
49481
|
try {
|
|
47968
49482
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
47969
49483
|
const tz = args.timeZone ?? "UTC";
|
|
@@ -47987,7 +49501,7 @@ EXAMPLES:
|
|
|
47987
49501
|
const event = await microsoftFetch(
|
|
47988
49502
|
connector,
|
|
47989
49503
|
`${prefix}/events/${args.eventId}`,
|
|
47990
|
-
{ method: "PATCH", userId: effectiveUserId, body: patchBody }
|
|
49504
|
+
{ method: "PATCH", userId: effectiveUserId, accountId: effectiveAccountId, body: patchBody }
|
|
47991
49505
|
);
|
|
47992
49506
|
return {
|
|
47993
49507
|
success: true,
|
|
@@ -48060,14 +49574,15 @@ EXAMPLES:
|
|
|
48060
49574
|
},
|
|
48061
49575
|
execute: async (args, context) => {
|
|
48062
49576
|
const effectiveUserId = context?.userId ?? userId;
|
|
49577
|
+
const effectiveAccountId = context?.accountId;
|
|
48063
49578
|
try {
|
|
48064
49579
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48065
|
-
const resolved = await resolveMeetingId(connector, args.meetingId, prefix, effectiveUserId);
|
|
49580
|
+
const resolved = await resolveMeetingId(connector, args.meetingId, prefix, effectiveUserId, effectiveAccountId);
|
|
48066
49581
|
const meetingId = resolved.meetingId;
|
|
48067
49582
|
const transcriptList = await microsoftFetch(
|
|
48068
49583
|
connector,
|
|
48069
49584
|
`${prefix}/onlineMeetings/${meetingId}/transcripts`,
|
|
48070
|
-
{ userId: effectiveUserId }
|
|
49585
|
+
{ userId: effectiveUserId, accountId: effectiveAccountId }
|
|
48071
49586
|
);
|
|
48072
49587
|
if (!transcriptList.value || transcriptList.value.length === 0) {
|
|
48073
49588
|
return {
|
|
@@ -48080,7 +49595,8 @@ EXAMPLES:
|
|
|
48080
49595
|
const response = await connector.fetch(
|
|
48081
49596
|
contentUrl + "?$format=text/vtt",
|
|
48082
49597
|
{ method: "GET", headers: { "Accept": "text/vtt" } },
|
|
48083
|
-
effectiveUserId
|
|
49598
|
+
effectiveUserId,
|
|
49599
|
+
effectiveAccountId
|
|
48084
49600
|
);
|
|
48085
49601
|
if (!response.ok) {
|
|
48086
49602
|
const errorText = await response.text();
|
|
@@ -48172,6 +49688,7 @@ EXAMPLES:
|
|
|
48172
49688
|
},
|
|
48173
49689
|
execute: async (args, context) => {
|
|
48174
49690
|
const effectiveUserId = context?.userId ?? userId;
|
|
49691
|
+
const effectiveAccountId = context?.accountId;
|
|
48175
49692
|
try {
|
|
48176
49693
|
const prefix = getUserPathPrefix(connector, args.targetUser);
|
|
48177
49694
|
const tz = args.timeZone ?? "UTC";
|
|
@@ -48181,6 +49698,7 @@ EXAMPLES:
|
|
|
48181
49698
|
{
|
|
48182
49699
|
method: "POST",
|
|
48183
49700
|
userId: effectiveUserId,
|
|
49701
|
+
accountId: effectiveAccountId,
|
|
48184
49702
|
body: {
|
|
48185
49703
|
attendees: formatAttendees(args.attendees),
|
|
48186
49704
|
timeConstraint: {
|
|
@@ -49109,27 +50627,42 @@ var customToolDelete = createCustomToolDelete();
|
|
|
49109
50627
|
|
|
49110
50628
|
// src/tools/custom-tools/sandboxDescription.ts
|
|
49111
50629
|
init_Connector();
|
|
49112
|
-
function formatConnectorEntry2(c) {
|
|
50630
|
+
function formatConnectorEntry2(c, accountId) {
|
|
49113
50631
|
const parts = [];
|
|
49114
50632
|
const serviceOrVendor = c.serviceType ?? c.vendor ?? void 0;
|
|
49115
50633
|
if (serviceOrVendor) parts.push(`Service: ${serviceOrVendor}`);
|
|
50634
|
+
if (accountId) parts.push(`Account: "${accountId}"`);
|
|
49116
50635
|
if (c.config.description) parts.push(c.config.description);
|
|
49117
50636
|
if (c.baseURL) parts.push(`URL: ${c.baseURL}`);
|
|
50637
|
+
const label = accountId ? `"${c.name}" account "${accountId}"` : `"${c.name}"`;
|
|
49118
50638
|
const details = parts.map((p) => ` ${p}`).join("\n");
|
|
49119
|
-
return ` \u2022
|
|
50639
|
+
return ` \u2022 ${label} (${c.displayName})
|
|
49120
50640
|
${details}`;
|
|
49121
50641
|
}
|
|
49122
50642
|
function buildConnectorList(context) {
|
|
50643
|
+
const identities = context?.identities;
|
|
49123
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
|
+
}
|
|
49124
50657
|
const connectors = registry.listAll();
|
|
49125
50658
|
if (connectors.length === 0) {
|
|
49126
50659
|
return " No connectors registered.";
|
|
49127
50660
|
}
|
|
49128
|
-
return connectors.map(formatConnectorEntry2).join("\n\n");
|
|
50661
|
+
return connectors.map((c) => formatConnectorEntry2(c)).join("\n\n");
|
|
49129
50662
|
}
|
|
49130
50663
|
var SANDBOX_API_REFERENCE = `SANDBOX API (available inside custom tool code):
|
|
49131
50664
|
|
|
49132
|
-
1. authenticatedFetch(url, options, connectorName)
|
|
50665
|
+
1. authenticatedFetch(url, options, connectorName, accountId?)
|
|
49133
50666
|
Makes authenticated HTTP requests using the connector's credentials.
|
|
49134
50667
|
Auth headers are added automatically \u2014 DO NOT set Authorization header manually.
|
|
49135
50668
|
|
|
@@ -49140,6 +50673,7 @@ var SANDBOX_API_REFERENCE = `SANDBOX API (available inside custom tool code):
|
|
|
49140
50673
|
\u2022 options: Standard fetch options { method, headers, body }
|
|
49141
50674
|
- For POST/PUT: set body to JSON.stringify(data) and headers to { 'Content-Type': 'application/json' }
|
|
49142
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')
|
|
49143
50677
|
|
|
49144
50678
|
Returns: Promise<Response>
|
|
49145
50679
|
\u2022 response.ok \u2014 true if status 200-299
|
|
@@ -50223,6 +51757,6 @@ REMEMBER: Keep it conversational, ask one question at a time, and only output th
|
|
|
50223
51757
|
}
|
|
50224
51758
|
};
|
|
50225
51759
|
|
|
50226
|
-
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, 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, 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 };
|
|
50227
51761
|
//# sourceMappingURL=index.js.map
|
|
50228
51762
|
//# sourceMappingURL=index.js.map
|