@everworker/oneringai 0.2.1 → 0.2.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/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var crypto2 = require('crypto');
4
4
  var jose = require('jose');
5
- var fs16 = require('fs');
5
+ var fs17 = require('fs');
6
6
  var eventemitter3 = require('eventemitter3');
7
7
  var path2 = require('path');
8
8
  var TurndownService = require('turndown');
@@ -17,7 +17,7 @@ var z = require('zod/v4');
17
17
  var spawn = require('cross-spawn');
18
18
  var process2 = require('process');
19
19
  var stream = require('stream');
20
- var fs15 = require('fs/promises');
20
+ var fs16 = require('fs/promises');
21
21
  var simpleIcons = require('simple-icons');
22
22
  var child_process = require('child_process');
23
23
  var util = require('util');
@@ -45,7 +45,7 @@ function _interopNamespace(e) {
45
45
  }
46
46
 
47
47
  var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
48
- var fs16__namespace = /*#__PURE__*/_interopNamespace(fs16);
48
+ var fs17__namespace = /*#__PURE__*/_interopNamespace(fs17);
49
49
  var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
50
50
  var TurndownService__default = /*#__PURE__*/_interopDefault(TurndownService);
51
51
  var os2__namespace = /*#__PURE__*/_interopNamespace(os2);
@@ -55,7 +55,7 @@ var z4mini__namespace = /*#__PURE__*/_interopNamespace(z4mini);
55
55
  var z__namespace = /*#__PURE__*/_interopNamespace(z);
56
56
  var spawn__default = /*#__PURE__*/_interopDefault(spawn);
57
57
  var process2__default = /*#__PURE__*/_interopDefault(process2);
58
- var fs15__namespace = /*#__PURE__*/_interopNamespace(fs15);
58
+ var fs16__namespace = /*#__PURE__*/_interopNamespace(fs16);
59
59
  var simpleIcons__namespace = /*#__PURE__*/_interopNamespace(simpleIcons);
60
60
  var vm__namespace = /*#__PURE__*/_interopNamespace(vm);
61
61
 
@@ -340,6 +340,10 @@ var init_pkce = __esm({
340
340
  });
341
341
 
342
342
  // src/connectors/oauth/flows/AuthCodePKCE.ts
343
+ function isPublicClientError(responseBody) {
344
+ const lower = responseBody.toLowerCase();
345
+ return lower.includes("aadsts700025") || lower.includes("invalid_client") && lower.includes("public");
346
+ }
343
347
  var AuthCodePKCEFlow;
344
348
  var init_AuthCodePKCE = __esm({
345
349
  "src/connectors/oauth/flows/AuthCodePKCE.ts"() {
@@ -435,14 +439,32 @@ var init_AuthCodePKCE = __esm({
435
439
  if (this.config.usePKCE !== false && verifierData) {
436
440
  params.append("code_verifier", verifierData.verifier);
437
441
  }
438
- const response = await fetch(this.config.tokenUrl, {
442
+ let response = await fetch(this.config.tokenUrl, {
439
443
  method: "POST",
440
444
  headers: {
441
445
  "Content-Type": "application/x-www-form-urlencoded"
442
446
  },
443
447
  body: params
444
448
  });
445
- if (!response.ok) {
449
+ if (!response.ok && this.config.clientSecret) {
450
+ const errorText = await response.text();
451
+ if (isPublicClientError(errorText)) {
452
+ params.delete("client_secret");
453
+ response = await fetch(this.config.tokenUrl, {
454
+ method: "POST",
455
+ headers: {
456
+ "Content-Type": "application/x-www-form-urlencoded"
457
+ },
458
+ body: params
459
+ });
460
+ if (!response.ok) {
461
+ const retryError = await response.text();
462
+ throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${retryError}`);
463
+ }
464
+ } else {
465
+ throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${errorText}`);
466
+ }
467
+ } else if (!response.ok) {
446
468
  const error = await response.text();
447
469
  throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${error}`);
448
470
  }
@@ -488,14 +510,32 @@ var init_AuthCodePKCE = __esm({
488
510
  if (this.config.clientSecret) {
489
511
  params.append("client_secret", this.config.clientSecret);
490
512
  }
491
- const response = await fetch(this.config.tokenUrl, {
513
+ let response = await fetch(this.config.tokenUrl, {
492
514
  method: "POST",
493
515
  headers: {
494
516
  "Content-Type": "application/x-www-form-urlencoded"
495
517
  },
496
518
  body: params
497
519
  });
498
- if (!response.ok) {
520
+ if (!response.ok && this.config.clientSecret) {
521
+ const errorText = await response.text();
522
+ if (isPublicClientError(errorText)) {
523
+ params.delete("client_secret");
524
+ response = await fetch(this.config.tokenUrl, {
525
+ method: "POST",
526
+ headers: {
527
+ "Content-Type": "application/x-www-form-urlencoded"
528
+ },
529
+ body: params
530
+ });
531
+ if (!response.ok) {
532
+ const retryError = await response.text();
533
+ throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${retryError}`);
534
+ }
535
+ } else {
536
+ throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${errorText}`);
537
+ }
538
+ } else if (!response.ok) {
499
539
  const error = await response.text();
500
540
  throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${error}`);
501
541
  }
@@ -633,7 +673,7 @@ var init_JWTBearer = __esm({
633
673
  this.privateKey = config.privateKey;
634
674
  } else if (config.privateKeyPath) {
635
675
  try {
636
- this.privateKey = fs16__namespace.readFileSync(config.privateKeyPath, "utf8");
676
+ this.privateKey = fs17__namespace.readFileSync(config.privateKeyPath, "utf8");
637
677
  } catch (error) {
638
678
  throw new Error(`Failed to read private key from ${config.privateKeyPath}: ${error.message}`);
639
679
  }
@@ -1284,10 +1324,10 @@ var init_Logger = __esm({
1284
1324
  initFileStream(filePath) {
1285
1325
  try {
1286
1326
  const dir = path2__namespace.dirname(filePath);
1287
- if (!fs16__namespace.existsSync(dir)) {
1288
- fs16__namespace.mkdirSync(dir, { recursive: true });
1327
+ if (!fs17__namespace.existsSync(dir)) {
1328
+ fs17__namespace.mkdirSync(dir, { recursive: true });
1289
1329
  }
1290
- this.fileStream = fs16__namespace.createWriteStream(filePath, {
1330
+ this.fileStream = fs17__namespace.createWriteStream(filePath, {
1291
1331
  flags: "a",
1292
1332
  // append mode
1293
1333
  encoding: "utf8"
@@ -14624,12 +14664,12 @@ var require_dist = __commonJS({
14624
14664
  throw new Error(`Unknown format "${name}"`);
14625
14665
  return f;
14626
14666
  };
14627
- function addFormats(ajv, list, fs17, exportName) {
14667
+ function addFormats(ajv, list, fs18, exportName) {
14628
14668
  var _a;
14629
14669
  var _b;
14630
14670
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14631
14671
  for (const f of list)
14632
- ajv.addFormat(f, fs17[f]);
14672
+ ajv.addFormat(f, fs18[f]);
14633
14673
  }
14634
14674
  module.exports = exports$1 = formatsPlugin;
14635
14675
  Object.defineProperty(exports$1, "__esModule", { value: true });
@@ -16683,6 +16723,9 @@ var ToolManager = class extends eventemitter3.EventEmitter {
16683
16723
  if (options.priority !== void 0) existing.priority = options.priority;
16684
16724
  if (options.conditions !== void 0) existing.conditions = options.conditions;
16685
16725
  if (options.permission !== void 0) existing.permission = options.permission;
16726
+ if (options.tags !== void 0) existing.tags = options.tags;
16727
+ if (options.category !== void 0) existing.category = options.category;
16728
+ if (options.source !== void 0) existing.source = options.source;
16686
16729
  return;
16687
16730
  }
16688
16731
  const namespace = options.namespace ?? "default";
@@ -16701,7 +16744,10 @@ var ToolManager = class extends eventemitter3.EventEmitter {
16701
16744
  successCount: 0,
16702
16745
  failureCount: 0
16703
16746
  },
16704
- permission: effectivePermission
16747
+ permission: effectivePermission,
16748
+ tags: options.tags,
16749
+ category: options.category,
16750
+ source: options.source
16705
16751
  };
16706
16752
  this.registry.set(name, registration);
16707
16753
  this.addToNamespace(name, namespace);
@@ -17284,6 +17330,9 @@ var ToolManager = class extends eventemitter3.EventEmitter {
17284
17330
  const namespaces = {};
17285
17331
  const priorities = {};
17286
17332
  const permissions = {};
17333
+ const tags = {};
17334
+ const categories = {};
17335
+ const sources = {};
17287
17336
  for (const [name, reg] of this.registry) {
17288
17337
  enabled[name] = reg.enabled;
17289
17338
  namespaces[name] = reg.namespace;
@@ -17291,8 +17340,17 @@ var ToolManager = class extends eventemitter3.EventEmitter {
17291
17340
  if (reg.permission) {
17292
17341
  permissions[name] = reg.permission;
17293
17342
  }
17343
+ if (reg.tags) {
17344
+ tags[name] = reg.tags;
17345
+ }
17346
+ if (reg.category) {
17347
+ categories[name] = reg.category;
17348
+ }
17349
+ if (reg.source) {
17350
+ sources[name] = reg.source;
17351
+ }
17294
17352
  }
17295
- return { enabled, namespaces, priorities, permissions };
17353
+ return { enabled, namespaces, priorities, permissions, tags, categories, sources };
17296
17354
  }
17297
17355
  /**
17298
17356
  * Load state (restores enabled/disabled, namespaces, priorities, permissions)
@@ -17316,6 +17374,24 @@ var ToolManager = class extends eventemitter3.EventEmitter {
17316
17374
  this.setPermission(name, permission);
17317
17375
  }
17318
17376
  }
17377
+ if (state.tags) {
17378
+ for (const [name, toolTags] of Object.entries(state.tags)) {
17379
+ const reg = this.registry.get(name);
17380
+ if (reg) reg.tags = toolTags;
17381
+ }
17382
+ }
17383
+ if (state.categories) {
17384
+ for (const [name, category] of Object.entries(state.categories)) {
17385
+ const reg = this.registry.get(name);
17386
+ if (reg) reg.category = category;
17387
+ }
17388
+ }
17389
+ if (state.sources) {
17390
+ for (const [name, source] of Object.entries(state.sources)) {
17391
+ const reg = this.registry.get(name);
17392
+ if (reg) reg.source = source;
17393
+ }
17394
+ }
17319
17395
  }
17320
17396
  // ==========================================================================
17321
17397
  // Private Helpers
@@ -20317,7 +20393,7 @@ var FilePersistentInstructionsStorage = class {
20317
20393
  */
20318
20394
  async load() {
20319
20395
  try {
20320
- const raw = await fs16.promises.readFile(this.filePath, "utf-8");
20396
+ const raw = await fs17.promises.readFile(this.filePath, "utf-8");
20321
20397
  const data = JSON.parse(raw);
20322
20398
  if (data.version === 2 && Array.isArray(data.entries)) {
20323
20399
  return data.entries.length > 0 ? data.entries : null;
@@ -20329,7 +20405,7 @@ var FilePersistentInstructionsStorage = class {
20329
20405
  }
20330
20406
  }
20331
20407
  try {
20332
- const content = await fs16.promises.readFile(this.legacyFilePath, "utf-8");
20408
+ const content = await fs17.promises.readFile(this.legacyFilePath, "utf-8");
20333
20409
  const trimmed = content.trim();
20334
20410
  if (!trimmed) return null;
20335
20411
  const now = Date.now();
@@ -20359,11 +20435,11 @@ var FilePersistentInstructionsStorage = class {
20359
20435
  };
20360
20436
  const tempPath = `${this.filePath}.tmp`;
20361
20437
  try {
20362
- await fs16.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
20363
- await fs16.promises.rename(tempPath, this.filePath);
20438
+ await fs17.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
20439
+ await fs17.promises.rename(tempPath, this.filePath);
20364
20440
  } catch (error) {
20365
20441
  try {
20366
- await fs16.promises.unlink(tempPath);
20442
+ await fs17.promises.unlink(tempPath);
20367
20443
  } catch {
20368
20444
  }
20369
20445
  throw error;
@@ -20375,7 +20451,7 @@ var FilePersistentInstructionsStorage = class {
20375
20451
  */
20376
20452
  async delete() {
20377
20453
  try {
20378
- await fs16.promises.unlink(this.filePath);
20454
+ await fs17.promises.unlink(this.filePath);
20379
20455
  } catch (error) {
20380
20456
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
20381
20457
  throw error;
@@ -20388,11 +20464,11 @@ var FilePersistentInstructionsStorage = class {
20388
20464
  */
20389
20465
  async exists() {
20390
20466
  try {
20391
- await fs16.promises.access(this.filePath);
20467
+ await fs17.promises.access(this.filePath);
20392
20468
  return true;
20393
20469
  } catch {
20394
20470
  try {
20395
- await fs16.promises.access(this.legacyFilePath);
20471
+ await fs17.promises.access(this.legacyFilePath);
20396
20472
  return true;
20397
20473
  } catch {
20398
20474
  return false;
@@ -20416,7 +20492,7 @@ var FilePersistentInstructionsStorage = class {
20416
20492
  */
20417
20493
  async ensureDirectory() {
20418
20494
  try {
20419
- await fs16.promises.mkdir(this.directory, { recursive: true });
20495
+ await fs17.promises.mkdir(this.directory, { recursive: true });
20420
20496
  } catch (error) {
20421
20497
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
20422
20498
  throw error;
@@ -20428,7 +20504,7 @@ var FilePersistentInstructionsStorage = class {
20428
20504
  */
20429
20505
  async removeLegacyFile() {
20430
20506
  try {
20431
- await fs16.promises.unlink(this.legacyFilePath);
20507
+ await fs17.promises.unlink(this.legacyFilePath);
20432
20508
  } catch (error) {
20433
20509
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
20434
20510
  console.warn(`Failed to remove legacy instructions file: ${this.legacyFilePath}`);
@@ -28288,7 +28364,7 @@ init_constants();
28288
28364
  throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
28289
28365
  }
28290
28366
  try {
28291
- const content = await fs16.promises.readFile(configPath, "utf-8");
28367
+ const content = await fs17.promises.readFile(configPath, "utf-8");
28292
28368
  let config = JSON.parse(content);
28293
28369
  config = this.interpolateEnvVars(config);
28294
28370
  this.validate(config);
@@ -28309,8 +28385,8 @@ init_constants();
28309
28385
  throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
28310
28386
  }
28311
28387
  try {
28312
- const fs17 = __require("fs");
28313
- const content = fs17.readFileSync(configPath, "utf-8");
28388
+ const fs18 = __require("fs");
28389
+ const content = fs18.readFileSync(configPath, "utf-8");
28314
28390
  let config = JSON.parse(content);
28315
28391
  config = this.interpolateEnvVars(config);
28316
28392
  this.validate(config);
@@ -28328,7 +28404,7 @@ init_constants();
28328
28404
  static async findConfig() {
28329
28405
  for (const path6 of this.DEFAULT_PATHS) {
28330
28406
  try {
28331
- await fs16.promises.access(path2.resolve(path6));
28407
+ await fs17.promises.access(path2.resolve(path6));
28332
28408
  return path2.resolve(path6);
28333
28409
  } catch {
28334
28410
  }
@@ -28339,10 +28415,10 @@ init_constants();
28339
28415
  * Find configuration file synchronously
28340
28416
  */
28341
28417
  static findConfigSync() {
28342
- const fs17 = __require("fs");
28418
+ const fs18 = __require("fs");
28343
28419
  for (const path6 of this.DEFAULT_PATHS) {
28344
28420
  try {
28345
- fs17.accessSync(path2.resolve(path6));
28421
+ fs18.accessSync(path2.resolve(path6));
28346
28422
  return path2.resolve(path6);
28347
28423
  } catch {
28348
28424
  }
@@ -33898,7 +33974,7 @@ var MCPRegistry = class {
33898
33974
  static async loadFromConfigFile(path6) {
33899
33975
  try {
33900
33976
  const configPath = path2.resolve(path6);
33901
- const content = await fs16.promises.readFile(configPath, "utf-8");
33977
+ const content = await fs17.promises.readFile(configPath, "utf-8");
33902
33978
  const config = JSON.parse(content);
33903
33979
  if (!config.mcp) {
33904
33980
  throw new MCPError("Configuration file does not contain MCP section");
@@ -34503,7 +34579,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
34503
34579
  if (Buffer.isBuffer(audio)) {
34504
34580
  return new File([new Uint8Array(audio)], "audio.wav", { type: "audio/wav" });
34505
34581
  } else if (typeof audio === "string") {
34506
- return fs16__namespace.createReadStream(audio);
34582
+ return fs17__namespace.createReadStream(audio);
34507
34583
  } else {
34508
34584
  throw new Error("Invalid audio input: must be Buffer or file path");
34509
34585
  }
@@ -35056,7 +35132,7 @@ var TextToSpeech = class _TextToSpeech {
35056
35132
  */
35057
35133
  async toFile(text, filePath, options) {
35058
35134
  const response = await this.synthesize(text, options);
35059
- await fs15__namespace.writeFile(filePath, response.audio);
35135
+ await fs16__namespace.writeFile(filePath, response.audio);
35060
35136
  }
35061
35137
  // ======================== Introspection Methods ========================
35062
35138
  /**
@@ -35404,7 +35480,7 @@ var SpeechToText = class _SpeechToText {
35404
35480
  * @param options - Optional transcription parameters
35405
35481
  */
35406
35482
  async transcribeFile(filePath, options) {
35407
- const audio = await fs15__namespace.readFile(filePath);
35483
+ const audio = await fs16__namespace.readFile(filePath);
35408
35484
  return this.transcribe(audio, options);
35409
35485
  }
35410
35486
  /**
@@ -35730,7 +35806,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
35730
35806
  if (Buffer.isBuffer(image)) {
35731
35807
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
35732
35808
  }
35733
- return fs16__namespace.createReadStream(image);
35809
+ return fs17__namespace.createReadStream(image);
35734
35810
  }
35735
35811
  /**
35736
35812
  * Handle OpenAI API errors
@@ -35877,8 +35953,8 @@ var GoogleImageProvider = class extends BaseMediaProvider {
35877
35953
  if (Buffer.isBuffer(image)) {
35878
35954
  imageBytes = image.toString("base64");
35879
35955
  } else {
35880
- const fs17 = await import('fs');
35881
- const buffer = fs17.readFileSync(image);
35956
+ const fs18 = await import('fs');
35957
+ const buffer = fs18.readFileSync(image);
35882
35958
  imageBytes = buffer.toString("base64");
35883
35959
  }
35884
35960
  return {
@@ -36039,7 +36115,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
36039
36115
  if (Buffer.isBuffer(image)) {
36040
36116
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
36041
36117
  }
36042
- return fs16__namespace.createReadStream(image);
36118
+ return fs17__namespace.createReadStream(image);
36043
36119
  }
36044
36120
  /**
36045
36121
  * Handle API errors
@@ -37489,8 +37565,8 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
37489
37565
  return new File([new Uint8Array(image)], "input.png", { type: "image/png" });
37490
37566
  }
37491
37567
  if (!image.startsWith("http")) {
37492
- const fs17 = await import('fs');
37493
- const data = fs17.readFileSync(image);
37568
+ const fs18 = await import('fs');
37569
+ const data = fs18.readFileSync(image);
37494
37570
  return new File([new Uint8Array(data)], "input.png", { type: "image/png" });
37495
37571
  }
37496
37572
  const response = await fetch(image);
@@ -37668,7 +37744,7 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
37668
37744
  if (video.videoBytes) {
37669
37745
  buffer = Buffer.from(video.videoBytes, "base64");
37670
37746
  } else if (video.uri) {
37671
- const fs17 = await import('fs/promises');
37747
+ const fs18 = await import('fs/promises');
37672
37748
  const os3 = await import('os');
37673
37749
  const path6 = await import('path');
37674
37750
  const tempDir = os3.tmpdir();
@@ -37679,11 +37755,11 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
37679
37755
  // Pass as GeneratedVideo
37680
37756
  downloadPath: tempFile
37681
37757
  });
37682
- buffer = await fs17.readFile(tempFile);
37683
- await fs17.unlink(tempFile).catch(() => {
37758
+ buffer = await fs18.readFile(tempFile);
37759
+ await fs18.unlink(tempFile).catch(() => {
37684
37760
  });
37685
37761
  } catch (downloadError) {
37686
- await fs17.unlink(tempFile).catch(() => {
37762
+ await fs18.unlink(tempFile).catch(() => {
37687
37763
  });
37688
37764
  throw new ProviderError(
37689
37765
  "google",
@@ -37805,8 +37881,8 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
37805
37881
  if (image.startsWith("http://") || image.startsWith("https://")) {
37806
37882
  return { imageUri: image };
37807
37883
  }
37808
- const fs17 = await import('fs/promises');
37809
- const data = await fs17.readFile(image);
37884
+ const fs18 = await import('fs/promises');
37885
+ const data = await fs18.readFile(image);
37810
37886
  return {
37811
37887
  imageBytes: data.toString("base64")
37812
37888
  };
@@ -38113,8 +38189,8 @@ var GrokImagineProvider = class extends BaseMediaProvider {
38113
38189
  if (image.startsWith("http") || image.startsWith("data:")) {
38114
38190
  return image;
38115
38191
  }
38116
- const fs17 = await import('fs');
38117
- const data = fs17.readFileSync(image);
38192
+ const fs18 = await import('fs');
38193
+ const data = fs18.readFileSync(image);
38118
38194
  const base64 = data.toString("base64");
38119
38195
  const ext = image.split(".").pop()?.toLowerCase() || "png";
38120
38196
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext}`;
@@ -39550,7 +39626,7 @@ var DocumentReader = class _DocumentReader {
39550
39626
  async resolveSource(source) {
39551
39627
  switch (source.type) {
39552
39628
  case "file": {
39553
- const buffer = await fs15.readFile(source.path);
39629
+ const buffer = await fs16.readFile(source.path);
39554
39630
  const filename = source.path.split("/").pop() || source.path;
39555
39631
  return { buffer, filename };
39556
39632
  }
@@ -41869,11 +41945,11 @@ var FileContextStorage = class {
41869
41945
  const data = this.prettyPrint ? JSON.stringify(storedSession, null, 2) : JSON.stringify(storedSession);
41870
41946
  const tempPath = `${filePath}.tmp`;
41871
41947
  try {
41872
- await fs16.promises.writeFile(tempPath, data, "utf-8");
41873
- await fs16.promises.rename(tempPath, filePath);
41948
+ await fs17.promises.writeFile(tempPath, data, "utf-8");
41949
+ await fs17.promises.rename(tempPath, filePath);
41874
41950
  } catch (error) {
41875
41951
  try {
41876
- await fs16.promises.unlink(tempPath);
41952
+ await fs17.promises.unlink(tempPath);
41877
41953
  } catch {
41878
41954
  }
41879
41955
  throw error;
@@ -41894,7 +41970,7 @@ var FileContextStorage = class {
41894
41970
  const sanitizedSessionId = sanitizeId(sessionId);
41895
41971
  const filePath = this.getFilePath(sanitizedSessionId);
41896
41972
  try {
41897
- await fs16.promises.unlink(filePath);
41973
+ await fs17.promises.unlink(filePath);
41898
41974
  } catch (error) {
41899
41975
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
41900
41976
  throw error;
@@ -41909,7 +41985,7 @@ var FileContextStorage = class {
41909
41985
  const sanitizedSessionId = sanitizeId(sessionId);
41910
41986
  const filePath = this.getFilePath(sanitizedSessionId);
41911
41987
  try {
41912
- await fs16.promises.access(filePath);
41988
+ await fs17.promises.access(filePath);
41913
41989
  return true;
41914
41990
  } catch {
41915
41991
  return false;
@@ -41974,7 +42050,7 @@ var FileContextStorage = class {
41974
42050
  const sanitizedSessionId = sanitizeId(sessionId);
41975
42051
  const filePath = this.getFilePath(sanitizedSessionId);
41976
42052
  const data = this.prettyPrint ? JSON.stringify(stored, null, 2) : JSON.stringify(stored);
41977
- await fs16.promises.writeFile(filePath, data, "utf-8");
42053
+ await fs17.promises.writeFile(filePath, data, "utf-8");
41978
42054
  await this.updateIndex(stored);
41979
42055
  }
41980
42056
  /**
@@ -42002,13 +42078,13 @@ var FileContextStorage = class {
42002
42078
  */
42003
42079
  async rebuildIndex() {
42004
42080
  await this.ensureDirectory();
42005
- const files = await fs16.promises.readdir(this.sessionsDirectory);
42081
+ const files = await fs17.promises.readdir(this.sessionsDirectory);
42006
42082
  const sessionFiles = files.filter((f) => f.endsWith(".json") && !f.startsWith("_"));
42007
42083
  const entries = [];
42008
42084
  for (const file of sessionFiles) {
42009
42085
  try {
42010
42086
  const filePath = path2.join(this.sessionsDirectory, file);
42011
- const data = await fs16.promises.readFile(filePath, "utf-8");
42087
+ const data = await fs17.promises.readFile(filePath, "utf-8");
42012
42088
  const stored = JSON.parse(data);
42013
42089
  entries.push(this.storedToIndexEntry(stored));
42014
42090
  } catch {
@@ -42030,7 +42106,7 @@ var FileContextStorage = class {
42030
42106
  }
42031
42107
  async ensureDirectory() {
42032
42108
  try {
42033
- await fs16.promises.mkdir(this.sessionsDirectory, { recursive: true });
42109
+ await fs17.promises.mkdir(this.sessionsDirectory, { recursive: true });
42034
42110
  } catch (error) {
42035
42111
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
42036
42112
  throw error;
@@ -42040,7 +42116,7 @@ var FileContextStorage = class {
42040
42116
  async loadRaw(sanitizedSessionId) {
42041
42117
  const filePath = this.getFilePath(sanitizedSessionId);
42042
42118
  try {
42043
- const data = await fs16.promises.readFile(filePath, "utf-8");
42119
+ const data = await fs17.promises.readFile(filePath, "utf-8");
42044
42120
  return JSON.parse(data);
42045
42121
  } catch (error) {
42046
42122
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -42058,7 +42134,7 @@ var FileContextStorage = class {
42058
42134
  return this.index;
42059
42135
  }
42060
42136
  try {
42061
- const data = await fs16.promises.readFile(this.indexPath, "utf-8");
42137
+ const data = await fs17.promises.readFile(this.indexPath, "utf-8");
42062
42138
  this.index = JSON.parse(data);
42063
42139
  return this.index;
42064
42140
  } catch (error) {
@@ -42079,7 +42155,7 @@ var FileContextStorage = class {
42079
42155
  await this.ensureDirectory();
42080
42156
  this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
42081
42157
  const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
42082
- await fs16.promises.writeFile(this.indexPath, data, "utf-8");
42158
+ await fs17.promises.writeFile(this.indexPath, data, "utf-8");
42083
42159
  }
42084
42160
  async updateIndex(stored) {
42085
42161
  const index = await this.loadIndex();
@@ -42153,11 +42229,11 @@ var FileAgentDefinitionStorage = class {
42153
42229
  const data = this.prettyPrint ? JSON.stringify(definition, null, 2) : JSON.stringify(definition);
42154
42230
  const tempPath = `${filePath}.tmp`;
42155
42231
  try {
42156
- await fs16.promises.writeFile(tempPath, data, "utf-8");
42157
- await fs16.promises.rename(tempPath, filePath);
42232
+ await fs17.promises.writeFile(tempPath, data, "utf-8");
42233
+ await fs17.promises.rename(tempPath, filePath);
42158
42234
  } catch (error) {
42159
42235
  try {
42160
- await fs16.promises.unlink(tempPath);
42236
+ await fs17.promises.unlink(tempPath);
42161
42237
  } catch {
42162
42238
  }
42163
42239
  throw error;
@@ -42179,7 +42255,7 @@ var FileAgentDefinitionStorage = class {
42179
42255
  const agentDir = path2.join(this.baseDirectory, sanitizedId);
42180
42256
  const filePath = path2.join(agentDir, "definition.json");
42181
42257
  try {
42182
- await fs16.promises.unlink(filePath);
42258
+ await fs17.promises.unlink(filePath);
42183
42259
  } catch (error) {
42184
42260
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
42185
42261
  throw error;
@@ -42194,7 +42270,7 @@ var FileAgentDefinitionStorage = class {
42194
42270
  const sanitizedId = sanitizeAgentId2(agentId);
42195
42271
  const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
42196
42272
  try {
42197
- await fs16.promises.access(filePath);
42273
+ await fs17.promises.access(filePath);
42198
42274
  return true;
42199
42275
  } catch {
42200
42276
  return false;
@@ -42256,13 +42332,13 @@ var FileAgentDefinitionStorage = class {
42256
42332
  */
42257
42333
  async rebuildIndex() {
42258
42334
  await this.ensureDirectory(this.baseDirectory);
42259
- const entries = await fs16.promises.readdir(this.baseDirectory, { withFileTypes: true });
42335
+ const entries = await fs17.promises.readdir(this.baseDirectory, { withFileTypes: true });
42260
42336
  const agentDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith("_"));
42261
42337
  const indexEntries = [];
42262
42338
  for (const dir of agentDirs) {
42263
42339
  try {
42264
42340
  const filePath = path2.join(this.baseDirectory, dir.name, "definition.json");
42265
- const data = await fs16.promises.readFile(filePath, "utf-8");
42341
+ const data = await fs17.promises.readFile(filePath, "utf-8");
42266
42342
  const definition = JSON.parse(data);
42267
42343
  indexEntries.push(this.definitionToIndexEntry(definition));
42268
42344
  } catch {
@@ -42280,7 +42356,7 @@ var FileAgentDefinitionStorage = class {
42280
42356
  // ==========================================================================
42281
42357
  async ensureDirectory(dir) {
42282
42358
  try {
42283
- await fs16.promises.mkdir(dir, { recursive: true });
42359
+ await fs17.promises.mkdir(dir, { recursive: true });
42284
42360
  } catch (error) {
42285
42361
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
42286
42362
  throw error;
@@ -42290,7 +42366,7 @@ var FileAgentDefinitionStorage = class {
42290
42366
  async loadRaw(sanitizedId) {
42291
42367
  const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
42292
42368
  try {
42293
- const data = await fs16.promises.readFile(filePath, "utf-8");
42369
+ const data = await fs17.promises.readFile(filePath, "utf-8");
42294
42370
  return JSON.parse(data);
42295
42371
  } catch (error) {
42296
42372
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -42308,7 +42384,7 @@ var FileAgentDefinitionStorage = class {
42308
42384
  return this.index;
42309
42385
  }
42310
42386
  try {
42311
- const data = await fs16.promises.readFile(this.indexPath, "utf-8");
42387
+ const data = await fs17.promises.readFile(this.indexPath, "utf-8");
42312
42388
  this.index = JSON.parse(data);
42313
42389
  return this.index;
42314
42390
  } catch (error) {
@@ -42328,7 +42404,7 @@ var FileAgentDefinitionStorage = class {
42328
42404
  await this.ensureDirectory(this.baseDirectory);
42329
42405
  this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
42330
42406
  const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
42331
- await fs16.promises.writeFile(this.indexPath, data, "utf-8");
42407
+ await fs17.promises.writeFile(this.indexPath, data, "utf-8");
42332
42408
  }
42333
42409
  async updateIndex(definition) {
42334
42410
  const index = await this.loadIndex();
@@ -42386,10 +42462,10 @@ var FileMediaStorage = class {
42386
42462
  }
42387
42463
  async save(data, metadata) {
42388
42464
  const dir = metadata.userId ? path2__namespace.join(this.outputDir, metadata.userId) : this.outputDir;
42389
- await fs15__namespace.mkdir(dir, { recursive: true });
42465
+ await fs16__namespace.mkdir(dir, { recursive: true });
42390
42466
  const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
42391
42467
  const filePath = path2__namespace.join(dir, filename);
42392
- await fs15__namespace.writeFile(filePath, data);
42468
+ await fs16__namespace.writeFile(filePath, data);
42393
42469
  const format = metadata.format.toLowerCase();
42394
42470
  const mimeType = MIME_TYPES2[format] ?? "application/octet-stream";
42395
42471
  return {
@@ -42400,7 +42476,7 @@ var FileMediaStorage = class {
42400
42476
  }
42401
42477
  async read(location) {
42402
42478
  try {
42403
- return await fs15__namespace.readFile(location);
42479
+ return await fs16__namespace.readFile(location);
42404
42480
  } catch (err) {
42405
42481
  if (err.code === "ENOENT") {
42406
42482
  return null;
@@ -42410,7 +42486,7 @@ var FileMediaStorage = class {
42410
42486
  }
42411
42487
  async delete(location) {
42412
42488
  try {
42413
- await fs15__namespace.unlink(location);
42489
+ await fs16__namespace.unlink(location);
42414
42490
  } catch (err) {
42415
42491
  if (err.code === "ENOENT") {
42416
42492
  return;
@@ -42420,7 +42496,7 @@ var FileMediaStorage = class {
42420
42496
  }
42421
42497
  async exists(location) {
42422
42498
  try {
42423
- await fs15__namespace.access(location);
42499
+ await fs16__namespace.access(location);
42424
42500
  return true;
42425
42501
  } catch {
42426
42502
  return false;
@@ -42429,11 +42505,11 @@ var FileMediaStorage = class {
42429
42505
  async list(options) {
42430
42506
  await this.ensureDir();
42431
42507
  let entries = [];
42432
- const files = await fs15__namespace.readdir(this.outputDir);
42508
+ const files = await fs16__namespace.readdir(this.outputDir);
42433
42509
  for (const file of files) {
42434
42510
  const filePath = path2__namespace.join(this.outputDir, file);
42435
42511
  try {
42436
- const stat6 = await fs15__namespace.stat(filePath);
42512
+ const stat6 = await fs16__namespace.stat(filePath);
42437
42513
  if (!stat6.isFile()) continue;
42438
42514
  const ext = path2__namespace.extname(file).slice(1).toLowerCase();
42439
42515
  const mimeType = MIME_TYPES2[ext] ?? "application/octet-stream";
@@ -42473,7 +42549,7 @@ var FileMediaStorage = class {
42473
42549
  }
42474
42550
  async ensureDir() {
42475
42551
  if (!this.initialized) {
42476
- await fs15__namespace.mkdir(this.outputDir, { recursive: true });
42552
+ await fs16__namespace.mkdir(this.outputDir, { recursive: true });
42477
42553
  this.initialized = true;
42478
42554
  }
42479
42555
  }
@@ -42481,6 +42557,230 @@ var FileMediaStorage = class {
42481
42557
  function createFileMediaStorage(config) {
42482
42558
  return new FileMediaStorage(config);
42483
42559
  }
42560
+ function getDefaultBaseDirectory4() {
42561
+ const platform2 = process.platform;
42562
+ if (platform2 === "win32") {
42563
+ const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
42564
+ if (appData) {
42565
+ return path2.join(appData, "oneringai", "custom-tools");
42566
+ }
42567
+ }
42568
+ return path2.join(os2.homedir(), ".oneringai", "custom-tools");
42569
+ }
42570
+ function sanitizeName(name) {
42571
+ return name.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
42572
+ }
42573
+ var FileCustomToolStorage = class {
42574
+ baseDirectory;
42575
+ indexPath;
42576
+ prettyPrint;
42577
+ index = null;
42578
+ constructor(config = {}) {
42579
+ this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory4();
42580
+ this.prettyPrint = config.prettyPrint ?? true;
42581
+ this.indexPath = path2.join(this.baseDirectory, "_index.json");
42582
+ }
42583
+ /**
42584
+ * Save a custom tool definition
42585
+ */
42586
+ async save(definition) {
42587
+ const sanitized = sanitizeName(definition.name);
42588
+ const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
42589
+ await this.ensureDirectory(this.baseDirectory);
42590
+ const data = this.prettyPrint ? JSON.stringify(definition, null, 2) : JSON.stringify(definition);
42591
+ const tempPath = `${filePath}.tmp`;
42592
+ try {
42593
+ await fs17.promises.writeFile(tempPath, data, "utf-8");
42594
+ await fs17.promises.rename(tempPath, filePath);
42595
+ } catch (error) {
42596
+ try {
42597
+ await fs17.promises.unlink(tempPath);
42598
+ } catch {
42599
+ }
42600
+ throw error;
42601
+ }
42602
+ await this.updateIndex(definition);
42603
+ }
42604
+ /**
42605
+ * Load a custom tool definition by name
42606
+ */
42607
+ async load(name) {
42608
+ const sanitized = sanitizeName(name);
42609
+ const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
42610
+ try {
42611
+ const data = await fs17.promises.readFile(filePath, "utf-8");
42612
+ return JSON.parse(data);
42613
+ } catch (error) {
42614
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
42615
+ return null;
42616
+ }
42617
+ if (error instanceof SyntaxError) {
42618
+ return null;
42619
+ }
42620
+ throw error;
42621
+ }
42622
+ }
42623
+ /**
42624
+ * Delete a custom tool definition
42625
+ */
42626
+ async delete(name) {
42627
+ const sanitized = sanitizeName(name);
42628
+ const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
42629
+ try {
42630
+ await fs17.promises.unlink(filePath);
42631
+ } catch (error) {
42632
+ if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
42633
+ throw error;
42634
+ }
42635
+ }
42636
+ await this.removeFromIndex(name);
42637
+ }
42638
+ /**
42639
+ * Check if a custom tool exists
42640
+ */
42641
+ async exists(name) {
42642
+ const sanitized = sanitizeName(name);
42643
+ const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
42644
+ try {
42645
+ await fs17.promises.access(filePath);
42646
+ return true;
42647
+ } catch {
42648
+ return false;
42649
+ }
42650
+ }
42651
+ /**
42652
+ * List custom tools (summaries only)
42653
+ */
42654
+ async list(options) {
42655
+ const index = await this.loadIndex();
42656
+ let entries = [...index.tools];
42657
+ if (options?.tags && options.tags.length > 0) {
42658
+ entries = entries.filter((e) => {
42659
+ const entryTags = e.tags ?? [];
42660
+ return options.tags.some((t) => entryTags.includes(t));
42661
+ });
42662
+ }
42663
+ if (options?.category) {
42664
+ entries = entries.filter((e) => e.category === options.category);
42665
+ }
42666
+ if (options?.search) {
42667
+ const searchLower = options.search.toLowerCase();
42668
+ entries = entries.filter(
42669
+ (e) => e.name.toLowerCase().includes(searchLower) || e.description.toLowerCase().includes(searchLower)
42670
+ );
42671
+ }
42672
+ entries.sort(
42673
+ (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
42674
+ );
42675
+ if (options?.offset) {
42676
+ entries = entries.slice(options.offset);
42677
+ }
42678
+ if (options?.limit) {
42679
+ entries = entries.slice(0, options.limit);
42680
+ }
42681
+ return entries.map((e) => ({
42682
+ name: e.name,
42683
+ displayName: e.displayName,
42684
+ description: e.description,
42685
+ createdAt: e.createdAt,
42686
+ updatedAt: e.updatedAt,
42687
+ metadata: {
42688
+ tags: e.tags,
42689
+ category: e.category
42690
+ }
42691
+ }));
42692
+ }
42693
+ /**
42694
+ * Update metadata without loading full definition
42695
+ */
42696
+ async updateMetadata(name, metadata) {
42697
+ const definition = await this.load(name);
42698
+ if (!definition) {
42699
+ throw new Error(`Custom tool '${name}' not found`);
42700
+ }
42701
+ definition.metadata = { ...definition.metadata, ...metadata };
42702
+ definition.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
42703
+ await this.save(definition);
42704
+ }
42705
+ /**
42706
+ * Get storage path
42707
+ */
42708
+ getPath() {
42709
+ return this.baseDirectory;
42710
+ }
42711
+ // ==========================================================================
42712
+ // Private Helpers
42713
+ // ==========================================================================
42714
+ async ensureDirectory(dir) {
42715
+ try {
42716
+ await fs17.promises.mkdir(dir, { recursive: true });
42717
+ } catch (error) {
42718
+ if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
42719
+ throw error;
42720
+ }
42721
+ }
42722
+ }
42723
+ async loadIndex() {
42724
+ if (this.index) {
42725
+ return this.index;
42726
+ }
42727
+ try {
42728
+ const data = await fs17.promises.readFile(this.indexPath, "utf-8");
42729
+ this.index = JSON.parse(data);
42730
+ return this.index;
42731
+ } catch (error) {
42732
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
42733
+ this.index = {
42734
+ version: 1,
42735
+ tools: [],
42736
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
42737
+ };
42738
+ return this.index;
42739
+ }
42740
+ throw error;
42741
+ }
42742
+ }
42743
+ async saveIndex() {
42744
+ if (!this.index) return;
42745
+ await this.ensureDirectory(this.baseDirectory);
42746
+ this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
42747
+ const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
42748
+ await fs17.promises.writeFile(this.indexPath, data, "utf-8");
42749
+ }
42750
+ async updateIndex(definition) {
42751
+ const index = await this.loadIndex();
42752
+ const entry = this.definitionToIndexEntry(definition);
42753
+ const existingIdx = index.tools.findIndex((e) => e.name === definition.name);
42754
+ if (existingIdx >= 0) {
42755
+ index.tools[existingIdx] = entry;
42756
+ } else {
42757
+ index.tools.push(entry);
42758
+ }
42759
+ await this.saveIndex();
42760
+ }
42761
+ async removeFromIndex(name) {
42762
+ const index = await this.loadIndex();
42763
+ index.tools = index.tools.filter((e) => e.name !== name);
42764
+ await this.saveIndex();
42765
+ }
42766
+ definitionToIndexEntry(definition) {
42767
+ return {
42768
+ name: definition.name,
42769
+ displayName: definition.displayName,
42770
+ description: definition.description,
42771
+ createdAt: definition.createdAt,
42772
+ updatedAt: definition.updatedAt,
42773
+ tags: definition.metadata?.tags,
42774
+ category: definition.metadata?.category
42775
+ };
42776
+ }
42777
+ };
42778
+ function createFileCustomToolStorage(config) {
42779
+ return new FileCustomToolStorage(config);
42780
+ }
42781
+
42782
+ // src/domain/entities/CustomToolDefinition.ts
42783
+ var CUSTOM_TOOL_DEFINITION_VERSION = 1;
42484
42784
 
42485
42785
  // src/capabilities/agents/StreamHelpers.ts
42486
42786
  var StreamHelpers = class {
@@ -42928,6 +43228,23 @@ var SERVICE_DEFINITIONS = [
42928
43228
  baseURL: "https://api-m.paypal.com/v2",
42929
43229
  docsURL: "https://developer.paypal.com/docs/api/"
42930
43230
  },
43231
+ {
43232
+ id: "quickbooks",
43233
+ name: "QuickBooks",
43234
+ category: "payments",
43235
+ urlPattern: /quickbooks\.api\.intuit\.com|intuit\.com.*quickbooks/i,
43236
+ baseURL: "https://quickbooks.api.intuit.com/v3",
43237
+ docsURL: "https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/account",
43238
+ commonScopes: ["com.intuit.quickbooks.accounting"]
43239
+ },
43240
+ {
43241
+ id: "ramp",
43242
+ name: "Ramp",
43243
+ category: "payments",
43244
+ urlPattern: /api\.ramp\.com/i,
43245
+ baseURL: "https://api.ramp.com/developer/v1",
43246
+ docsURL: "https://docs.ramp.com/reference"
43247
+ },
42931
43248
  // ============ Cloud Providers ============
42932
43249
  {
42933
43250
  id: "aws",
@@ -43560,8 +43877,8 @@ var FileStorage = class {
43560
43877
  }
43561
43878
  async ensureDirectory() {
43562
43879
  try {
43563
- await fs15__namespace.mkdir(this.directory, { recursive: true });
43564
- await fs15__namespace.chmod(this.directory, 448);
43880
+ await fs16__namespace.mkdir(this.directory, { recursive: true });
43881
+ await fs16__namespace.chmod(this.directory, 448);
43565
43882
  } catch (error) {
43566
43883
  }
43567
43884
  }
@@ -43577,13 +43894,13 @@ var FileStorage = class {
43577
43894
  const filePath = this.getFilePath(key);
43578
43895
  const plaintext = JSON.stringify(token);
43579
43896
  const encrypted = encrypt(plaintext, this.encryptionKey);
43580
- await fs15__namespace.writeFile(filePath, encrypted, "utf8");
43581
- await fs15__namespace.chmod(filePath, 384);
43897
+ await fs16__namespace.writeFile(filePath, encrypted, "utf8");
43898
+ await fs16__namespace.chmod(filePath, 384);
43582
43899
  }
43583
43900
  async getToken(key) {
43584
43901
  const filePath = this.getFilePath(key);
43585
43902
  try {
43586
- const encrypted = await fs15__namespace.readFile(filePath, "utf8");
43903
+ const encrypted = await fs16__namespace.readFile(filePath, "utf8");
43587
43904
  const decrypted = decrypt(encrypted, this.encryptionKey);
43588
43905
  return JSON.parse(decrypted);
43589
43906
  } catch (error) {
@@ -43592,7 +43909,7 @@ var FileStorage = class {
43592
43909
  }
43593
43910
  console.error("Failed to read/decrypt token file:", error);
43594
43911
  try {
43595
- await fs15__namespace.unlink(filePath);
43912
+ await fs16__namespace.unlink(filePath);
43596
43913
  } catch {
43597
43914
  }
43598
43915
  return null;
@@ -43601,7 +43918,7 @@ var FileStorage = class {
43601
43918
  async deleteToken(key) {
43602
43919
  const filePath = this.getFilePath(key);
43603
43920
  try {
43604
- await fs15__namespace.unlink(filePath);
43921
+ await fs16__namespace.unlink(filePath);
43605
43922
  } catch (error) {
43606
43923
  if (error.code !== "ENOENT") {
43607
43924
  throw error;
@@ -43611,7 +43928,7 @@ var FileStorage = class {
43611
43928
  async hasToken(key) {
43612
43929
  const filePath = this.getFilePath(key);
43613
43930
  try {
43614
- await fs15__namespace.access(filePath);
43931
+ await fs16__namespace.access(filePath);
43615
43932
  return true;
43616
43933
  } catch {
43617
43934
  return false;
@@ -43622,7 +43939,7 @@ var FileStorage = class {
43622
43939
  */
43623
43940
  async listTokens() {
43624
43941
  try {
43625
- const files = await fs15__namespace.readdir(this.directory);
43942
+ const files = await fs16__namespace.readdir(this.directory);
43626
43943
  return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
43627
43944
  } catch {
43628
43945
  return [];
@@ -43633,10 +43950,10 @@ var FileStorage = class {
43633
43950
  */
43634
43951
  async clearAll() {
43635
43952
  try {
43636
- const files = await fs15__namespace.readdir(this.directory);
43953
+ const files = await fs16__namespace.readdir(this.directory);
43637
43954
  const tokenFiles = files.filter((f) => f.endsWith(".token"));
43638
43955
  await Promise.all(
43639
- tokenFiles.map((f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
43956
+ tokenFiles.map((f) => fs16__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
43640
43957
  }))
43641
43958
  );
43642
43959
  } catch {
@@ -44063,14 +44380,14 @@ var FileConnectorStorage = class {
44063
44380
  await this.ensureDirectory();
44064
44381
  const filePath = this.getFilePath(name);
44065
44382
  const json = JSON.stringify(stored, null, 2);
44066
- await fs15__namespace.writeFile(filePath, json, "utf8");
44067
- await fs15__namespace.chmod(filePath, 384);
44383
+ await fs16__namespace.writeFile(filePath, json, "utf8");
44384
+ await fs16__namespace.chmod(filePath, 384);
44068
44385
  await this.updateIndex(name, "add");
44069
44386
  }
44070
44387
  async get(name) {
44071
44388
  const filePath = this.getFilePath(name);
44072
44389
  try {
44073
- const json = await fs15__namespace.readFile(filePath, "utf8");
44390
+ const json = await fs16__namespace.readFile(filePath, "utf8");
44074
44391
  return JSON.parse(json);
44075
44392
  } catch (error) {
44076
44393
  const err = error;
@@ -44083,7 +44400,7 @@ var FileConnectorStorage = class {
44083
44400
  async delete(name) {
44084
44401
  const filePath = this.getFilePath(name);
44085
44402
  try {
44086
- await fs15__namespace.unlink(filePath);
44403
+ await fs16__namespace.unlink(filePath);
44087
44404
  await this.updateIndex(name, "remove");
44088
44405
  return true;
44089
44406
  } catch (error) {
@@ -44097,7 +44414,7 @@ var FileConnectorStorage = class {
44097
44414
  async has(name) {
44098
44415
  const filePath = this.getFilePath(name);
44099
44416
  try {
44100
- await fs15__namespace.access(filePath);
44417
+ await fs16__namespace.access(filePath);
44101
44418
  return true;
44102
44419
  } catch {
44103
44420
  return false;
@@ -44123,13 +44440,13 @@ var FileConnectorStorage = class {
44123
44440
  */
44124
44441
  async clear() {
44125
44442
  try {
44126
- const files = await fs15__namespace.readdir(this.directory);
44443
+ const files = await fs16__namespace.readdir(this.directory);
44127
44444
  const connectorFiles = files.filter(
44128
44445
  (f) => f.endsWith(".connector.json") || f === "_index.json"
44129
44446
  );
44130
44447
  await Promise.all(
44131
44448
  connectorFiles.map(
44132
- (f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
44449
+ (f) => fs16__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
44133
44450
  })
44134
44451
  )
44135
44452
  );
@@ -44156,8 +44473,8 @@ var FileConnectorStorage = class {
44156
44473
  async ensureDirectory() {
44157
44474
  if (this.initialized) return;
44158
44475
  try {
44159
- await fs15__namespace.mkdir(this.directory, { recursive: true });
44160
- await fs15__namespace.chmod(this.directory, 448);
44476
+ await fs16__namespace.mkdir(this.directory, { recursive: true });
44477
+ await fs16__namespace.chmod(this.directory, 448);
44161
44478
  this.initialized = true;
44162
44479
  } catch {
44163
44480
  this.initialized = true;
@@ -44168,7 +44485,7 @@ var FileConnectorStorage = class {
44168
44485
  */
44169
44486
  async loadIndex() {
44170
44487
  try {
44171
- const json = await fs15__namespace.readFile(this.indexPath, "utf8");
44488
+ const json = await fs16__namespace.readFile(this.indexPath, "utf8");
44172
44489
  return JSON.parse(json);
44173
44490
  } catch {
44174
44491
  return { connectors: {} };
@@ -44186,8 +44503,8 @@ var FileConnectorStorage = class {
44186
44503
  delete index.connectors[hash];
44187
44504
  }
44188
44505
  const json = JSON.stringify(index, null, 2);
44189
- await fs15__namespace.writeFile(this.indexPath, json, "utf8");
44190
- await fs15__namespace.chmod(this.indexPath, 384);
44506
+ await fs16__namespace.writeFile(this.indexPath, json, "utf8");
44507
+ await fs16__namespace.chmod(this.indexPath, 384);
44191
44508
  }
44192
44509
  };
44193
44510
 
@@ -44353,7 +44670,9 @@ function getVendorInfo(vendorId) {
44353
44670
  name: a.name,
44354
44671
  type: a.type,
44355
44672
  description: a.description,
44356
- requiredFields: a.requiredFields
44673
+ requiredFields: a.requiredFields,
44674
+ scopes: a.scopes,
44675
+ scopeDescriptions: a.scopeDescriptions
44357
44676
  }))
44358
44677
  };
44359
44678
  }
@@ -44369,7 +44688,9 @@ function listVendors() {
44369
44688
  name: a.name,
44370
44689
  type: a.type,
44371
44690
  description: a.description,
44372
- requiredFields: a.requiredFields
44691
+ requiredFields: a.requiredFields,
44692
+ scopes: a.scopes,
44693
+ scopeDescriptions: a.scopeDescriptions
44373
44694
  }))
44374
44695
  }));
44375
44696
  }
@@ -44418,14 +44739,49 @@ var microsoftTemplate = {
44418
44739
  scopes: [
44419
44740
  "User.Read",
44420
44741
  "Mail.Read",
44742
+ "Mail.ReadWrite",
44421
44743
  "Mail.Send",
44422
- "Files.ReadWrite",
44423
44744
  "Calendars.ReadWrite",
44745
+ "Contacts.Read",
44746
+ "Contacts.ReadWrite",
44747
+ "Files.ReadWrite",
44748
+ "Sites.Read.All",
44749
+ "Sites.ReadWrite.All",
44750
+ "Notes.Read",
44751
+ "Notes.ReadWrite",
44752
+ "Tasks.ReadWrite",
44424
44753
  "ChannelMessage.Send",
44425
44754
  "Team.ReadBasic.All",
44426
44755
  "Chat.ReadWrite",
44756
+ "People.Read",
44757
+ "Presence.Read",
44758
+ "Directory.Read.All",
44759
+ "BookingsAppointment.ReadWrite.All",
44427
44760
  "offline_access"
44428
- ]
44761
+ ],
44762
+ scopeDescriptions: {
44763
+ "User.Read": "Read your profile",
44764
+ "Mail.Read": "Read your email",
44765
+ "Mail.ReadWrite": "Read and write your email",
44766
+ "Mail.Send": "Send email on your behalf",
44767
+ "Calendars.ReadWrite": "Read and write your calendar",
44768
+ "Contacts.Read": "Read your contacts",
44769
+ "Contacts.ReadWrite": "Read and write your contacts",
44770
+ "Files.ReadWrite": "Read and write your files (OneDrive)",
44771
+ "Sites.Read.All": "Read SharePoint sites",
44772
+ "Sites.ReadWrite.All": "Read and write SharePoint sites",
44773
+ "Notes.Read": "Read your OneNote notebooks",
44774
+ "Notes.ReadWrite": "Read and write your OneNote notebooks",
44775
+ "Tasks.ReadWrite": "Read and write your tasks (To Do / Planner)",
44776
+ "ChannelMessage.Send": "Send messages in Teams channels",
44777
+ "Team.ReadBasic.All": "Read Teams basic info",
44778
+ "Chat.ReadWrite": "Read and write Teams chats",
44779
+ "People.Read": "Read your relevant people list",
44780
+ "Presence.Read": "Read user presence information",
44781
+ "Directory.Read.All": "Read directory data (Azure AD)",
44782
+ "BookingsAppointment.ReadWrite.All": "Manage Bookings appointments",
44783
+ "offline_access": "Maintain access (refresh token)"
44784
+ }
44429
44785
  },
44430
44786
  {
44431
44787
  id: "client-credentials",
@@ -44440,7 +44796,10 @@ var microsoftTemplate = {
44440
44796
  flow: "client_credentials",
44441
44797
  tokenUrl: "https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token"
44442
44798
  },
44443
- scopes: ["https://graph.microsoft.com/.default"]
44799
+ scopes: ["https://graph.microsoft.com/.default"],
44800
+ scopeDescriptions: {
44801
+ "https://graph.microsoft.com/.default": "All permissions granted to the app registration"
44802
+ }
44444
44803
  }
44445
44804
  ]
44446
44805
  };
@@ -44474,9 +44833,24 @@ var googleTemplate = {
44474
44833
  "https://www.googleapis.com/auth/drive",
44475
44834
  "https://www.googleapis.com/auth/calendar",
44476
44835
  "https://www.googleapis.com/auth/gmail.readonly",
44836
+ "https://www.googleapis.com/auth/gmail.send",
44477
44837
  "https://www.googleapis.com/auth/spreadsheets",
44478
- "https://www.googleapis.com/auth/documents"
44479
- ]
44838
+ "https://www.googleapis.com/auth/documents",
44839
+ "https://www.googleapis.com/auth/contacts.readonly",
44840
+ "https://www.googleapis.com/auth/tasks",
44841
+ "https://www.googleapis.com/auth/admin.directory.user.readonly"
44842
+ ],
44843
+ scopeDescriptions: {
44844
+ "https://www.googleapis.com/auth/drive": "Read and write Google Drive files",
44845
+ "https://www.googleapis.com/auth/calendar": "Read and write Google Calendar",
44846
+ "https://www.googleapis.com/auth/gmail.readonly": "Read Gmail messages",
44847
+ "https://www.googleapis.com/auth/gmail.send": "Send Gmail messages",
44848
+ "https://www.googleapis.com/auth/spreadsheets": "Read and write Google Sheets",
44849
+ "https://www.googleapis.com/auth/documents": "Read and write Google Docs",
44850
+ "https://www.googleapis.com/auth/contacts.readonly": "Read Google Contacts",
44851
+ "https://www.googleapis.com/auth/tasks": "Read and write Google Tasks",
44852
+ "https://www.googleapis.com/auth/admin.directory.user.readonly": "Read user directory (Admin)"
44853
+ }
44480
44854
  },
44481
44855
  {
44482
44856
  id: "service-account",
@@ -44495,7 +44869,11 @@ var googleTemplate = {
44495
44869
  scopes: [
44496
44870
  "https://www.googleapis.com/auth/cloud-platform",
44497
44871
  "https://www.googleapis.com/auth/drive"
44498
- ]
44872
+ ],
44873
+ scopeDescriptions: {
44874
+ "https://www.googleapis.com/auth/cloud-platform": "Full access to Google Cloud Platform",
44875
+ "https://www.googleapis.com/auth/drive": "Read and write Google Drive files"
44876
+ }
44499
44877
  }
44500
44878
  ]
44501
44879
  };
@@ -44537,7 +44915,19 @@ var slackTemplate = {
44537
44915
  authorizationUrl: "https://slack.com/oauth/v2/authorize",
44538
44916
  tokenUrl: "https://slack.com/api/oauth.v2.access"
44539
44917
  },
44540
- scopes: ["chat:write", "channels:read", "users:read", "im:write", "groups:read"]
44918
+ scopes: ["chat:write", "channels:read", "users:read", "im:write", "groups:read", "files:read", "files:write", "reactions:read", "reactions:write", "team:read"],
44919
+ scopeDescriptions: {
44920
+ "chat:write": "Send messages as the app",
44921
+ "channels:read": "View basic channel info",
44922
+ "users:read": "View people in the workspace",
44923
+ "im:write": "Send direct messages",
44924
+ "groups:read": "View basic private channel info",
44925
+ "files:read": "View files shared in channels",
44926
+ "files:write": "Upload and manage files",
44927
+ "reactions:read": "View emoji reactions",
44928
+ "reactions:write": "Add and remove emoji reactions",
44929
+ "team:read": "View workspace info"
44930
+ }
44541
44931
  }
44542
44932
  ]
44543
44933
  };
@@ -44578,7 +44968,16 @@ var discordTemplate = {
44578
44968
  authorizationUrl: "https://discord.com/api/oauth2/authorize",
44579
44969
  tokenUrl: "https://discord.com/api/oauth2/token"
44580
44970
  },
44581
- scopes: ["identify", "guilds", "guilds.members.read", "messages.read"]
44971
+ scopes: ["identify", "email", "guilds", "guilds.members.read", "messages.read", "bot", "connections"],
44972
+ scopeDescriptions: {
44973
+ "identify": "Access your username and avatar",
44974
+ "email": "Access your email address",
44975
+ "guilds": "View your server list",
44976
+ "guilds.members.read": "Read server member info",
44977
+ "messages.read": "Read messages in accessible channels",
44978
+ "bot": "Add a bot to your servers",
44979
+ "connections": "View your connected accounts"
44980
+ }
44582
44981
  }
44583
44982
  ]
44584
44983
  };
@@ -44645,7 +45044,18 @@ var githubTemplate = {
44645
45044
  authorizationUrl: "https://github.com/login/oauth/authorize",
44646
45045
  tokenUrl: "https://github.com/login/oauth/access_token"
44647
45046
  },
44648
- scopes: ["repo", "read:user", "read:org", "workflow", "gist"]
45047
+ scopes: ["repo", "read:user", "user:email", "read:org", "workflow", "gist", "notifications", "delete_repo", "admin:org"],
45048
+ scopeDescriptions: {
45049
+ "repo": "Full control of private repositories",
45050
+ "read:user": "Read user profile data",
45051
+ "user:email": "Access user email addresses",
45052
+ "read:org": "Read org and team membership",
45053
+ "workflow": "Update GitHub Actions workflows",
45054
+ "gist": "Create and manage gists",
45055
+ "notifications": "Access notifications",
45056
+ "delete_repo": "Delete repositories",
45057
+ "admin:org": "Full control of orgs and teams"
45058
+ }
44649
45059
  },
44650
45060
  {
44651
45061
  id: "github-app",
@@ -44700,7 +45110,13 @@ var gitlabTemplate = {
44700
45110
  authorizationUrl: "https://gitlab.com/oauth/authorize",
44701
45111
  tokenUrl: "https://gitlab.com/oauth/token"
44702
45112
  },
44703
- scopes: ["api", "read_user", "read_repository", "write_repository"]
45113
+ scopes: ["api", "read_user", "read_repository", "write_repository"],
45114
+ scopeDescriptions: {
45115
+ "api": "Full API access",
45116
+ "read_user": "Read user profile",
45117
+ "read_repository": "Read repository contents",
45118
+ "write_repository": "Write to repositories"
45119
+ }
44704
45120
  }
44705
45121
  ]
44706
45122
  };
@@ -44742,7 +45158,14 @@ var jiraTemplate = {
44742
45158
  authorizationUrl: "https://auth.atlassian.com/authorize",
44743
45159
  tokenUrl: "https://auth.atlassian.com/oauth/token"
44744
45160
  },
44745
- scopes: ["read:jira-work", "write:jira-work", "read:jira-user"]
45161
+ scopes: ["read:jira-work", "write:jira-work", "read:jira-user", "manage:jira-project", "manage:jira-configuration"],
45162
+ scopeDescriptions: {
45163
+ "read:jira-work": "Read issues, projects, boards",
45164
+ "write:jira-work": "Create and update issues",
45165
+ "read:jira-user": "Read user information",
45166
+ "manage:jira-project": "Manage projects and components",
45167
+ "manage:jira-configuration": "Manage Jira settings"
45168
+ }
44746
45169
  }
44747
45170
  ]
44748
45171
  };
@@ -44782,7 +45205,14 @@ var confluenceTemplate = {
44782
45205
  authorizationUrl: "https://auth.atlassian.com/authorize",
44783
45206
  tokenUrl: "https://auth.atlassian.com/oauth/token"
44784
45207
  },
44785
- scopes: ["read:confluence-content.all", "write:confluence-content", "read:confluence-space.summary"]
45208
+ scopes: ["read:confluence-content.all", "write:confluence-content", "read:confluence-space.summary", "write:confluence-space", "read:confluence-user"],
45209
+ scopeDescriptions: {
45210
+ "read:confluence-content.all": "Read all pages and blog posts",
45211
+ "write:confluence-content": "Create and update pages",
45212
+ "read:confluence-space.summary": "Read space summaries",
45213
+ "write:confluence-space": "Create and manage spaces",
45214
+ "read:confluence-user": "Read user information"
45215
+ }
44786
45216
  }
44787
45217
  ]
44788
45218
  };
@@ -44821,7 +45251,16 @@ var bitbucketTemplate = {
44821
45251
  authorizationUrl: "https://bitbucket.org/site/oauth2/authorize",
44822
45252
  tokenUrl: "https://bitbucket.org/site/oauth2/access_token"
44823
45253
  },
44824
- scopes: ["repository", "pullrequest", "account"]
45254
+ scopes: ["repository", "repository:write", "pullrequest", "pullrequest:write", "account", "pipeline", "wiki"],
45255
+ scopeDescriptions: {
45256
+ "repository": "Read repositories",
45257
+ "repository:write": "Write to repositories",
45258
+ "pullrequest": "Read pull requests",
45259
+ "pullrequest:write": "Create and update pull requests",
45260
+ "account": "Read account information",
45261
+ "pipeline": "Access Pipelines (CI/CD)",
45262
+ "wiki": "Access repository wiki"
45263
+ }
44825
45264
  }
44826
45265
  ]
44827
45266
  };
@@ -44861,7 +45300,12 @@ var trelloTemplate = {
44861
45300
  authorizationUrl: "https://trello.com/1/authorize",
44862
45301
  tokenUrl: "https://trello.com/1/OAuthGetAccessToken"
44863
45302
  },
44864
- scopes: ["read", "write", "account"]
45303
+ scopes: ["read", "write", "account"],
45304
+ scopeDescriptions: {
45305
+ "read": "Read boards, lists, and cards",
45306
+ "write": "Create and update boards, lists, and cards",
45307
+ "account": "Read member information"
45308
+ }
44865
45309
  }
44866
45310
  ]
44867
45311
  };
@@ -45056,7 +45500,15 @@ var salesforceTemplate = {
45056
45500
  authorizationUrl: "https://login.salesforce.com/services/oauth2/authorize",
45057
45501
  tokenUrl: "https://login.salesforce.com/services/oauth2/token"
45058
45502
  },
45059
- scopes: ["api", "refresh_token", "offline_access"]
45503
+ scopes: ["api", "refresh_token", "offline_access", "chatter_api", "wave_api", "full"],
45504
+ scopeDescriptions: {
45505
+ "api": "Access and manage your data",
45506
+ "refresh_token": "Maintain access with refresh tokens",
45507
+ "offline_access": "Access data while you are offline",
45508
+ "chatter_api": "Access Chatter feeds and posts",
45509
+ "wave_api": "Access Analytics (Wave) API",
45510
+ "full": "Full access to all data"
45511
+ }
45060
45512
  },
45061
45513
  {
45062
45514
  id: "jwt-bearer",
@@ -45111,7 +45563,26 @@ var hubspotTemplate = {
45111
45563
  authorizationUrl: "https://app.hubspot.com/oauth/authorize",
45112
45564
  tokenUrl: "https://api.hubapi.com/oauth/v1/token"
45113
45565
  },
45114
- scopes: ["crm.objects.contacts.read", "crm.objects.contacts.write", "crm.objects.companies.read"]
45566
+ scopes: [
45567
+ "crm.objects.contacts.read",
45568
+ "crm.objects.contacts.write",
45569
+ "crm.objects.companies.read",
45570
+ "crm.objects.companies.write",
45571
+ "crm.objects.deals.read",
45572
+ "crm.objects.deals.write",
45573
+ "tickets",
45574
+ "e-commerce"
45575
+ ],
45576
+ scopeDescriptions: {
45577
+ "crm.objects.contacts.read": "Read contacts",
45578
+ "crm.objects.contacts.write": "Create and update contacts",
45579
+ "crm.objects.companies.read": "Read companies",
45580
+ "crm.objects.companies.write": "Create and update companies",
45581
+ "crm.objects.deals.read": "Read deals",
45582
+ "crm.objects.deals.write": "Create and update deals",
45583
+ "tickets": "Read and write support tickets",
45584
+ "e-commerce": "Access e-commerce data (products, line items)"
45585
+ }
45115
45586
  }
45116
45587
  ]
45117
45588
  };
@@ -45224,6 +45695,86 @@ var paypalTemplate = {
45224
45695
  ]
45225
45696
  };
45226
45697
 
45698
+ // src/connectors/vendors/templates/quickbooks.ts
45699
+ var quickbooksTemplate = {
45700
+ id: "quickbooks",
45701
+ name: "QuickBooks",
45702
+ serviceType: "quickbooks",
45703
+ baseURL: "https://quickbooks.api.intuit.com/v3",
45704
+ docsURL: "https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/account",
45705
+ credentialsSetupURL: "https://developer.intuit.com/app/developer/dashboard",
45706
+ category: "payments",
45707
+ notes: "Use sandbox URL (sandbox-quickbooks.api.intuit.com) for testing. Requires company/realm ID in API paths.",
45708
+ authTemplates: [
45709
+ {
45710
+ id: "oauth-user",
45711
+ name: "OAuth (User Authorization)",
45712
+ type: "oauth",
45713
+ flow: "authorization_code",
45714
+ description: "Standard OAuth 2.0 flow for accessing QuickBooks on behalf of a user. Create an app at developer.intuit.com",
45715
+ requiredFields: ["clientId", "clientSecret", "redirectUri"],
45716
+ optionalFields: ["scope"],
45717
+ defaults: {
45718
+ type: "oauth",
45719
+ flow: "authorization_code",
45720
+ authorizationUrl: "https://appcenter.intuit.com/connect/oauth2",
45721
+ tokenUrl: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
45722
+ },
45723
+ scopes: ["com.intuit.quickbooks.accounting", "com.intuit.quickbooks.payment"]
45724
+ }
45725
+ ]
45726
+ };
45727
+
45728
+ // src/connectors/vendors/templates/ramp.ts
45729
+ var rampTemplate = {
45730
+ id: "ramp",
45731
+ name: "Ramp",
45732
+ serviceType: "ramp",
45733
+ baseURL: "https://api.ramp.com/developer/v1",
45734
+ docsURL: "https://docs.ramp.com",
45735
+ credentialsSetupURL: "https://app.ramp.com/settings/developer",
45736
+ category: "payments",
45737
+ authTemplates: [
45738
+ {
45739
+ id: "oauth-client-credentials",
45740
+ name: "OAuth (Client Credentials)",
45741
+ type: "oauth",
45742
+ flow: "client_credentials",
45743
+ description: "App-level authentication using client credentials. Create an API application in Ramp developer settings",
45744
+ requiredFields: ["clientId", "clientSecret"],
45745
+ defaults: {
45746
+ type: "oauth",
45747
+ flow: "client_credentials",
45748
+ tokenUrl: "https://api.ramp.com/developer/v1/token"
45749
+ }
45750
+ },
45751
+ {
45752
+ id: "oauth-user",
45753
+ name: "OAuth (User Authorization)",
45754
+ type: "oauth",
45755
+ flow: "authorization_code",
45756
+ description: "OAuth 2.0 authorization code flow for accessing Ramp on behalf of a user",
45757
+ requiredFields: ["clientId", "clientSecret", "redirectUri"],
45758
+ optionalFields: ["scope"],
45759
+ defaults: {
45760
+ type: "oauth",
45761
+ flow: "authorization_code",
45762
+ authorizationUrl: "https://app.ramp.com/v1/authorize",
45763
+ tokenUrl: "https://api.ramp.com/developer/v1/token"
45764
+ },
45765
+ scopes: [
45766
+ "transactions:read",
45767
+ "users:read",
45768
+ "users:write",
45769
+ "cards:read",
45770
+ "cards:write",
45771
+ "departments:read",
45772
+ "reimbursements:read"
45773
+ ]
45774
+ }
45775
+ ]
45776
+ };
45777
+
45227
45778
  // src/connectors/vendors/templates/aws.ts
45228
45779
  var awsTemplate = {
45229
45780
  id: "aws",
@@ -45276,7 +45827,16 @@ var dropboxTemplate = {
45276
45827
  tokenUrl: "https://api.dropboxapi.com/oauth2/token",
45277
45828
  usePKCE: true
45278
45829
  },
45279
- scopes: ["files.content.read", "files.content.write", "files.metadata.read"]
45830
+ scopes: ["files.content.read", "files.content.write", "files.metadata.read", "files.metadata.write", "sharing.read", "sharing.write", "account_info.read"],
45831
+ scopeDescriptions: {
45832
+ "files.content.read": "Read file contents",
45833
+ "files.content.write": "Upload and modify files",
45834
+ "files.metadata.read": "Read file and folder metadata",
45835
+ "files.metadata.write": "Modify file and folder metadata",
45836
+ "sharing.read": "View sharing settings",
45837
+ "sharing.write": "Manage sharing settings",
45838
+ "account_info.read": "Read account information"
45839
+ }
45280
45840
  }
45281
45841
  ]
45282
45842
  };
@@ -45304,6 +45864,13 @@ var boxTemplate = {
45304
45864
  flow: "authorization_code",
45305
45865
  authorizationUrl: "https://account.box.com/api/oauth2/authorize",
45306
45866
  tokenUrl: "https://api.box.com/oauth2/token"
45867
+ },
45868
+ scopes: ["root_readwrite", "manage_users", "manage_groups", "manage_enterprise"],
45869
+ scopeDescriptions: {
45870
+ "root_readwrite": "Read and write all files and folders",
45871
+ "manage_users": "Manage enterprise users",
45872
+ "manage_groups": "Manage enterprise groups",
45873
+ "manage_enterprise": "Manage enterprise settings"
45307
45874
  }
45308
45875
  },
45309
45876
  {
@@ -45480,6 +46047,11 @@ var pagerdutyTemplate = {
45480
46047
  flow: "authorization_code",
45481
46048
  authorizationUrl: "https://app.pagerduty.com/oauth/authorize",
45482
46049
  tokenUrl: "https://app.pagerduty.com/oauth/token"
46050
+ },
46051
+ scopes: ["read", "write"],
46052
+ scopeDescriptions: {
46053
+ "read": "Read incidents, services, and schedules",
46054
+ "write": "Create and update incidents and services"
45483
46055
  }
45484
46056
  }
45485
46057
  ]
@@ -45518,6 +46090,14 @@ var sentryTemplate = {
45518
46090
  flow: "authorization_code",
45519
46091
  authorizationUrl: "https://sentry.io/oauth/authorize/",
45520
46092
  tokenUrl: "https://sentry.io/oauth/token/"
46093
+ },
46094
+ scopes: ["project:read", "project:write", "event:read", "org:read", "member:read"],
46095
+ scopeDescriptions: {
46096
+ "project:read": "Read project settings",
46097
+ "project:write": "Manage project settings",
46098
+ "event:read": "Read error events and issues",
46099
+ "org:read": "Read organization info",
46100
+ "member:read": "Read org member info"
45521
46101
  }
45522
46102
  }
45523
46103
  ]
@@ -45715,7 +46295,13 @@ var zendeskTemplate = {
45715
46295
  authorizationUrl: "https://{subdomain}.zendesk.com/oauth/authorizations/new",
45716
46296
  tokenUrl: "https://{subdomain}.zendesk.com/oauth/tokens"
45717
46297
  },
45718
- scopes: ["read", "write", "tickets:read", "tickets:write"]
46298
+ scopes: ["read", "write", "tickets:read", "tickets:write"],
46299
+ scopeDescriptions: {
46300
+ "read": "Read all resources",
46301
+ "write": "Create and update resources",
46302
+ "tickets:read": "Read support tickets",
46303
+ "tickets:write": "Create and update tickets"
46304
+ }
45719
46305
  }
45720
46306
  ]
45721
46307
  };
@@ -45793,7 +46379,19 @@ var shopifyTemplate = {
45793
46379
  authorizationUrl: "https://{subdomain}.myshopify.com/admin/oauth/authorize",
45794
46380
  tokenUrl: "https://{subdomain}.myshopify.com/admin/oauth/access_token"
45795
46381
  },
45796
- scopes: ["read_products", "write_products", "read_orders", "write_orders"]
46382
+ scopes: ["read_products", "write_products", "read_orders", "write_orders", "read_customers", "write_customers", "read_inventory", "write_inventory", "read_fulfillments", "write_fulfillments"],
46383
+ scopeDescriptions: {
46384
+ "read_products": "Read products and collections",
46385
+ "write_products": "Create and update products",
46386
+ "read_orders": "Read orders and transactions",
46387
+ "write_orders": "Create and update orders",
46388
+ "read_customers": "Read customer information",
46389
+ "write_customers": "Create and update customers",
46390
+ "read_inventory": "Read inventory levels",
46391
+ "write_inventory": "Update inventory levels",
46392
+ "read_fulfillments": "Read fulfillment data",
46393
+ "write_fulfillments": "Create and update fulfillments"
46394
+ }
45797
46395
  }
45798
46396
  ]
45799
46397
  };
@@ -45826,6 +46424,8 @@ var allVendorTemplates = [
45826
46424
  // Payments
45827
46425
  stripeTemplate,
45828
46426
  paypalTemplate,
46427
+ quickbooksTemplate,
46428
+ rampTemplate,
45829
46429
  // Cloud
45830
46430
  awsTemplate,
45831
46431
  // Storage
@@ -45888,6 +46488,9 @@ var VENDOR_ICON_MAP = {
45888
46488
  // Payments
45889
46489
  stripe: "stripe",
45890
46490
  paypal: "paypal",
46491
+ quickbooks: "quickbooks",
46492
+ ramp: null,
46493
+ // No Simple Icon available
45891
46494
  // Email
45892
46495
  sendgrid: "sendgrid",
45893
46496
  mailchimp: "mailchimp",
@@ -45934,6 +46537,8 @@ var FALLBACK_PLACEHOLDERS = {
45934
46537
  // Email (trademark removed)
45935
46538
  sendgrid: { color: "#1A82E2", letter: "S" },
45936
46539
  postmark: { color: "#FFDE00", letter: "P" },
46540
+ // Payments (no Simple Icon available)
46541
+ ramp: { color: "#F2C94C", letter: "R" },
45937
46542
  // Search (no Simple Icon available)
45938
46543
  serper: { color: "#4A90A4", letter: "S" },
45939
46544
  tavily: { color: "#7C3AED", letter: "T" },
@@ -46354,8 +46959,8 @@ function createMessageWithImages(text, imageUrls, role = "user" /* USER */) {
46354
46959
  var execAsync = util.promisify(child_process.exec);
46355
46960
  function cleanupTempFile(filePath) {
46356
46961
  try {
46357
- if (fs16__namespace.existsSync(filePath)) {
46358
- fs16__namespace.unlinkSync(filePath);
46962
+ if (fs17__namespace.existsSync(filePath)) {
46963
+ fs17__namespace.unlinkSync(filePath);
46359
46964
  }
46360
46965
  } catch {
46361
46966
  }
@@ -46406,7 +47011,7 @@ async function readClipboardImageMac() {
46406
47011
  end try
46407
47012
  `;
46408
47013
  const { stdout } = await execAsync(`osascript -e '${script}'`);
46409
- if (stdout.includes("success") || fs16__namespace.existsSync(tempFile)) {
47014
+ if (stdout.includes("success") || fs17__namespace.existsSync(tempFile)) {
46410
47015
  return await convertFileToDataUri(tempFile);
46411
47016
  }
46412
47017
  return {
@@ -46423,14 +47028,14 @@ async function readClipboardImageLinux() {
46423
47028
  try {
46424
47029
  try {
46425
47030
  await execAsync(`xclip -selection clipboard -t image/png -o > "${tempFile}"`);
46426
- if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
47031
+ if (fs17__namespace.existsSync(tempFile) && fs17__namespace.statSync(tempFile).size > 0) {
46427
47032
  return await convertFileToDataUri(tempFile);
46428
47033
  }
46429
47034
  } catch {
46430
47035
  }
46431
47036
  try {
46432
47037
  await execAsync(`wl-paste -t image/png > "${tempFile}"`);
46433
- if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
47038
+ if (fs17__namespace.existsSync(tempFile) && fs17__namespace.statSync(tempFile).size > 0) {
46434
47039
  return await convertFileToDataUri(tempFile);
46435
47040
  }
46436
47041
  } catch {
@@ -46457,7 +47062,7 @@ async function readClipboardImageWindows() {
46457
47062
  }
46458
47063
  `;
46459
47064
  await execAsync(`powershell -Command "${psScript}"`);
46460
- if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
47065
+ if (fs17__namespace.existsSync(tempFile) && fs17__namespace.statSync(tempFile).size > 0) {
46461
47066
  return await convertFileToDataUri(tempFile);
46462
47067
  }
46463
47068
  return {
@@ -46470,7 +47075,7 @@ async function readClipboardImageWindows() {
46470
47075
  }
46471
47076
  async function convertFileToDataUri(filePath) {
46472
47077
  try {
46473
- const imageBuffer = fs16__namespace.readFileSync(filePath);
47078
+ const imageBuffer = fs17__namespace.readFileSync(filePath);
46474
47079
  const base64Image = imageBuffer.toString("base64");
46475
47080
  const magic = imageBuffer.slice(0, 4).toString("hex");
46476
47081
  let mimeType = "image/png";
@@ -46726,6 +47331,13 @@ __export(tools_exports, {
46726
47331
  bash: () => bash,
46727
47332
  createBashTool: () => createBashTool,
46728
47333
  createCreatePRTool: () => createCreatePRTool,
47334
+ createCustomToolDelete: () => createCustomToolDelete,
47335
+ createCustomToolDraft: () => createCustomToolDraft,
47336
+ createCustomToolList: () => createCustomToolList,
47337
+ createCustomToolLoad: () => createCustomToolLoad,
47338
+ createCustomToolMetaTools: () => createCustomToolMetaTools,
47339
+ createCustomToolSave: () => createCustomToolSave,
47340
+ createCustomToolTest: () => createCustomToolTest,
46729
47341
  createDesktopGetCursorTool: () => createDesktopGetCursorTool,
46730
47342
  createDesktopGetScreenSizeTool: () => createDesktopGetScreenSizeTool,
46731
47343
  createDesktopKeyboardKeyTool: () => createDesktopKeyboardKeyTool,
@@ -46756,6 +47368,12 @@ __export(tools_exports, {
46756
47368
  createWebScrapeTool: () => createWebScrapeTool,
46757
47369
  createWebSearchTool: () => createWebSearchTool,
46758
47370
  createWriteFileTool: () => createWriteFileTool,
47371
+ customToolDelete: () => customToolDelete,
47372
+ customToolDraft: () => customToolDraft,
47373
+ customToolList: () => customToolList,
47374
+ customToolLoad: () => customToolLoad,
47375
+ customToolSave: () => customToolSave,
47376
+ customToolTest: () => customToolTest,
46759
47377
  desktopGetCursor: () => desktopGetCursor,
46760
47378
  desktopGetScreenSize: () => desktopGetScreenSize,
46761
47379
  desktopKeyboardKey: () => desktopKeyboardKey,
@@ -46770,6 +47388,7 @@ __export(tools_exports, {
46770
47388
  desktopWindowList: () => desktopWindowList,
46771
47389
  developerTools: () => developerTools,
46772
47390
  editFile: () => editFile,
47391
+ executeInVM: () => executeInVM,
46773
47392
  executeJavaScript: () => executeJavaScript,
46774
47393
  expandTilde: () => expandTilde,
46775
47394
  getAllBuiltInTools: () => getAllBuiltInTools,
@@ -46784,6 +47403,7 @@ __export(tools_exports, {
46784
47403
  getToolsRequiringConnector: () => getToolsRequiringConnector,
46785
47404
  glob: () => glob,
46786
47405
  grep: () => grep,
47406
+ hydrateCustomTool: () => hydrateCustomTool,
46787
47407
  isBlockedCommand: () => isBlockedCommand,
46788
47408
  isExcludedExtension: () => isExcludedExtension,
46789
47409
  jsonManipulator: () => jsonManipulator,
@@ -47004,7 +47624,7 @@ EXAMPLES:
47004
47624
  };
47005
47625
  }
47006
47626
  const resolvedPath = validation.resolvedPath;
47007
- if (!fs16.existsSync(resolvedPath)) {
47627
+ if (!fs17.existsSync(resolvedPath)) {
47008
47628
  return {
47009
47629
  success: false,
47010
47630
  error: `File not found: ${file_path}`,
@@ -47012,7 +47632,7 @@ EXAMPLES:
47012
47632
  };
47013
47633
  }
47014
47634
  try {
47015
- const stats = await fs15.stat(resolvedPath);
47635
+ const stats = await fs16.stat(resolvedPath);
47016
47636
  if (!stats.isFile()) {
47017
47637
  return {
47018
47638
  success: false,
@@ -47054,7 +47674,7 @@ EXAMPLES:
47054
47674
  } catch {
47055
47675
  }
47056
47676
  }
47057
- const content = await fs15.readFile(resolvedPath, "utf-8");
47677
+ const content = await fs16.readFile(resolvedPath, "utf-8");
47058
47678
  const allLines = content.split("\n");
47059
47679
  const totalLines = allLines.length;
47060
47680
  const startIndex = Math.max(0, offset - 1);
@@ -47159,13 +47779,13 @@ EXAMPLES:
47159
47779
  };
47160
47780
  }
47161
47781
  const resolvedPath = validation.resolvedPath;
47162
- const fileExists = fs16.existsSync(resolvedPath);
47782
+ const fileExists = fs17.existsSync(resolvedPath);
47163
47783
  try {
47164
47784
  const parentDir = path2.dirname(resolvedPath);
47165
- if (!fs16.existsSync(parentDir)) {
47166
- await fs15.mkdir(parentDir, { recursive: true });
47785
+ if (!fs17.existsSync(parentDir)) {
47786
+ await fs16.mkdir(parentDir, { recursive: true });
47167
47787
  }
47168
- await fs15.writeFile(resolvedPath, content, "utf-8");
47788
+ await fs16.writeFile(resolvedPath, content, "utf-8");
47169
47789
  return {
47170
47790
  success: true,
47171
47791
  path: file_path,
@@ -47268,7 +47888,7 @@ EXAMPLES:
47268
47888
  };
47269
47889
  }
47270
47890
  const resolvedPath = validation.resolvedPath;
47271
- if (!fs16.existsSync(resolvedPath)) {
47891
+ if (!fs17.existsSync(resolvedPath)) {
47272
47892
  return {
47273
47893
  success: false,
47274
47894
  error: `File not found: ${file_path}`,
@@ -47276,7 +47896,7 @@ EXAMPLES:
47276
47896
  };
47277
47897
  }
47278
47898
  try {
47279
- const content = await fs15.readFile(resolvedPath, "utf-8");
47899
+ const content = await fs16.readFile(resolvedPath, "utf-8");
47280
47900
  let occurrences = 0;
47281
47901
  let searchIndex = 0;
47282
47902
  while (true) {
@@ -47315,7 +47935,7 @@ EXAMPLES:
47315
47935
  } else {
47316
47936
  newContent = content.replace(old_string, new_string);
47317
47937
  }
47318
- await fs15.writeFile(resolvedPath, newContent, "utf-8");
47938
+ await fs16.writeFile(resolvedPath, newContent, "utf-8");
47319
47939
  const diffPreview = generateDiffPreview(old_string, new_string);
47320
47940
  return {
47321
47941
  success: true,
@@ -47371,7 +47991,7 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
47371
47991
  return results;
47372
47992
  }
47373
47993
  try {
47374
- const entries = await fs15.readdir(dir, { withFileTypes: true });
47994
+ const entries = await fs16.readdir(dir, { withFileTypes: true });
47375
47995
  for (const entry of entries) {
47376
47996
  if (results.length >= config.maxResults) break;
47377
47997
  const fullPath = path2.join(dir, entry.name);
@@ -47385,7 +48005,7 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
47385
48005
  } else if (entry.isFile()) {
47386
48006
  if (matchGlobPattern(pattern, relativePath)) {
47387
48007
  try {
47388
- const stats = await fs15.stat(fullPath);
48008
+ const stats = await fs16.stat(fullPath);
47389
48009
  results.push({
47390
48010
  path: relativePath,
47391
48011
  mtime: stats.mtimeMs
@@ -47467,7 +48087,7 @@ WHEN TO USE:
47467
48087
  };
47468
48088
  }
47469
48089
  const resolvedDir = validation.resolvedPath;
47470
- if (!fs16.existsSync(resolvedDir)) {
48090
+ if (!fs17.existsSync(resolvedDir)) {
47471
48091
  return {
47472
48092
  success: false,
47473
48093
  error: `Directory not found: ${searchDir}`
@@ -47522,7 +48142,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
47522
48142
  return files;
47523
48143
  }
47524
48144
  try {
47525
- const entries = await fs15.readdir(dir, { withFileTypes: true });
48145
+ const entries = await fs16.readdir(dir, { withFileTypes: true });
47526
48146
  for (const entry of entries) {
47527
48147
  const fullPath = path2.join(dir, entry.name);
47528
48148
  if (entry.isDirectory()) {
@@ -47555,7 +48175,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
47555
48175
  async function searchFile(filePath, regex, contextBefore, contextAfter) {
47556
48176
  const matches = [];
47557
48177
  try {
47558
- const content = await fs15.readFile(filePath, "utf-8");
48178
+ const content = await fs16.readFile(filePath, "utf-8");
47559
48179
  const lines = content.split("\n");
47560
48180
  for (let i = 0; i < lines.length; i++) {
47561
48181
  const line = lines[i] ?? "";
@@ -47696,7 +48316,7 @@ WHEN TO USE:
47696
48316
  };
47697
48317
  }
47698
48318
  const resolvedPath = validation.resolvedPath;
47699
- if (!fs16.existsSync(resolvedPath)) {
48319
+ if (!fs17.existsSync(resolvedPath)) {
47700
48320
  return {
47701
48321
  success: false,
47702
48322
  error: `Path not found: ${searchPath}`
@@ -47712,7 +48332,7 @@ WHEN TO USE:
47712
48332
  };
47713
48333
  }
47714
48334
  try {
47715
- const stats = await fs15.stat(resolvedPath);
48335
+ const stats = await fs16.stat(resolvedPath);
47716
48336
  let filesToSearch;
47717
48337
  if (stats.isFile()) {
47718
48338
  filesToSearch = [resolvedPath];
@@ -47800,7 +48420,7 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
47800
48420
  return entries;
47801
48421
  }
47802
48422
  try {
47803
- const dirEntries = await fs15.readdir(dir, { withFileTypes: true });
48423
+ const dirEntries = await fs16.readdir(dir, { withFileTypes: true });
47804
48424
  for (const entry of dirEntries) {
47805
48425
  if (entries.length >= config.maxResults) break;
47806
48426
  const fullPath = path2.join(dir, entry.name);
@@ -47818,7 +48438,7 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
47818
48438
  }
47819
48439
  if (filter === "directories" && !isDir) continue;
47820
48440
  try {
47821
- const stats = await fs15.stat(fullPath);
48441
+ const stats = await fs16.stat(fullPath);
47822
48442
  const dirEntry = {
47823
48443
  name: entry.name,
47824
48444
  path: relativePath,
@@ -47914,14 +48534,14 @@ EXAMPLES:
47914
48534
  };
47915
48535
  }
47916
48536
  const resolvedPath = validation.resolvedPath;
47917
- if (!fs16.existsSync(resolvedPath)) {
48537
+ if (!fs17.existsSync(resolvedPath)) {
47918
48538
  return {
47919
48539
  success: false,
47920
48540
  error: `Directory not found: ${path6}`
47921
48541
  };
47922
48542
  }
47923
48543
  try {
47924
- const stats = await fs15.stat(resolvedPath);
48544
+ const stats = await fs16.stat(resolvedPath);
47925
48545
  if (!stats.isDirectory()) {
47926
48546
  return {
47927
48547
  success: false,
@@ -51691,6 +52311,498 @@ var desktopTools = [
51691
52311
  desktopWindowFocus
51692
52312
  ];
51693
52313
 
52314
+ // src/tools/custom-tools/customToolDelete.ts
52315
+ function createCustomToolDelete(storage) {
52316
+ return {
52317
+ definition: {
52318
+ type: "function",
52319
+ function: {
52320
+ name: "custom_tool_delete",
52321
+ description: "Delete a custom tool from persistent storage.",
52322
+ parameters: {
52323
+ type: "object",
52324
+ properties: {
52325
+ name: {
52326
+ type: "string",
52327
+ description: "Name of the tool to delete"
52328
+ }
52329
+ },
52330
+ required: ["name"]
52331
+ }
52332
+ }
52333
+ },
52334
+ permission: { scope: "session", riskLevel: "medium" },
52335
+ execute: async (args) => {
52336
+ try {
52337
+ const exists = await storage.exists(args.name);
52338
+ if (!exists) {
52339
+ return { success: false, name: args.name, error: `Custom tool '${args.name}' not found` };
52340
+ }
52341
+ await storage.delete(args.name);
52342
+ return { success: true, name: args.name };
52343
+ } catch (error) {
52344
+ return { success: false, name: args.name, error: error.message };
52345
+ }
52346
+ },
52347
+ describeCall: (args) => args.name
52348
+ };
52349
+ }
52350
+ var customToolDelete = createCustomToolDelete(new FileCustomToolStorage());
52351
+
52352
+ // src/tools/custom-tools/sandboxDescription.ts
52353
+ init_Connector();
52354
+ function formatConnectorEntry2(c) {
52355
+ const parts = [];
52356
+ const serviceOrVendor = c.serviceType ?? c.vendor ?? void 0;
52357
+ if (serviceOrVendor) parts.push(`Service: ${serviceOrVendor}`);
52358
+ if (c.config.description) parts.push(c.config.description);
52359
+ if (c.baseURL) parts.push(`URL: ${c.baseURL}`);
52360
+ const details = parts.map((p) => ` ${p}`).join("\n");
52361
+ return ` \u2022 "${c.name}" (${c.displayName})
52362
+ ${details}`;
52363
+ }
52364
+ function buildConnectorList(context) {
52365
+ const registry = context?.connectorRegistry ?? exports.Connector.asRegistry();
52366
+ const connectors = registry.listAll();
52367
+ if (connectors.length === 0) {
52368
+ return " No connectors registered.";
52369
+ }
52370
+ return connectors.map(formatConnectorEntry2).join("\n\n");
52371
+ }
52372
+ var SANDBOX_API_REFERENCE = `SANDBOX API (available inside custom tool code):
52373
+
52374
+ 1. authenticatedFetch(url, options, connectorName)
52375
+ Makes authenticated HTTP requests using the connector's credentials.
52376
+ Auth headers are added automatically \u2014 DO NOT set Authorization header manually.
52377
+
52378
+ Parameters:
52379
+ \u2022 url: Full URL or path relative to the connector's base URL
52380
+ - Full: "https://api.github.com/user/repos"
52381
+ - Relative: "/user/repos" (resolved against connector's base URL)
52382
+ \u2022 options: Standard fetch options { method, headers, body }
52383
+ - For POST/PUT: set body to JSON.stringify(data) and headers to { 'Content-Type': 'application/json' }
52384
+ \u2022 connectorName: Name of a registered connector (see REGISTERED CONNECTORS below)
52385
+
52386
+ Returns: Promise<Response>
52387
+ \u2022 response.ok \u2014 true if status 200-299
52388
+ \u2022 response.status \u2014 HTTP status code
52389
+ \u2022 await response.json() \u2014 parse JSON body
52390
+ \u2022 await response.text() \u2014 get text body
52391
+
52392
+ 2. fetch(url, options) \u2014 Standard fetch without authentication
52393
+
52394
+ 3. connectors.list() \u2014 Array of available connector names
52395
+ 4. connectors.get(name) \u2014 Connector info: { displayName, description, baseURL, serviceType }
52396
+
52397
+ VARIABLES:
52398
+ \u2022 input \u2014 the tool's input arguments (matches inputSchema)
52399
+ \u2022 output \u2014 SET THIS to return the tool's result to the caller
52400
+
52401
+ GLOBALS: console.log/error/warn, JSON, Math, Date, Buffer, Promise, Array, Object, String, Number, Boolean, setTimeout, setInterval, URL, URLSearchParams, RegExp, Map, Set, Error, TextEncoder, TextDecoder
52402
+
52403
+ LIMITS: No file system access, no require/import. Code runs in async context (await is available).`;
52404
+ function buildDraftDescription(context) {
52405
+ const connectorList = buildConnectorList(context);
52406
+ return `Validate a draft custom tool definition. Checks name format, schema structure, and code syntax.
52407
+
52408
+ When writing the "code" field, you have access to the full VM sandbox:
52409
+
52410
+ ${SANDBOX_API_REFERENCE}
52411
+
52412
+ REGISTERED CONNECTORS:
52413
+ ${connectorList}
52414
+
52415
+ CODE EXAMPLES:
52416
+
52417
+ // Simple data processing tool
52418
+ const items = input.data;
52419
+ output = items.filter(i => i.score > 0.8).sort((a, b) => b.score - a.score);
52420
+
52421
+ // API tool using a connector
52422
+ const resp = await authenticatedFetch('/user/repos', { method: 'GET' }, 'github');
52423
+ const repos = await resp.json();
52424
+ output = repos.map(r => ({ name: r.full_name, stars: r.stargazers_count }));
52425
+
52426
+ // Tool that chains multiple API calls
52427
+ const users = await (await authenticatedFetch('/users', {}, 'my-api')).json();
52428
+ const enriched = await Promise.all(users.map(async u => {
52429
+ const details = await (await authenticatedFetch(\`/users/\${u.id}\`, {}, 'my-api')).json();
52430
+ return { ...u, ...details };
52431
+ }));
52432
+ output = enriched;`;
52433
+ }
52434
+ function buildTestDescription(context) {
52435
+ const connectorList = buildConnectorList(context);
52436
+ return `Test custom tool code by executing it in the VM sandbox with provided test input. Returns execution result, captured logs, and timing.
52437
+
52438
+ The code runs in the same sandbox as execute_javascript:
52439
+
52440
+ ${SANDBOX_API_REFERENCE}
52441
+
52442
+ REGISTERED CONNECTORS:
52443
+ ${connectorList}
52444
+
52445
+ The testInput you provide will be available as the \`input\` variable in the code.
52446
+ Set \`output\` to the value you want returned.`;
52447
+ }
52448
+
52449
+ // src/tools/custom-tools/customToolDraft.ts
52450
+ var NAME_PATTERN = /^[a-z][a-z0-9_]*$/;
52451
+ function createCustomToolDraft() {
52452
+ return {
52453
+ definition: {
52454
+ type: "function",
52455
+ function: {
52456
+ name: "custom_tool_draft",
52457
+ description: "Validate a draft custom tool definition. Checks name format, schema structure, and code syntax.",
52458
+ parameters: {
52459
+ type: "object",
52460
+ properties: {
52461
+ name: {
52462
+ type: "string",
52463
+ description: 'Tool name (lowercase, underscores, must start with letter). Example: "fetch_weather"'
52464
+ },
52465
+ description: {
52466
+ type: "string",
52467
+ description: "What the tool does"
52468
+ },
52469
+ inputSchema: {
52470
+ type: "object",
52471
+ description: 'JSON Schema for the tool input (must have type: "object")'
52472
+ },
52473
+ outputSchema: {
52474
+ type: "object",
52475
+ description: "Optional JSON Schema for the tool output (documentation only)"
52476
+ },
52477
+ code: {
52478
+ type: "string",
52479
+ description: "JavaScript code that reads `input` and sets `output`. Runs in the same sandbox as execute_javascript. See tool description for full API reference."
52480
+ },
52481
+ tags: {
52482
+ type: "array",
52483
+ description: "Optional tags for categorization",
52484
+ items: { type: "string" }
52485
+ },
52486
+ connectorName: {
52487
+ type: "string",
52488
+ description: "Optional connector name if the tool requires API access"
52489
+ }
52490
+ },
52491
+ required: ["name", "description", "inputSchema", "code"]
52492
+ }
52493
+ }
52494
+ },
52495
+ descriptionFactory: (context) => buildDraftDescription(context),
52496
+ permission: { scope: "always", riskLevel: "low" },
52497
+ execute: async (args) => {
52498
+ const errors = [];
52499
+ if (!args.name || typeof args.name !== "string") {
52500
+ errors.push("name is required and must be a string");
52501
+ } else if (!NAME_PATTERN.test(args.name)) {
52502
+ errors.push(
52503
+ `name "${args.name}" is invalid. Must match /^[a-z][a-z0-9_]*$/ (lowercase, underscores, start with letter)`
52504
+ );
52505
+ }
52506
+ if (!args.description || typeof args.description !== "string" || args.description.trim().length === 0) {
52507
+ errors.push("description is required and must be a non-empty string");
52508
+ }
52509
+ if (!args.inputSchema || typeof args.inputSchema !== "object") {
52510
+ errors.push("inputSchema is required and must be an object");
52511
+ } else if (args.inputSchema.type !== "object") {
52512
+ errors.push('inputSchema.type must be "object"');
52513
+ }
52514
+ if (!args.code || typeof args.code !== "string" || args.code.trim().length === 0) {
52515
+ errors.push("code is required and must be a non-empty string");
52516
+ } else {
52517
+ try {
52518
+ new Function(args.code);
52519
+ } catch (e) {
52520
+ errors.push(`code has syntax error: ${e.message}`);
52521
+ }
52522
+ }
52523
+ if (errors.length > 0) {
52524
+ return { success: false, errors };
52525
+ }
52526
+ return {
52527
+ success: true,
52528
+ validated: {
52529
+ name: args.name,
52530
+ description: args.description,
52531
+ inputSchema: args.inputSchema,
52532
+ outputSchema: args.outputSchema,
52533
+ code: args.code,
52534
+ tags: args.tags,
52535
+ connectorName: args.connectorName
52536
+ }
52537
+ };
52538
+ },
52539
+ describeCall: (args) => args.name ?? "unknown"
52540
+ };
52541
+ }
52542
+ var customToolDraft = createCustomToolDraft();
52543
+
52544
+ // src/tools/custom-tools/customToolList.ts
52545
+ function createCustomToolList(storage) {
52546
+ return {
52547
+ definition: {
52548
+ type: "function",
52549
+ function: {
52550
+ name: "custom_tool_list",
52551
+ description: "List saved custom tools from persistent storage. Supports filtering by search text, tags, and category.",
52552
+ parameters: {
52553
+ type: "object",
52554
+ properties: {
52555
+ search: {
52556
+ type: "string",
52557
+ description: "Search text (case-insensitive substring match on name + description)"
52558
+ },
52559
+ tags: {
52560
+ type: "array",
52561
+ description: "Filter by tags (any match)",
52562
+ items: { type: "string" }
52563
+ },
52564
+ category: {
52565
+ type: "string",
52566
+ description: "Filter by category"
52567
+ },
52568
+ limit: {
52569
+ type: "number",
52570
+ description: "Maximum number of results"
52571
+ },
52572
+ offset: {
52573
+ type: "number",
52574
+ description: "Offset for pagination"
52575
+ }
52576
+ }
52577
+ }
52578
+ }
52579
+ },
52580
+ permission: { scope: "always", riskLevel: "low" },
52581
+ execute: async (args) => {
52582
+ const tools = await storage.list({
52583
+ search: args.search,
52584
+ tags: args.tags,
52585
+ category: args.category,
52586
+ limit: args.limit,
52587
+ offset: args.offset
52588
+ });
52589
+ return { tools, total: tools.length };
52590
+ },
52591
+ describeCall: (args) => args.search ?? "all tools"
52592
+ };
52593
+ }
52594
+ var customToolList = createCustomToolList(new FileCustomToolStorage());
52595
+
52596
+ // src/tools/custom-tools/customToolLoad.ts
52597
+ function createCustomToolLoad(storage) {
52598
+ return {
52599
+ definition: {
52600
+ type: "function",
52601
+ function: {
52602
+ name: "custom_tool_load",
52603
+ description: "Load a full custom tool definition from storage (including code). Use this to inspect, modify, or hydrate a saved tool.",
52604
+ parameters: {
52605
+ type: "object",
52606
+ properties: {
52607
+ name: {
52608
+ type: "string",
52609
+ description: "Name of the tool to load"
52610
+ }
52611
+ },
52612
+ required: ["name"]
52613
+ }
52614
+ }
52615
+ },
52616
+ permission: { scope: "always", riskLevel: "low" },
52617
+ execute: async (args) => {
52618
+ const tool = await storage.load(args.name);
52619
+ if (!tool) {
52620
+ return { success: false, error: `Custom tool '${args.name}' not found` };
52621
+ }
52622
+ return { success: true, tool };
52623
+ },
52624
+ describeCall: (args) => args.name
52625
+ };
52626
+ }
52627
+ var customToolLoad = createCustomToolLoad(new FileCustomToolStorage());
52628
+
52629
+ // src/tools/custom-tools/customToolSave.ts
52630
+ function createCustomToolSave(storage) {
52631
+ return {
52632
+ definition: {
52633
+ type: "function",
52634
+ function: {
52635
+ name: "custom_tool_save",
52636
+ description: "Save a custom tool definition to persistent storage. The tool can later be loaded, hydrated, and registered on any agent.",
52637
+ parameters: {
52638
+ type: "object",
52639
+ properties: {
52640
+ name: {
52641
+ type: "string",
52642
+ description: "Tool name (must match /^[a-z][a-z0-9_]*$/)"
52643
+ },
52644
+ description: {
52645
+ type: "string",
52646
+ description: "What the tool does"
52647
+ },
52648
+ displayName: {
52649
+ type: "string",
52650
+ description: "Optional human-readable display name"
52651
+ },
52652
+ inputSchema: {
52653
+ type: "object",
52654
+ description: "JSON Schema for input parameters"
52655
+ },
52656
+ outputSchema: {
52657
+ type: "object",
52658
+ description: "Optional JSON Schema for output"
52659
+ },
52660
+ code: {
52661
+ type: "string",
52662
+ description: "JavaScript code (same sandbox as execute_javascript)"
52663
+ },
52664
+ tags: {
52665
+ type: "array",
52666
+ description: "Tags for categorization",
52667
+ items: { type: "string" }
52668
+ },
52669
+ category: {
52670
+ type: "string",
52671
+ description: "Category grouping"
52672
+ },
52673
+ generationPrompt: {
52674
+ type: "string",
52675
+ description: "The prompt that was used to generate this tool (for reference)"
52676
+ },
52677
+ connectorNames: {
52678
+ type: "array",
52679
+ description: "Connector names this tool uses",
52680
+ items: { type: "string" }
52681
+ }
52682
+ },
52683
+ required: ["name", "description", "inputSchema", "code"]
52684
+ }
52685
+ }
52686
+ },
52687
+ permission: { scope: "session", riskLevel: "medium" },
52688
+ execute: async (args) => {
52689
+ try {
52690
+ const now = (/* @__PURE__ */ new Date()).toISOString();
52691
+ const existing = await storage.load(args.name);
52692
+ const definition = {
52693
+ version: CUSTOM_TOOL_DEFINITION_VERSION,
52694
+ name: args.name,
52695
+ displayName: args.displayName,
52696
+ description: args.description,
52697
+ inputSchema: args.inputSchema,
52698
+ outputSchema: args.outputSchema,
52699
+ code: args.code,
52700
+ createdAt: existing?.createdAt ?? now,
52701
+ updatedAt: now,
52702
+ metadata: {
52703
+ tags: args.tags,
52704
+ category: args.category,
52705
+ generationPrompt: args.generationPrompt,
52706
+ connectorNames: args.connectorNames,
52707
+ requiresConnector: (args.connectorNames?.length ?? 0) > 0
52708
+ }
52709
+ };
52710
+ await storage.save(definition);
52711
+ return {
52712
+ success: true,
52713
+ name: args.name,
52714
+ storagePath: storage.getPath()
52715
+ };
52716
+ } catch (error) {
52717
+ return {
52718
+ success: false,
52719
+ name: args.name,
52720
+ storagePath: storage.getPath(),
52721
+ error: error.message
52722
+ };
52723
+ }
52724
+ },
52725
+ describeCall: (args) => args.name
52726
+ };
52727
+ }
52728
+ var customToolSave = createCustomToolSave(new FileCustomToolStorage());
52729
+
52730
+ // src/tools/custom-tools/customToolTest.ts
52731
+ init_Connector();
52732
+ var DEFAULT_TEST_TIMEOUT = 1e4;
52733
+ var MAX_TEST_TIMEOUT = 3e4;
52734
+ function createCustomToolTest() {
52735
+ return {
52736
+ definition: {
52737
+ type: "function",
52738
+ function: {
52739
+ name: "custom_tool_test",
52740
+ description: "Test custom tool code by executing it in the VM sandbox with provided test input.",
52741
+ parameters: {
52742
+ type: "object",
52743
+ properties: {
52744
+ code: {
52745
+ type: "string",
52746
+ description: "JavaScript code to test. See tool description for full sandbox API reference."
52747
+ },
52748
+ inputSchema: {
52749
+ type: "object",
52750
+ description: "The input schema (for documentation, not enforced at test time)"
52751
+ },
52752
+ testInput: {
52753
+ description: "Test input data \u2014 available as `input` in the code"
52754
+ },
52755
+ connectorName: {
52756
+ type: "string",
52757
+ description: "Optional connector name for authenticated API access"
52758
+ },
52759
+ timeout: {
52760
+ type: "number",
52761
+ description: `Execution timeout in ms. Default: ${DEFAULT_TEST_TIMEOUT}, max: ${MAX_TEST_TIMEOUT}`
52762
+ }
52763
+ },
52764
+ required: ["code", "inputSchema", "testInput"]
52765
+ }
52766
+ },
52767
+ timeout: MAX_TEST_TIMEOUT + 5e3
52768
+ },
52769
+ descriptionFactory: (context) => buildTestDescription(context),
52770
+ permission: { scope: "session", riskLevel: "medium" },
52771
+ execute: async (args, context) => {
52772
+ const logs = [];
52773
+ const startTime = Date.now();
52774
+ const timeout = Math.min(Math.max(args.timeout || DEFAULT_TEST_TIMEOUT, 0), MAX_TEST_TIMEOUT);
52775
+ try {
52776
+ const registry = context?.connectorRegistry ?? exports.Connector.asRegistry();
52777
+ const result = await executeInVM(
52778
+ args.code,
52779
+ args.testInput,
52780
+ timeout,
52781
+ logs,
52782
+ context?.userId,
52783
+ registry
52784
+ );
52785
+ return {
52786
+ success: true,
52787
+ result,
52788
+ logs,
52789
+ executionTime: Date.now() - startTime
52790
+ };
52791
+ } catch (error) {
52792
+ return {
52793
+ success: false,
52794
+ result: null,
52795
+ logs,
52796
+ error: error.message,
52797
+ executionTime: Date.now() - startTime
52798
+ };
52799
+ }
52800
+ },
52801
+ describeCall: (args) => `testing code (${args.code.length} chars)`
52802
+ };
52803
+ }
52804
+ var customToolTest = createCustomToolTest();
52805
+
51694
52806
  // src/tools/registry.generated.ts
51695
52807
  var toolRegistry = [
51696
52808
  {
@@ -51702,6 +52814,60 @@ var toolRegistry = [
51702
52814
  tool: executeJavaScript,
51703
52815
  safeByDefault: false
51704
52816
  },
52817
+ {
52818
+ name: "custom_tool_delete",
52819
+ exportName: "customToolDelete",
52820
+ displayName: "Custom Tool Delete",
52821
+ category: "custom-tools",
52822
+ description: "Delete a custom tool from persistent storage.",
52823
+ tool: customToolDelete,
52824
+ safeByDefault: false
52825
+ },
52826
+ {
52827
+ name: "custom_tool_draft",
52828
+ exportName: "customToolDraft",
52829
+ displayName: "Custom Tool Draft",
52830
+ category: "custom-tools",
52831
+ description: "Validate a draft custom tool definition. Checks name format, schema structure, and code syntax.",
52832
+ tool: customToolDraft,
52833
+ safeByDefault: true
52834
+ },
52835
+ {
52836
+ name: "custom_tool_list",
52837
+ exportName: "customToolList",
52838
+ displayName: "Custom Tool List",
52839
+ category: "custom-tools",
52840
+ description: "List saved custom tools from persistent storage. Supports filtering by search text, tags, and category.",
52841
+ tool: customToolList,
52842
+ safeByDefault: true
52843
+ },
52844
+ {
52845
+ name: "custom_tool_load",
52846
+ exportName: "customToolLoad",
52847
+ displayName: "Custom Tool Load",
52848
+ category: "custom-tools",
52849
+ description: "Load a full custom tool definition from storage (including code).",
52850
+ tool: customToolLoad,
52851
+ safeByDefault: true
52852
+ },
52853
+ {
52854
+ name: "custom_tool_save",
52855
+ exportName: "customToolSave",
52856
+ displayName: "Custom Tool Save",
52857
+ category: "custom-tools",
52858
+ description: "Save a custom tool definition to persistent storage.",
52859
+ tool: customToolSave,
52860
+ safeByDefault: false
52861
+ },
52862
+ {
52863
+ name: "custom_tool_test",
52864
+ exportName: "customToolTest",
52865
+ displayName: "Custom Tool Test",
52866
+ category: "custom-tools",
52867
+ description: "Test custom tool code by executing it in the VM sandbox with provided test input.",
52868
+ tool: customToolTest,
52869
+ safeByDefault: false
52870
+ },
51705
52871
  {
51706
52872
  name: "desktop_get_cursor",
51707
52873
  exportName: "desktopGetCursor",
@@ -51902,6 +53068,61 @@ function getToolCategories() {
51902
53068
  return [...new Set(toolRegistry.map((entry) => entry.category))];
51903
53069
  }
51904
53070
 
53071
+ // src/tools/custom-tools/factories.ts
53072
+ function createCustomToolMetaTools(options) {
53073
+ const storage = options?.storage ?? new FileCustomToolStorage();
53074
+ return [
53075
+ createCustomToolDraft(),
53076
+ createCustomToolTest(),
53077
+ createCustomToolSave(storage),
53078
+ createCustomToolList(storage),
53079
+ createCustomToolLoad(storage),
53080
+ createCustomToolDelete(storage)
53081
+ ];
53082
+ }
53083
+
53084
+ // src/tools/custom-tools/hydrate.ts
53085
+ init_Connector();
53086
+ var DEFAULT_TIMEOUT2 = 1e4;
53087
+ var MAX_TIMEOUT = 3e4;
53088
+ function hydrateCustomTool(definition, options) {
53089
+ const defaultTimeout = options?.defaultTimeout ?? DEFAULT_TIMEOUT2;
53090
+ const maxTimeout = options?.maxTimeout ?? MAX_TIMEOUT;
53091
+ return {
53092
+ definition: {
53093
+ type: "function",
53094
+ function: {
53095
+ name: definition.name,
53096
+ description: definition.description,
53097
+ parameters: definition.inputSchema
53098
+ },
53099
+ timeout: maxTimeout + 5e3
53100
+ },
53101
+ permission: { scope: "session", riskLevel: "medium" },
53102
+ execute: async (args, context) => {
53103
+ const logs = [];
53104
+ const registry = context?.connectorRegistry ?? exports.Connector.asRegistry();
53105
+ const result = await executeInVM(
53106
+ definition.code,
53107
+ args,
53108
+ defaultTimeout,
53109
+ logs,
53110
+ context?.userId,
53111
+ registry
53112
+ );
53113
+ return result;
53114
+ },
53115
+ describeCall: (args) => {
53116
+ if (!args || typeof args !== "object") return definition.name;
53117
+ const firstKey = Object.keys(args)[0];
53118
+ if (!firstKey) return definition.name;
53119
+ const val = args[firstKey];
53120
+ const str = typeof val === "string" ? val : JSON.stringify(val);
53121
+ return str.length > 50 ? str.slice(0, 47) + "..." : str;
53122
+ }
53123
+ };
53124
+ }
53125
+
51905
53126
  // src/tools/ToolRegistry.ts
51906
53127
  init_Connector();
51907
53128
  var ToolRegistry = class {
@@ -52251,6 +53472,7 @@ exports.BaseTextProvider = BaseTextProvider;
52251
53472
  exports.BraveProvider = BraveProvider;
52252
53473
  exports.CONNECTOR_CONFIG_VERSION = CONNECTOR_CONFIG_VERSION;
52253
53474
  exports.CONTEXT_SESSION_FORMAT_VERSION = CONTEXT_SESSION_FORMAT_VERSION;
53475
+ exports.CUSTOM_TOOL_DEFINITION_VERSION = CUSTOM_TOOL_DEFINITION_VERSION;
52254
53476
  exports.CheckpointManager = CheckpointManager;
52255
53477
  exports.ConnectorConfigStore = ConnectorConfigStore;
52256
53478
  exports.ConnectorTools = ConnectorTools;
@@ -52278,6 +53500,7 @@ exports.ExternalDependencyHandler = ExternalDependencyHandler;
52278
53500
  exports.FileAgentDefinitionStorage = FileAgentDefinitionStorage;
52279
53501
  exports.FileConnectorStorage = FileConnectorStorage;
52280
53502
  exports.FileContextStorage = FileContextStorage;
53503
+ exports.FileCustomToolStorage = FileCustomToolStorage;
52281
53504
  exports.FileMediaOutputHandler = FileMediaStorage;
52282
53505
  exports.FileMediaStorage = FileMediaStorage;
52283
53506
  exports.FilePersistentInstructionsStorage = FilePersistentInstructionsStorage;
@@ -52388,6 +53611,13 @@ exports.createAuthenticatedFetch = createAuthenticatedFetch;
52388
53611
  exports.createBashTool = createBashTool;
52389
53612
  exports.createConnectorFromTemplate = createConnectorFromTemplate;
52390
53613
  exports.createCreatePRTool = createCreatePRTool;
53614
+ exports.createCustomToolDelete = createCustomToolDelete;
53615
+ exports.createCustomToolDraft = createCustomToolDraft;
53616
+ exports.createCustomToolList = createCustomToolList;
53617
+ exports.createCustomToolLoad = createCustomToolLoad;
53618
+ exports.createCustomToolMetaTools = createCustomToolMetaTools;
53619
+ exports.createCustomToolSave = createCustomToolSave;
53620
+ exports.createCustomToolTest = createCustomToolTest;
52391
53621
  exports.createDesktopGetCursorTool = createDesktopGetCursorTool;
52392
53622
  exports.createDesktopGetScreenSizeTool = createDesktopGetScreenSizeTool;
52393
53623
  exports.createDesktopKeyboardKeyTool = createDesktopKeyboardKeyTool;
@@ -52404,6 +53634,7 @@ exports.createEstimator = createEstimator;
52404
53634
  exports.createExecuteJavaScriptTool = createExecuteJavaScriptTool;
52405
53635
  exports.createFileAgentDefinitionStorage = createFileAgentDefinitionStorage;
52406
53636
  exports.createFileContextStorage = createFileContextStorage;
53637
+ exports.createFileCustomToolStorage = createFileCustomToolStorage;
52407
53638
  exports.createFileMediaStorage = createFileMediaStorage;
52408
53639
  exports.createGetPRTool = createGetPRTool;
52409
53640
  exports.createGitHubReadFileTool = createGitHubReadFileTool;
@@ -52428,6 +53659,12 @@ exports.createTextToSpeechTool = createTextToSpeechTool;
52428
53659
  exports.createVideoProvider = createVideoProvider;
52429
53660
  exports.createVideoTools = createVideoTools;
52430
53661
  exports.createWriteFileTool = createWriteFileTool;
53662
+ exports.customToolDelete = customToolDelete;
53663
+ exports.customToolDraft = customToolDraft;
53664
+ exports.customToolList = customToolList;
53665
+ exports.customToolLoad = customToolLoad;
53666
+ exports.customToolSave = customToolSave;
53667
+ exports.customToolTest = customToolTest;
52431
53668
  exports.defaultDescribeCall = defaultDescribeCall;
52432
53669
  exports.desktopGetCursor = desktopGetCursor;
52433
53670
  exports.desktopGetScreenSize = desktopGetScreenSize;
@@ -52512,6 +53749,7 @@ exports.globalErrorHandler = globalErrorHandler;
52512
53749
  exports.grep = grep;
52513
53750
  exports.hasClipboardImage = hasClipboardImage;
52514
53751
  exports.hasVendorLogo = hasVendorLogo;
53752
+ exports.hydrateCustomTool = hydrateCustomTool;
52515
53753
  exports.isBlockedCommand = isBlockedCommand;
52516
53754
  exports.isErrorEvent = isErrorEvent;
52517
53755
  exports.isExcludedExtension = isExcludedExtension;