@everworker/oneringai 0.1.3 → 0.1.4

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,11 +2,11 @@
2
2
 
3
3
  var crypto2 = require('crypto');
4
4
  var jose = require('jose');
5
- var fs15 = require('fs');
5
+ var fs16 = require('fs');
6
6
  var eventemitter3 = require('eventemitter3');
7
- var path3 = require('path');
8
- var os = require('os');
9
- var OpenAI2 = require('openai');
7
+ var path2 = require('path');
8
+ var os2 = require('os');
9
+ var OpenAI3 = require('openai');
10
10
  var Anthropic = require('@anthropic-ai/sdk');
11
11
  var genai = require('@google/genai');
12
12
  require('zod/v3');
@@ -14,7 +14,7 @@ var z4mini = require('zod/v4-mini');
14
14
  var z = require('zod/v4');
15
15
  var process2 = require('process');
16
16
  var stream = require('stream');
17
- var fs14 = require('fs/promises');
17
+ var fs15 = require('fs/promises');
18
18
  var simpleIcons = require('simple-icons');
19
19
  var child_process = require('child_process');
20
20
  var util = require('util');
@@ -44,15 +44,15 @@ function _interopNamespace(e) {
44
44
  }
45
45
 
46
46
  var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
47
- var fs15__namespace = /*#__PURE__*/_interopNamespace(fs15);
48
- var path3__namespace = /*#__PURE__*/_interopNamespace(path3);
49
- var os__namespace = /*#__PURE__*/_interopNamespace(os);
50
- var OpenAI2__default = /*#__PURE__*/_interopDefault(OpenAI2);
47
+ var fs16__namespace = /*#__PURE__*/_interopNamespace(fs16);
48
+ var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
49
+ var os2__namespace = /*#__PURE__*/_interopNamespace(os2);
50
+ var OpenAI3__default = /*#__PURE__*/_interopDefault(OpenAI3);
51
51
  var Anthropic__default = /*#__PURE__*/_interopDefault(Anthropic);
52
52
  var z4mini__namespace = /*#__PURE__*/_interopNamespace(z4mini);
53
53
  var z__namespace = /*#__PURE__*/_interopNamespace(z);
54
54
  var process2__default = /*#__PURE__*/_interopDefault(process2);
55
- var fs14__namespace = /*#__PURE__*/_interopNamespace(fs14);
55
+ var fs15__namespace = /*#__PURE__*/_interopNamespace(fs15);
56
56
  var simpleIcons__namespace = /*#__PURE__*/_interopNamespace(simpleIcons);
57
57
  var TurndownService__default = /*#__PURE__*/_interopDefault(TurndownService);
58
58
  var vm__namespace = /*#__PURE__*/_interopNamespace(vm);
@@ -631,7 +631,7 @@ var init_JWTBearer = __esm({
631
631
  this.privateKey = config.privateKey;
632
632
  } else if (config.privateKeyPath) {
633
633
  try {
634
- this.privateKey = fs15__namespace.readFileSync(config.privateKeyPath, "utf8");
634
+ this.privateKey = fs16__namespace.readFileSync(config.privateKeyPath, "utf8");
635
635
  } catch (error) {
636
636
  throw new Error(`Failed to read private key from ${config.privateKeyPath}: ${error.message}`);
637
637
  }
@@ -1281,11 +1281,11 @@ var init_Logger = __esm({
1281
1281
  */
1282
1282
  initFileStream(filePath) {
1283
1283
  try {
1284
- const dir = path3__namespace.dirname(filePath);
1285
- if (!fs15__namespace.existsSync(dir)) {
1286
- fs15__namespace.mkdirSync(dir, { recursive: true });
1284
+ const dir = path2__namespace.dirname(filePath);
1285
+ if (!fs16__namespace.existsSync(dir)) {
1286
+ fs16__namespace.mkdirSync(dir, { recursive: true });
1287
1287
  }
1288
- this.fileStream = fs15__namespace.createWriteStream(filePath, {
1288
+ this.fileStream = fs16__namespace.createWriteStream(filePath, {
1289
1289
  flags: "a",
1290
1290
  // append mode
1291
1291
  encoding: "utf8"
@@ -14555,12 +14555,12 @@ var require_dist = __commonJS({
14555
14555
  throw new Error(`Unknown format "${name}"`);
14556
14556
  return f;
14557
14557
  };
14558
- function addFormats(ajv, list, fs18, exportName) {
14558
+ function addFormats(ajv, list, fs17, exportName) {
14559
14559
  var _a;
14560
14560
  var _b;
14561
14561
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14562
14562
  for (const f of list)
14563
- ajv.addFormat(f, fs18[f]);
14563
+ ajv.addFormat(f, fs17[f]);
14564
14564
  }
14565
14565
  module.exports = exports$1 = formatsPlugin;
14566
14566
  Object.defineProperty(exports$1, "__esModule", { value: true });
@@ -14573,7 +14573,7 @@ var require_windows = __commonJS({
14573
14573
  "node_modules/isexe/windows.js"(exports$1, module) {
14574
14574
  module.exports = isexe;
14575
14575
  isexe.sync = sync;
14576
- var fs18 = __require("fs");
14576
+ var fs17 = __require("fs");
14577
14577
  function checkPathExt(path6, options) {
14578
14578
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
14579
14579
  if (!pathext) {
@@ -14591,19 +14591,19 @@ var require_windows = __commonJS({
14591
14591
  }
14592
14592
  return false;
14593
14593
  }
14594
- function checkStat(stat5, path6, options) {
14595
- if (!stat5.isSymbolicLink() && !stat5.isFile()) {
14594
+ function checkStat(stat6, path6, options) {
14595
+ if (!stat6.isSymbolicLink() && !stat6.isFile()) {
14596
14596
  return false;
14597
14597
  }
14598
14598
  return checkPathExt(path6, options);
14599
14599
  }
14600
14600
  function isexe(path6, options, cb) {
14601
- fs18.stat(path6, function(er, stat5) {
14602
- cb(er, er ? false : checkStat(stat5, path6, options));
14601
+ fs17.stat(path6, function(er, stat6) {
14602
+ cb(er, er ? false : checkStat(stat6, path6, options));
14603
14603
  });
14604
14604
  }
14605
14605
  function sync(path6, options) {
14606
- return checkStat(fs18.statSync(path6), path6, options);
14606
+ return checkStat(fs17.statSync(path6), path6, options);
14607
14607
  }
14608
14608
  }
14609
14609
  });
@@ -14613,22 +14613,22 @@ var require_mode = __commonJS({
14613
14613
  "node_modules/isexe/mode.js"(exports$1, module) {
14614
14614
  module.exports = isexe;
14615
14615
  isexe.sync = sync;
14616
- var fs18 = __require("fs");
14616
+ var fs17 = __require("fs");
14617
14617
  function isexe(path6, options, cb) {
14618
- fs18.stat(path6, function(er, stat5) {
14619
- cb(er, er ? false : checkStat(stat5, options));
14618
+ fs17.stat(path6, function(er, stat6) {
14619
+ cb(er, er ? false : checkStat(stat6, options));
14620
14620
  });
14621
14621
  }
14622
14622
  function sync(path6, options) {
14623
- return checkStat(fs18.statSync(path6), options);
14623
+ return checkStat(fs17.statSync(path6), options);
14624
14624
  }
14625
- function checkStat(stat5, options) {
14626
- return stat5.isFile() && checkMode(stat5, options);
14625
+ function checkStat(stat6, options) {
14626
+ return stat6.isFile() && checkMode(stat6, options);
14627
14627
  }
14628
- function checkMode(stat5, options) {
14629
- var mod = stat5.mode;
14630
- var uid = stat5.uid;
14631
- var gid = stat5.gid;
14628
+ function checkMode(stat6, options) {
14629
+ var mod = stat6.mode;
14630
+ var uid = stat6.uid;
14631
+ var gid = stat6.gid;
14632
14632
  var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
14633
14633
  var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
14634
14634
  var u = parseInt("100", 8);
@@ -14902,16 +14902,16 @@ var require_shebang_command = __commonJS({
14902
14902
  // node_modules/cross-spawn/lib/util/readShebang.js
14903
14903
  var require_readShebang = __commonJS({
14904
14904
  "node_modules/cross-spawn/lib/util/readShebang.js"(exports$1, module) {
14905
- var fs18 = __require("fs");
14905
+ var fs17 = __require("fs");
14906
14906
  var shebangCommand = require_shebang_command();
14907
14907
  function readShebang(command) {
14908
14908
  const size = 150;
14909
14909
  const buffer = Buffer.alloc(size);
14910
14910
  let fd;
14911
14911
  try {
14912
- fd = fs18.openSync(command, "r");
14913
- fs18.readSync(fd, buffer, 0, size, 0);
14914
- fs18.closeSync(fd);
14912
+ fd = fs17.openSync(command, "r");
14913
+ fs17.readSync(fd, buffer, 0, size, 0);
14914
+ fs17.closeSync(fd);
14915
14915
  } catch (e) {
14916
14916
  }
14917
14917
  return shebangCommand(buffer.toString());
@@ -16020,13 +16020,26 @@ var ToolManager = class extends eventemitter3.EventEmitter {
16020
16020
  pipeline;
16021
16021
  /** Optional tool context for execution (set by agent before runs) */
16022
16022
  _toolContext;
16023
- constructor() {
16023
+ /** Hard timeout for tool execution (0 = disabled) */
16024
+ _toolExecutionTimeout;
16025
+ constructor(config) {
16024
16026
  super();
16027
+ this._toolExecutionTimeout = config?.toolExecutionTimeout ?? 0;
16025
16028
  this.namespaceIndex.set("default", /* @__PURE__ */ new Set());
16026
16029
  this.toolLogger = exports.logger.child({ component: "ToolManager" });
16027
16030
  this.pipeline = new ToolExecutionPipeline();
16028
16031
  this.pipeline.use(new ResultNormalizerPlugin());
16029
16032
  }
16033
+ /**
16034
+ * Get or set the hard tool execution timeout in milliseconds.
16035
+ * 0 = disabled (relies on tool's own timeout).
16036
+ */
16037
+ get toolExecutionTimeout() {
16038
+ return this._toolExecutionTimeout;
16039
+ }
16040
+ set toolExecutionTimeout(value) {
16041
+ this._toolExecutionTimeout = Math.max(0, value);
16042
+ }
16030
16043
  /**
16031
16044
  * Access the execution pipeline for plugin management.
16032
16045
  *
@@ -16524,7 +16537,7 @@ var ToolManager = class extends eventemitter3.EventEmitter {
16524
16537
  const startTime = Date.now();
16525
16538
  exports.metrics.increment("tool.executed", 1, { tool: toolName });
16526
16539
  try {
16527
- const result = await breaker.execute(async () => {
16540
+ const executionPromise = breaker.execute(async () => {
16528
16541
  const toolWithContext = {
16529
16542
  ...registration.tool,
16530
16543
  execute: async (pipelineArgs) => {
@@ -16533,6 +16546,7 @@ var ToolManager = class extends eventemitter3.EventEmitter {
16533
16546
  };
16534
16547
  return await this.pipeline.execute(toolWithContext, args);
16535
16548
  });
16549
+ const result = this._toolExecutionTimeout > 0 ? await this.withHardTimeout(executionPromise, toolName, this._toolExecutionTimeout) : await executionPromise;
16536
16550
  const duration = Date.now() - startTime;
16537
16551
  this.recordExecution(toolName, duration, true);
16538
16552
  const resultSummary = this.summarizeResult(result);
@@ -16595,6 +16609,29 @@ var ToolManager = class extends eventemitter3.EventEmitter {
16595
16609
  return this.list();
16596
16610
  }
16597
16611
  // ==========================================================================
16612
+ // Hard Timeout
16613
+ // ==========================================================================
16614
+ /**
16615
+ * Wrap a promise with a hard timeout safety net.
16616
+ * If the promise doesn't resolve within the timeout, throws ToolExecutionError.
16617
+ */
16618
+ async withHardTimeout(promise, toolName, timeoutMs) {
16619
+ let timeoutId;
16620
+ const timeoutPromise = new Promise((_, reject) => {
16621
+ timeoutId = setTimeout(() => {
16622
+ reject(new ToolExecutionError(
16623
+ toolName,
16624
+ `Tool execution hard timeout after ${timeoutMs}ms (safety net - tool's own timeout may have failed)`
16625
+ ));
16626
+ }, timeoutMs);
16627
+ });
16628
+ try {
16629
+ return await Promise.race([promise, timeoutPromise]);
16630
+ } finally {
16631
+ clearTimeout(timeoutId);
16632
+ }
16633
+ }
16634
+ // ==========================================================================
16598
16635
  // Circuit Breaker Management
16599
16636
  // ==========================================================================
16600
16637
  /**
@@ -19653,10 +19690,10 @@ function getDefaultBaseDirectory() {
19653
19690
  if (platform2 === "win32") {
19654
19691
  const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
19655
19692
  if (appData) {
19656
- return path3.join(appData, "oneringai", "agents");
19693
+ return path2.join(appData, "oneringai", "agents");
19657
19694
  }
19658
19695
  }
19659
- return path3.join(os.homedir(), ".oneringai", "agents");
19696
+ return path2.join(os2.homedir(), ".oneringai", "agents");
19660
19697
  }
19661
19698
  function sanitizeAgentId(agentId) {
19662
19699
  return agentId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
@@ -19671,9 +19708,9 @@ var FilePersistentInstructionsStorage = class {
19671
19708
  const sanitizedId = sanitizeAgentId(config.agentId);
19672
19709
  const baseDir = config.baseDirectory ?? getDefaultBaseDirectory();
19673
19710
  const filename = config.filename ?? "custom_instructions.json";
19674
- this.directory = path3.join(baseDir, sanitizedId);
19675
- this.filePath = path3.join(this.directory, filename);
19676
- this.legacyFilePath = path3.join(this.directory, "custom_instructions.md");
19711
+ this.directory = path2.join(baseDir, sanitizedId);
19712
+ this.filePath = path2.join(this.directory, filename);
19713
+ this.legacyFilePath = path2.join(this.directory, "custom_instructions.md");
19677
19714
  }
19678
19715
  /**
19679
19716
  * Load instruction entries from file.
@@ -19681,7 +19718,7 @@ var FilePersistentInstructionsStorage = class {
19681
19718
  */
19682
19719
  async load() {
19683
19720
  try {
19684
- const raw = await fs15.promises.readFile(this.filePath, "utf-8");
19721
+ const raw = await fs16.promises.readFile(this.filePath, "utf-8");
19685
19722
  const data = JSON.parse(raw);
19686
19723
  if (data.version === 2 && Array.isArray(data.entries)) {
19687
19724
  return data.entries.length > 0 ? data.entries : null;
@@ -19693,7 +19730,7 @@ var FilePersistentInstructionsStorage = class {
19693
19730
  }
19694
19731
  }
19695
19732
  try {
19696
- const content = await fs15.promises.readFile(this.legacyFilePath, "utf-8");
19733
+ const content = await fs16.promises.readFile(this.legacyFilePath, "utf-8");
19697
19734
  const trimmed = content.trim();
19698
19735
  if (!trimmed) return null;
19699
19736
  const now = Date.now();
@@ -19723,11 +19760,11 @@ var FilePersistentInstructionsStorage = class {
19723
19760
  };
19724
19761
  const tempPath = `${this.filePath}.tmp`;
19725
19762
  try {
19726
- await fs15.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
19727
- await fs15.promises.rename(tempPath, this.filePath);
19763
+ await fs16.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
19764
+ await fs16.promises.rename(tempPath, this.filePath);
19728
19765
  } catch (error) {
19729
19766
  try {
19730
- await fs15.promises.unlink(tempPath);
19767
+ await fs16.promises.unlink(tempPath);
19731
19768
  } catch {
19732
19769
  }
19733
19770
  throw error;
@@ -19739,7 +19776,7 @@ var FilePersistentInstructionsStorage = class {
19739
19776
  */
19740
19777
  async delete() {
19741
19778
  try {
19742
- await fs15.promises.unlink(this.filePath);
19779
+ await fs16.promises.unlink(this.filePath);
19743
19780
  } catch (error) {
19744
19781
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
19745
19782
  throw error;
@@ -19752,11 +19789,11 @@ var FilePersistentInstructionsStorage = class {
19752
19789
  */
19753
19790
  async exists() {
19754
19791
  try {
19755
- await fs15.promises.access(this.filePath);
19792
+ await fs16.promises.access(this.filePath);
19756
19793
  return true;
19757
19794
  } catch {
19758
19795
  try {
19759
- await fs15.promises.access(this.legacyFilePath);
19796
+ await fs16.promises.access(this.legacyFilePath);
19760
19797
  return true;
19761
19798
  } catch {
19762
19799
  return false;
@@ -19780,7 +19817,7 @@ var FilePersistentInstructionsStorage = class {
19780
19817
  */
19781
19818
  async ensureDirectory() {
19782
19819
  try {
19783
- await fs15.promises.mkdir(this.directory, { recursive: true });
19820
+ await fs16.promises.mkdir(this.directory, { recursive: true });
19784
19821
  } catch (error) {
19785
19822
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
19786
19823
  throw error;
@@ -19792,7 +19829,7 @@ var FilePersistentInstructionsStorage = class {
19792
19829
  */
19793
19830
  async removeLegacyFile() {
19794
19831
  try {
19795
- await fs15.promises.unlink(this.legacyFilePath);
19832
+ await fs16.promises.unlink(this.legacyFilePath);
19796
19833
  } catch (error) {
19797
19834
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
19798
19835
  console.warn(`Failed to remove legacy instructions file: ${this.legacyFilePath}`);
@@ -20973,7 +21010,9 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
20973
21010
  this._agentId = this._config.agentId;
20974
21011
  this._storage = config.storage;
20975
21012
  this._compactionStrategy = config.compactionStrategy ?? StrategyRegistry.create(this._config.strategy);
20976
- this._tools = new ToolManager();
21013
+ this._tools = new ToolManager(
21014
+ config.toolExecutionTimeout ? { toolExecutionTimeout: config.toolExecutionTimeout } : void 0
21015
+ );
20977
21016
  if (config.tools) {
20978
21017
  for (const tool of config.tools) {
20979
21018
  this._tools.register(tool);
@@ -22709,7 +22748,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
22709
22748
  streamConverter;
22710
22749
  constructor(config) {
22711
22750
  super(config);
22712
- this.client = new OpenAI2__default.default({
22751
+ this.client = new OpenAI3__default.default({
22713
22752
  apiKey: this.getApiKey(),
22714
22753
  baseURL: this.getBaseURL(),
22715
22754
  organization: config.organization,
@@ -24439,7 +24478,9 @@ var GoogleTextProvider = class extends BaseTextProvider {
24439
24478
  constructor(config) {
24440
24479
  super(config);
24441
24480
  this.client = new genai.GoogleGenAI({
24442
- apiKey: this.getApiKey()
24481
+ apiKey: this.getApiKey(),
24482
+ // Pass custom baseURL for proxy support (e.g. when routing through EW proxy)
24483
+ ...config.baseURL ? { httpOptions: { baseUrl: config.baseURL } } : {}
24443
24484
  });
24444
24485
  this.converter = new GoogleConverter();
24445
24486
  this.streamConverter = new GoogleStreamConverter();
@@ -24736,6 +24777,30 @@ var GenericOpenAIProvider = class extends OpenAITextProvider {
24736
24777
  };
24737
24778
 
24738
24779
  // src/core/createProvider.ts
24780
+ var VENDOR_DEFAULT_URLS = (() => {
24781
+ const map = /* @__PURE__ */ new Map();
24782
+ try {
24783
+ map.set(Vendor.OpenAI, new OpenAI3__default.default({ apiKey: "_" }).baseURL);
24784
+ } catch {
24785
+ }
24786
+ try {
24787
+ map.set(Vendor.Anthropic, new Anthropic__default.default({ apiKey: "_" }).baseURL);
24788
+ } catch {
24789
+ }
24790
+ map.set(Vendor.Google, "https://generativelanguage.googleapis.com");
24791
+ map.set(Vendor.GoogleVertex, "https://us-central1-aiplatform.googleapis.com");
24792
+ map.set(Vendor.Groq, "https://api.groq.com/openai/v1");
24793
+ map.set(Vendor.Together, "https://api.together.xyz/v1");
24794
+ map.set(Vendor.Perplexity, "https://api.perplexity.ai");
24795
+ map.set(Vendor.Grok, "https://api.x.ai/v1");
24796
+ map.set(Vendor.DeepSeek, "https://api.deepseek.com/v1");
24797
+ map.set(Vendor.Mistral, "https://api.mistral.ai/v1");
24798
+ map.set(Vendor.Ollama, "http://localhost:11434/v1");
24799
+ return map;
24800
+ })();
24801
+ function getVendorDefaultBaseURL(vendor) {
24802
+ return VENDOR_DEFAULT_URLS.get(vendor);
24803
+ }
24739
24804
  function createProvider(connector) {
24740
24805
  const injectedProvider = connector.getOptions().provider;
24741
24806
  if (injectedProvider && typeof injectedProvider.generate === "function") {
@@ -24770,39 +24835,15 @@ function createProvider(connector) {
24770
24835
  });
24771
24836
  // OpenAI-compatible providers (use connector.name for unique identification)
24772
24837
  case Vendor.Groq:
24773
- return new GenericOpenAIProvider(connector.name, {
24774
- ...config,
24775
- baseURL: config.baseURL || "https://api.groq.com/openai/v1"
24776
- });
24777
24838
  case Vendor.Together:
24778
- return new GenericOpenAIProvider(connector.name, {
24779
- ...config,
24780
- baseURL: config.baseURL || "https://api.together.xyz/v1"
24781
- });
24782
24839
  case Vendor.Perplexity:
24783
- return new GenericOpenAIProvider(connector.name, {
24784
- ...config,
24785
- baseURL: config.baseURL || "https://api.perplexity.ai"
24786
- });
24787
24840
  case Vendor.Grok:
24788
- return new GenericOpenAIProvider(connector.name, {
24789
- ...config,
24790
- baseURL: config.baseURL || "https://api.x.ai/v1"
24791
- });
24792
24841
  case Vendor.DeepSeek:
24793
- return new GenericOpenAIProvider(connector.name, {
24794
- ...config,
24795
- baseURL: config.baseURL || "https://api.deepseek.com/v1"
24796
- });
24797
24842
  case Vendor.Mistral:
24798
- return new GenericOpenAIProvider(connector.name, {
24799
- ...config,
24800
- baseURL: config.baseURL || "https://api.mistral.ai/v1"
24801
- });
24802
24843
  case Vendor.Ollama:
24803
24844
  return new GenericOpenAIProvider(connector.name, {
24804
24845
  ...config,
24805
- baseURL: config.baseURL || "http://localhost:11434/v1"
24846
+ baseURL: config.baseURL || getVendorDefaultBaseURL(vendor)
24806
24847
  });
24807
24848
  case Vendor.Custom:
24808
24849
  if (!config.baseURL) {
@@ -24914,7 +24955,10 @@ var BaseAgent = class extends eventemitter3.EventEmitter {
24914
24955
  agentId: config.name,
24915
24956
  // Include storage and sessionId if session config is provided
24916
24957
  storage: config.session?.storage,
24958
+ // Thread tool execution timeout to ToolManager
24959
+ toolExecutionTimeout: config.toolExecutionTimeout,
24917
24960
  // Subclasses can add systemPrompt via their config
24961
+ // Note: context-level toolExecutionTimeout overrides agent-level if both set
24918
24962
  ...typeof config.context === "object" && config.context !== null ? config.context : {}
24919
24963
  };
24920
24964
  return AgentContextNextGen.create(contextConfig);
@@ -27354,18 +27398,18 @@ var Agent = class _Agent extends BaseAgent {
27354
27398
  (class {
27355
27399
  static DEFAULT_PATHS = [
27356
27400
  "./oneringai.config.json",
27357
- path3.join(os.homedir(), ".oneringai", "config.json")
27401
+ path2.join(os2.homedir(), ".oneringai", "config.json")
27358
27402
  ];
27359
27403
  /**
27360
27404
  * Load configuration from file
27361
27405
  */
27362
27406
  static async load(path6) {
27363
- const configPath = path6 ? path3.resolve(path6) : await this.findConfig();
27407
+ const configPath = path6 ? path2.resolve(path6) : await this.findConfig();
27364
27408
  if (!configPath) {
27365
27409
  throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
27366
27410
  }
27367
27411
  try {
27368
- const content = await fs15.promises.readFile(configPath, "utf-8");
27412
+ const content = await fs16.promises.readFile(configPath, "utf-8");
27369
27413
  let config = JSON.parse(content);
27370
27414
  config = this.interpolateEnvVars(config);
27371
27415
  this.validate(config);
@@ -27381,13 +27425,13 @@ var Agent = class _Agent extends BaseAgent {
27381
27425
  * Load configuration synchronously
27382
27426
  */
27383
27427
  static loadSync(path6) {
27384
- const configPath = path6 ? path3.resolve(path6) : this.findConfigSync();
27428
+ const configPath = path6 ? path2.resolve(path6) : this.findConfigSync();
27385
27429
  if (!configPath) {
27386
27430
  throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
27387
27431
  }
27388
27432
  try {
27389
- const fs18 = __require("fs");
27390
- const content = fs18.readFileSync(configPath, "utf-8");
27433
+ const fs17 = __require("fs");
27434
+ const content = fs17.readFileSync(configPath, "utf-8");
27391
27435
  let config = JSON.parse(content);
27392
27436
  config = this.interpolateEnvVars(config);
27393
27437
  this.validate(config);
@@ -27405,8 +27449,8 @@ var Agent = class _Agent extends BaseAgent {
27405
27449
  static async findConfig() {
27406
27450
  for (const path6 of this.DEFAULT_PATHS) {
27407
27451
  try {
27408
- await fs15.promises.access(path3.resolve(path6));
27409
- return path3.resolve(path6);
27452
+ await fs16.promises.access(path2.resolve(path6));
27453
+ return path2.resolve(path6);
27410
27454
  } catch {
27411
27455
  }
27412
27456
  }
@@ -27416,11 +27460,11 @@ var Agent = class _Agent extends BaseAgent {
27416
27460
  * Find configuration file synchronously
27417
27461
  */
27418
27462
  static findConfigSync() {
27419
- const fs18 = __require("fs");
27463
+ const fs17 = __require("fs");
27420
27464
  for (const path6 of this.DEFAULT_PATHS) {
27421
27465
  try {
27422
- fs18.accessSync(path3.resolve(path6));
27423
- return path3.resolve(path6);
27466
+ fs17.accessSync(path2.resolve(path6));
27467
+ return path2.resolve(path6);
27424
27468
  } catch {
27425
27469
  }
27426
27470
  }
@@ -32977,8 +33021,8 @@ var MCPRegistry = class {
32977
33021
  */
32978
33022
  static async loadFromConfigFile(path6) {
32979
33023
  try {
32980
- const configPath = path3.resolve(path6);
32981
- const content = await fs15.promises.readFile(configPath, "utf-8");
33024
+ const configPath = path2.resolve(path6);
33025
+ const content = await fs16.promises.readFile(configPath, "utf-8");
32982
33026
  const config = JSON.parse(content);
32983
33027
  if (!config.mcp) {
32984
33028
  throw new MCPError("Configuration file does not contain MCP section");
@@ -33366,7 +33410,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
33366
33410
  client;
33367
33411
  constructor(config) {
33368
33412
  super({ apiKey: config.auth.apiKey, ...config });
33369
- this.client = new OpenAI2__default.default({
33413
+ this.client = new OpenAI3__default.default({
33370
33414
  apiKey: config.auth.apiKey,
33371
33415
  baseURL: config.baseURL,
33372
33416
  organization: config.organization,
@@ -33449,7 +33493,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
33449
33493
  * Handle OpenAI API errors
33450
33494
  */
33451
33495
  handleError(error) {
33452
- if (error instanceof OpenAI2__default.default.APIError) {
33496
+ if (error instanceof OpenAI3__default.default.APIError) {
33453
33497
  const status = error.status;
33454
33498
  const message = error.message || "Unknown OpenAI API error";
33455
33499
  if (status === 401) {
@@ -33481,7 +33525,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
33481
33525
  client;
33482
33526
  constructor(config) {
33483
33527
  super({ apiKey: config.auth.apiKey, ...config });
33484
- this.client = new OpenAI2__default.default({
33528
+ this.client = new OpenAI3__default.default({
33485
33529
  apiKey: config.auth.apiKey,
33486
33530
  baseURL: config.baseURL,
33487
33531
  organization: config.organization,
@@ -33583,7 +33627,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
33583
33627
  if (Buffer.isBuffer(audio)) {
33584
33628
  return new File([new Uint8Array(audio)], "audio.wav", { type: "audio/wav" });
33585
33629
  } else if (typeof audio === "string") {
33586
- return fs15__namespace.createReadStream(audio);
33630
+ return fs16__namespace.createReadStream(audio);
33587
33631
  } else {
33588
33632
  throw new Error("Invalid audio input: must be Buffer or file path");
33589
33633
  }
@@ -33642,7 +33686,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
33642
33686
  * Handle OpenAI API errors
33643
33687
  */
33644
33688
  handleError(error) {
33645
- if (error instanceof OpenAI2__default.default.APIError) {
33689
+ if (error instanceof OpenAI3__default.default.APIError) {
33646
33690
  const status = error.status;
33647
33691
  const message = error.message || "Unknown OpenAI API error";
33648
33692
  if (status === 401) {
@@ -34136,7 +34180,7 @@ var TextToSpeech = class _TextToSpeech {
34136
34180
  */
34137
34181
  async toFile(text, filePath, options) {
34138
34182
  const response = await this.synthesize(text, options);
34139
- await fs14__namespace.writeFile(filePath, response.audio);
34183
+ await fs15__namespace.writeFile(filePath, response.audio);
34140
34184
  }
34141
34185
  // ======================== Introspection Methods ========================
34142
34186
  /**
@@ -34484,7 +34528,7 @@ var SpeechToText = class _SpeechToText {
34484
34528
  * @param options - Optional transcription parameters
34485
34529
  */
34486
34530
  async transcribeFile(filePath, options) {
34487
- const audio = await fs14__namespace.readFile(filePath);
34531
+ const audio = await fs15__namespace.readFile(filePath);
34488
34532
  return this.transcribe(audio, options);
34489
34533
  }
34490
34534
  /**
@@ -34648,7 +34692,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
34648
34692
  client;
34649
34693
  constructor(config) {
34650
34694
  super({ apiKey: config.auth.apiKey, ...config });
34651
- this.client = new OpenAI2__default.default({
34695
+ this.client = new OpenAI3__default.default({
34652
34696
  apiKey: config.auth.apiKey,
34653
34697
  baseURL: config.baseURL,
34654
34698
  organization: config.organization,
@@ -34810,7 +34854,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
34810
34854
  if (Buffer.isBuffer(image)) {
34811
34855
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
34812
34856
  }
34813
- return fs15__namespace.createReadStream(image);
34857
+ return fs16__namespace.createReadStream(image);
34814
34858
  }
34815
34859
  /**
34816
34860
  * Handle OpenAI API errors
@@ -34957,8 +35001,8 @@ var GoogleImageProvider = class extends BaseMediaProvider {
34957
35001
  if (Buffer.isBuffer(image)) {
34958
35002
  imageBytes = image.toString("base64");
34959
35003
  } else {
34960
- const fs18 = await import('fs');
34961
- const buffer = fs18.readFileSync(image);
35004
+ const fs17 = await import('fs');
35005
+ const buffer = fs17.readFileSync(image);
34962
35006
  imageBytes = buffer.toString("base64");
34963
35007
  }
34964
35008
  return {
@@ -35008,7 +35052,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
35008
35052
  client;
35009
35053
  constructor(config) {
35010
35054
  super({ apiKey: config.auth.apiKey, ...config });
35011
- this.client = new OpenAI2__default.default({
35055
+ this.client = new OpenAI3__default.default({
35012
35056
  apiKey: config.auth.apiKey,
35013
35057
  baseURL: config.baseURL || GROK_API_BASE_URL,
35014
35058
  timeout: config.timeout,
@@ -35119,7 +35163,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
35119
35163
  if (Buffer.isBuffer(image)) {
35120
35164
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
35121
35165
  }
35122
- return fs15__namespace.createReadStream(image);
35166
+ return fs16__namespace.createReadStream(image);
35123
35167
  }
35124
35168
  /**
35125
35169
  * Handle API errors
@@ -36321,7 +36365,7 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
36321
36365
  client;
36322
36366
  constructor(config) {
36323
36367
  super({ apiKey: config.auth.apiKey, ...config });
36324
- this.client = new OpenAI2__default.default({
36368
+ this.client = new OpenAI3__default.default({
36325
36369
  apiKey: config.auth.apiKey,
36326
36370
  baseURL: config.baseURL,
36327
36371
  organization: config.organization,
@@ -36569,8 +36613,8 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
36569
36613
  return new File([new Uint8Array(image)], "input.png", { type: "image/png" });
36570
36614
  }
36571
36615
  if (!image.startsWith("http")) {
36572
- const fs18 = await import('fs');
36573
- const data = fs18.readFileSync(image);
36616
+ const fs17 = await import('fs');
36617
+ const data = fs17.readFileSync(image);
36574
36618
  return new File([new Uint8Array(data)], "input.png", { type: "image/png" });
36575
36619
  }
36576
36620
  const response = await fetch(image);
@@ -36748,7 +36792,7 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
36748
36792
  if (video.videoBytes) {
36749
36793
  buffer = Buffer.from(video.videoBytes, "base64");
36750
36794
  } else if (video.uri) {
36751
- const fs18 = await import('fs/promises');
36795
+ const fs17 = await import('fs/promises');
36752
36796
  const os3 = await import('os');
36753
36797
  const path6 = await import('path');
36754
36798
  const tempDir = os3.tmpdir();
@@ -36759,11 +36803,11 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
36759
36803
  // Pass as GeneratedVideo
36760
36804
  downloadPath: tempFile
36761
36805
  });
36762
- buffer = await fs18.readFile(tempFile);
36763
- await fs18.unlink(tempFile).catch(() => {
36806
+ buffer = await fs17.readFile(tempFile);
36807
+ await fs17.unlink(tempFile).catch(() => {
36764
36808
  });
36765
36809
  } catch (downloadError) {
36766
- await fs18.unlink(tempFile).catch(() => {
36810
+ await fs17.unlink(tempFile).catch(() => {
36767
36811
  });
36768
36812
  throw new ProviderError(
36769
36813
  "google",
@@ -36885,8 +36929,8 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
36885
36929
  if (image.startsWith("http://") || image.startsWith("https://")) {
36886
36930
  return { imageUri: image };
36887
36931
  }
36888
- const fs18 = await import('fs/promises');
36889
- const data = await fs18.readFile(image);
36932
+ const fs17 = await import('fs/promises');
36933
+ const data = await fs17.readFile(image);
36890
36934
  return {
36891
36935
  imageBytes: data.toString("base64")
36892
36936
  };
@@ -37193,8 +37237,8 @@ var GrokImagineProvider = class extends BaseMediaProvider {
37193
37237
  if (image.startsWith("http") || image.startsWith("data:")) {
37194
37238
  return image;
37195
37239
  }
37196
- const fs18 = await import('fs');
37197
- const data = fs18.readFileSync(image);
37240
+ const fs17 = await import('fs');
37241
+ const data = fs17.readFileSync(image);
37198
37242
  const base64 = data.toString("base64");
37199
37243
  const ext = image.split(".").pop()?.toLowerCase() || "png";
37200
37244
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext}`;
@@ -40399,10 +40443,10 @@ function getDefaultBaseDirectory2() {
40399
40443
  if (platform2 === "win32") {
40400
40444
  const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
40401
40445
  if (appData) {
40402
- return path3.join(appData, "oneringai", "agents");
40446
+ return path2.join(appData, "oneringai", "agents");
40403
40447
  }
40404
40448
  }
40405
- return path3.join(os.homedir(), ".oneringai", "agents");
40449
+ return path2.join(os2.homedir(), ".oneringai", "agents");
40406
40450
  }
40407
40451
  function sanitizeId(id) {
40408
40452
  return id.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
@@ -40419,8 +40463,8 @@ var FileContextStorage = class {
40419
40463
  const sanitizedAgentId = sanitizeId(config.agentId);
40420
40464
  const baseDir = config.baseDirectory ?? getDefaultBaseDirectory2();
40421
40465
  this.prettyPrint = config.prettyPrint ?? true;
40422
- this.sessionsDirectory = path3.join(baseDir, sanitizedAgentId, "sessions");
40423
- this.indexPath = path3.join(this.sessionsDirectory, "_index.json");
40466
+ this.sessionsDirectory = path2.join(baseDir, sanitizedAgentId, "sessions");
40467
+ this.indexPath = path2.join(this.sessionsDirectory, "_index.json");
40424
40468
  }
40425
40469
  /**
40426
40470
  * Save context state to a session file
@@ -40446,11 +40490,11 @@ var FileContextStorage = class {
40446
40490
  const data = this.prettyPrint ? JSON.stringify(storedSession, null, 2) : JSON.stringify(storedSession);
40447
40491
  const tempPath = `${filePath}.tmp`;
40448
40492
  try {
40449
- await fs15.promises.writeFile(tempPath, data, "utf-8");
40450
- await fs15.promises.rename(tempPath, filePath);
40493
+ await fs16.promises.writeFile(tempPath, data, "utf-8");
40494
+ await fs16.promises.rename(tempPath, filePath);
40451
40495
  } catch (error) {
40452
40496
  try {
40453
- await fs15.promises.unlink(tempPath);
40497
+ await fs16.promises.unlink(tempPath);
40454
40498
  } catch {
40455
40499
  }
40456
40500
  throw error;
@@ -40471,7 +40515,7 @@ var FileContextStorage = class {
40471
40515
  const sanitizedSessionId = sanitizeId(sessionId);
40472
40516
  const filePath = this.getFilePath(sanitizedSessionId);
40473
40517
  try {
40474
- await fs15.promises.unlink(filePath);
40518
+ await fs16.promises.unlink(filePath);
40475
40519
  } catch (error) {
40476
40520
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
40477
40521
  throw error;
@@ -40486,7 +40530,7 @@ var FileContextStorage = class {
40486
40530
  const sanitizedSessionId = sanitizeId(sessionId);
40487
40531
  const filePath = this.getFilePath(sanitizedSessionId);
40488
40532
  try {
40489
- await fs15.promises.access(filePath);
40533
+ await fs16.promises.access(filePath);
40490
40534
  return true;
40491
40535
  } catch {
40492
40536
  return false;
@@ -40551,7 +40595,7 @@ var FileContextStorage = class {
40551
40595
  const sanitizedSessionId = sanitizeId(sessionId);
40552
40596
  const filePath = this.getFilePath(sanitizedSessionId);
40553
40597
  const data = this.prettyPrint ? JSON.stringify(stored, null, 2) : JSON.stringify(stored);
40554
- await fs15.promises.writeFile(filePath, data, "utf-8");
40598
+ await fs16.promises.writeFile(filePath, data, "utf-8");
40555
40599
  await this.updateIndex(stored);
40556
40600
  }
40557
40601
  /**
@@ -40572,13 +40616,13 @@ var FileContextStorage = class {
40572
40616
  */
40573
40617
  async rebuildIndex() {
40574
40618
  await this.ensureDirectory();
40575
- const files = await fs15.promises.readdir(this.sessionsDirectory);
40619
+ const files = await fs16.promises.readdir(this.sessionsDirectory);
40576
40620
  const sessionFiles = files.filter((f) => f.endsWith(".json") && !f.startsWith("_"));
40577
40621
  const entries = [];
40578
40622
  for (const file of sessionFiles) {
40579
40623
  try {
40580
- const filePath = path3.join(this.sessionsDirectory, file);
40581
- const data = await fs15.promises.readFile(filePath, "utf-8");
40624
+ const filePath = path2.join(this.sessionsDirectory, file);
40625
+ const data = await fs16.promises.readFile(filePath, "utf-8");
40582
40626
  const stored = JSON.parse(data);
40583
40627
  entries.push(this.storedToIndexEntry(stored));
40584
40628
  } catch {
@@ -40596,11 +40640,11 @@ var FileContextStorage = class {
40596
40640
  // Private Helpers
40597
40641
  // ==========================================================================
40598
40642
  getFilePath(sanitizedSessionId) {
40599
- return path3.join(this.sessionsDirectory, `${sanitizedSessionId}.json`);
40643
+ return path2.join(this.sessionsDirectory, `${sanitizedSessionId}.json`);
40600
40644
  }
40601
40645
  async ensureDirectory() {
40602
40646
  try {
40603
- await fs15.promises.mkdir(this.sessionsDirectory, { recursive: true });
40647
+ await fs16.promises.mkdir(this.sessionsDirectory, { recursive: true });
40604
40648
  } catch (error) {
40605
40649
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
40606
40650
  throw error;
@@ -40610,7 +40654,7 @@ var FileContextStorage = class {
40610
40654
  async loadRaw(sanitizedSessionId) {
40611
40655
  const filePath = this.getFilePath(sanitizedSessionId);
40612
40656
  try {
40613
- const data = await fs15.promises.readFile(filePath, "utf-8");
40657
+ const data = await fs16.promises.readFile(filePath, "utf-8");
40614
40658
  return JSON.parse(data);
40615
40659
  } catch (error) {
40616
40660
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -40628,7 +40672,7 @@ var FileContextStorage = class {
40628
40672
  return this.index;
40629
40673
  }
40630
40674
  try {
40631
- const data = await fs15.promises.readFile(this.indexPath, "utf-8");
40675
+ const data = await fs16.promises.readFile(this.indexPath, "utf-8");
40632
40676
  this.index = JSON.parse(data);
40633
40677
  return this.index;
40634
40678
  } catch (error) {
@@ -40649,7 +40693,7 @@ var FileContextStorage = class {
40649
40693
  await this.ensureDirectory();
40650
40694
  this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
40651
40695
  const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
40652
- await fs15.promises.writeFile(this.indexPath, data, "utf-8");
40696
+ await fs16.promises.writeFile(this.indexPath, data, "utf-8");
40653
40697
  }
40654
40698
  async updateIndex(stored) {
40655
40699
  const index = await this.loadIndex();
@@ -40687,10 +40731,10 @@ function getDefaultBaseDirectory3() {
40687
40731
  if (platform2 === "win32") {
40688
40732
  const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
40689
40733
  if (appData) {
40690
- return path3.join(appData, "oneringai", "agents");
40734
+ return path2.join(appData, "oneringai", "agents");
40691
40735
  }
40692
40736
  }
40693
- return path3.join(os.homedir(), ".oneringai", "agents");
40737
+ return path2.join(os2.homedir(), ".oneringai", "agents");
40694
40738
  }
40695
40739
  function sanitizeAgentId2(agentId) {
40696
40740
  return agentId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
@@ -40703,15 +40747,15 @@ var FileAgentDefinitionStorage = class {
40703
40747
  constructor(config = {}) {
40704
40748
  this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory3();
40705
40749
  this.prettyPrint = config.prettyPrint ?? true;
40706
- this.indexPath = path3.join(this.baseDirectory, "_agents_index.json");
40750
+ this.indexPath = path2.join(this.baseDirectory, "_agents_index.json");
40707
40751
  }
40708
40752
  /**
40709
40753
  * Save an agent definition
40710
40754
  */
40711
40755
  async save(definition) {
40712
40756
  const sanitizedId = sanitizeAgentId2(definition.agentId);
40713
- const agentDir = path3.join(this.baseDirectory, sanitizedId);
40714
- const filePath = path3.join(agentDir, "definition.json");
40757
+ const agentDir = path2.join(this.baseDirectory, sanitizedId);
40758
+ const filePath = path2.join(agentDir, "definition.json");
40715
40759
  await this.ensureDirectory(agentDir);
40716
40760
  const now = (/* @__PURE__ */ new Date()).toISOString();
40717
40761
  if (!definition.createdAt) {
@@ -40723,11 +40767,11 @@ var FileAgentDefinitionStorage = class {
40723
40767
  const data = this.prettyPrint ? JSON.stringify(definition, null, 2) : JSON.stringify(definition);
40724
40768
  const tempPath = `${filePath}.tmp`;
40725
40769
  try {
40726
- await fs15.promises.writeFile(tempPath, data, "utf-8");
40727
- await fs15.promises.rename(tempPath, filePath);
40770
+ await fs16.promises.writeFile(tempPath, data, "utf-8");
40771
+ await fs16.promises.rename(tempPath, filePath);
40728
40772
  } catch (error) {
40729
40773
  try {
40730
- await fs15.promises.unlink(tempPath);
40774
+ await fs16.promises.unlink(tempPath);
40731
40775
  } catch {
40732
40776
  }
40733
40777
  throw error;
@@ -40746,10 +40790,10 @@ var FileAgentDefinitionStorage = class {
40746
40790
  */
40747
40791
  async delete(agentId) {
40748
40792
  const sanitizedId = sanitizeAgentId2(agentId);
40749
- const agentDir = path3.join(this.baseDirectory, sanitizedId);
40750
- const filePath = path3.join(agentDir, "definition.json");
40793
+ const agentDir = path2.join(this.baseDirectory, sanitizedId);
40794
+ const filePath = path2.join(agentDir, "definition.json");
40751
40795
  try {
40752
- await fs15.promises.unlink(filePath);
40796
+ await fs16.promises.unlink(filePath);
40753
40797
  } catch (error) {
40754
40798
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
40755
40799
  throw error;
@@ -40762,9 +40806,9 @@ var FileAgentDefinitionStorage = class {
40762
40806
  */
40763
40807
  async exists(agentId) {
40764
40808
  const sanitizedId = sanitizeAgentId2(agentId);
40765
- const filePath = path3.join(this.baseDirectory, sanitizedId, "definition.json");
40809
+ const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
40766
40810
  try {
40767
- await fs15.promises.access(filePath);
40811
+ await fs16.promises.access(filePath);
40768
40812
  return true;
40769
40813
  } catch {
40770
40814
  return false;
@@ -40826,13 +40870,13 @@ var FileAgentDefinitionStorage = class {
40826
40870
  */
40827
40871
  async rebuildIndex() {
40828
40872
  await this.ensureDirectory(this.baseDirectory);
40829
- const entries = await fs15.promises.readdir(this.baseDirectory, { withFileTypes: true });
40873
+ const entries = await fs16.promises.readdir(this.baseDirectory, { withFileTypes: true });
40830
40874
  const agentDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith("_"));
40831
40875
  const indexEntries = [];
40832
40876
  for (const dir of agentDirs) {
40833
40877
  try {
40834
- const filePath = path3.join(this.baseDirectory, dir.name, "definition.json");
40835
- const data = await fs15.promises.readFile(filePath, "utf-8");
40878
+ const filePath = path2.join(this.baseDirectory, dir.name, "definition.json");
40879
+ const data = await fs16.promises.readFile(filePath, "utf-8");
40836
40880
  const definition = JSON.parse(data);
40837
40881
  indexEntries.push(this.definitionToIndexEntry(definition));
40838
40882
  } catch {
@@ -40850,7 +40894,7 @@ var FileAgentDefinitionStorage = class {
40850
40894
  // ==========================================================================
40851
40895
  async ensureDirectory(dir) {
40852
40896
  try {
40853
- await fs15.promises.mkdir(dir, { recursive: true });
40897
+ await fs16.promises.mkdir(dir, { recursive: true });
40854
40898
  } catch (error) {
40855
40899
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
40856
40900
  throw error;
@@ -40858,9 +40902,9 @@ var FileAgentDefinitionStorage = class {
40858
40902
  }
40859
40903
  }
40860
40904
  async loadRaw(sanitizedId) {
40861
- const filePath = path3.join(this.baseDirectory, sanitizedId, "definition.json");
40905
+ const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
40862
40906
  try {
40863
- const data = await fs15.promises.readFile(filePath, "utf-8");
40907
+ const data = await fs16.promises.readFile(filePath, "utf-8");
40864
40908
  return JSON.parse(data);
40865
40909
  } catch (error) {
40866
40910
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -40878,7 +40922,7 @@ var FileAgentDefinitionStorage = class {
40878
40922
  return this.index;
40879
40923
  }
40880
40924
  try {
40881
- const data = await fs15.promises.readFile(this.indexPath, "utf-8");
40925
+ const data = await fs16.promises.readFile(this.indexPath, "utf-8");
40882
40926
  this.index = JSON.parse(data);
40883
40927
  return this.index;
40884
40928
  } catch (error) {
@@ -40898,7 +40942,7 @@ var FileAgentDefinitionStorage = class {
40898
40942
  await this.ensureDirectory(this.baseDirectory);
40899
40943
  this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
40900
40944
  const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
40901
- await fs15.promises.writeFile(this.indexPath, data, "utf-8");
40945
+ await fs16.promises.writeFile(this.indexPath, data, "utf-8");
40902
40946
  }
40903
40947
  async updateIndex(definition) {
40904
40948
  const index = await this.loadIndex();
@@ -40931,6 +40975,126 @@ var FileAgentDefinitionStorage = class {
40931
40975
  function createFileAgentDefinitionStorage(config) {
40932
40976
  return new FileAgentDefinitionStorage(config);
40933
40977
  }
40978
+ var MIME_TYPES = {
40979
+ png: "image/png",
40980
+ jpeg: "image/jpeg",
40981
+ jpg: "image/jpeg",
40982
+ webp: "image/webp",
40983
+ gif: "image/gif",
40984
+ mp4: "video/mp4",
40985
+ webm: "video/webm",
40986
+ mp3: "audio/mpeg",
40987
+ wav: "audio/wav",
40988
+ opus: "audio/opus",
40989
+ ogg: "audio/ogg",
40990
+ aac: "audio/aac",
40991
+ flac: "audio/flac",
40992
+ pcm: "audio/pcm"
40993
+ };
40994
+ var MEDIA_TYPE_PREFIXES = ["image", "video", "audio"];
40995
+ var FileMediaStorage = class {
40996
+ outputDir;
40997
+ initialized = false;
40998
+ constructor(config) {
40999
+ this.outputDir = config?.outputDir ?? path2__namespace.join(os2__namespace.tmpdir(), "oneringai-media");
41000
+ }
41001
+ async save(data, metadata) {
41002
+ const dir = metadata.userId ? path2__namespace.join(this.outputDir, metadata.userId) : this.outputDir;
41003
+ await fs15__namespace.mkdir(dir, { recursive: true });
41004
+ const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
41005
+ const filePath = path2__namespace.join(dir, filename);
41006
+ await fs15__namespace.writeFile(filePath, data);
41007
+ const format = metadata.format.toLowerCase();
41008
+ const mimeType = MIME_TYPES[format] ?? "application/octet-stream";
41009
+ return {
41010
+ location: filePath,
41011
+ mimeType,
41012
+ size: data.length
41013
+ };
41014
+ }
41015
+ async read(location) {
41016
+ try {
41017
+ return await fs15__namespace.readFile(location);
41018
+ } catch (err) {
41019
+ if (err.code === "ENOENT") {
41020
+ return null;
41021
+ }
41022
+ throw err;
41023
+ }
41024
+ }
41025
+ async delete(location) {
41026
+ try {
41027
+ await fs15__namespace.unlink(location);
41028
+ } catch (err) {
41029
+ if (err.code === "ENOENT") {
41030
+ return;
41031
+ }
41032
+ throw err;
41033
+ }
41034
+ }
41035
+ async exists(location) {
41036
+ try {
41037
+ await fs15__namespace.access(location);
41038
+ return true;
41039
+ } catch {
41040
+ return false;
41041
+ }
41042
+ }
41043
+ async list(options) {
41044
+ await this.ensureDir();
41045
+ let entries = [];
41046
+ const files = await fs15__namespace.readdir(this.outputDir);
41047
+ for (const file of files) {
41048
+ const filePath = path2__namespace.join(this.outputDir, file);
41049
+ try {
41050
+ const stat6 = await fs15__namespace.stat(filePath);
41051
+ if (!stat6.isFile()) continue;
41052
+ const ext = path2__namespace.extname(file).slice(1).toLowerCase();
41053
+ const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
41054
+ let type;
41055
+ for (const prefix of MEDIA_TYPE_PREFIXES) {
41056
+ if (file.startsWith(`${prefix}_`)) {
41057
+ type = prefix;
41058
+ break;
41059
+ }
41060
+ }
41061
+ entries.push({
41062
+ location: filePath,
41063
+ mimeType,
41064
+ size: stat6.size,
41065
+ type,
41066
+ createdAt: stat6.birthtime
41067
+ });
41068
+ } catch {
41069
+ }
41070
+ }
41071
+ if (options?.type) {
41072
+ entries = entries.filter((e) => e.type === options.type);
41073
+ }
41074
+ entries.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
41075
+ const offset = options?.offset ?? 0;
41076
+ const limit = options?.limit ?? entries.length;
41077
+ return entries.slice(offset, offset + limit);
41078
+ }
41079
+ getPath() {
41080
+ return this.outputDir;
41081
+ }
41082
+ generateFilename(metadata) {
41083
+ const timestamp = Date.now();
41084
+ const random2 = crypto2__namespace.randomBytes(4).toString("hex");
41085
+ const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
41086
+ return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
41087
+ }
41088
+ async ensureDir() {
41089
+ if (!this.initialized) {
41090
+ await fs15__namespace.mkdir(this.outputDir, { recursive: true });
41091
+ this.initialized = true;
41092
+ }
41093
+ }
41094
+ };
41095
+ function createFileMediaStorage(config) {
41096
+ return new FileMediaStorage(config);
41097
+ }
40934
41098
 
40935
41099
  // src/capabilities/agents/StreamHelpers.ts
40936
41100
  var StreamHelpers = class {
@@ -41853,7 +42017,7 @@ var ConnectorTools = class {
41853
42017
  static createGenericAPITool(connector, options) {
41854
42018
  const toolName = options?.toolName ?? `${connector.name}_api`;
41855
42019
  const userId = options?.userId;
41856
- const description = options?.description ?? `Make an authenticated API call to ${connector.displayName}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}` : " Provide full URL in endpoint.");
42020
+ const description = options?.description ?? `Make an authenticated API call to ${connector.displayName}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}.` : " Provide full URL in endpoint.") + ' IMPORTANT: For POST/PUT/PATCH requests, pass data in the "body" parameter as a JSON object, NOT as query string parameters in the endpoint URL. The body is sent as application/json.';
41857
42021
  return {
41858
42022
  definition: {
41859
42023
  type: "function",
@@ -41870,15 +42034,15 @@ var ConnectorTools = class {
41870
42034
  },
41871
42035
  endpoint: {
41872
42036
  type: "string",
41873
- description: "API endpoint (relative to base URL) or full URL"
42037
+ description: 'API endpoint path (relative to base URL) or full URL. Do NOT put request data as query parameters here for POST/PUT/PATCH \u2014 use the "body" parameter instead.'
41874
42038
  },
41875
42039
  body: {
41876
42040
  type: "object",
41877
- description: "Request body (for POST/PUT/PATCH)"
42041
+ description: 'JSON request body for POST/PUT/PATCH requests. ALWAYS use this for sending data (e.g., {"channel": "C123", "text": "hello"}) instead of query string parameters.'
41878
42042
  },
41879
42043
  queryParams: {
41880
42044
  type: "object",
41881
- description: "URL query parameters"
42045
+ description: 'URL query parameters (for filtering/pagination on GET requests). Do NOT use for POST/PUT/PATCH data \u2014 use "body" instead.'
41882
42046
  },
41883
42047
  headers: {
41884
42048
  type: "object",
@@ -41943,7 +42107,10 @@ var ConnectorTools = class {
41943
42107
  };
41944
42108
  }
41945
42109
  },
41946
- describeCall: (args) => `${args.method} ${args.endpoint}`,
42110
+ describeCall: (args) => {
42111
+ const bodyInfo = args.body ? ` body=${JSON.stringify(args.body).slice(0, 100)}` : "";
42112
+ return `${args.method} ${args.endpoint}${bodyInfo}`;
42113
+ },
41947
42114
  permission: options?.permission ?? {
41948
42115
  scope: "session",
41949
42116
  riskLevel: "medium",
@@ -41978,8 +42145,8 @@ var FileStorage = class {
41978
42145
  }
41979
42146
  async ensureDirectory() {
41980
42147
  try {
41981
- await fs14__namespace.mkdir(this.directory, { recursive: true });
41982
- await fs14__namespace.chmod(this.directory, 448);
42148
+ await fs15__namespace.mkdir(this.directory, { recursive: true });
42149
+ await fs15__namespace.chmod(this.directory, 448);
41983
42150
  } catch (error) {
41984
42151
  }
41985
42152
  }
@@ -41988,20 +42155,20 @@ var FileStorage = class {
41988
42155
  */
41989
42156
  getFilePath(key) {
41990
42157
  const hash = crypto2__namespace.createHash("sha256").update(key).digest("hex");
41991
- return path3__namespace.join(this.directory, `${hash}.token`);
42158
+ return path2__namespace.join(this.directory, `${hash}.token`);
41992
42159
  }
41993
42160
  async storeToken(key, token) {
41994
42161
  await this.ensureDirectory();
41995
42162
  const filePath = this.getFilePath(key);
41996
42163
  const plaintext = JSON.stringify(token);
41997
42164
  const encrypted = encrypt(plaintext, this.encryptionKey);
41998
- await fs14__namespace.writeFile(filePath, encrypted, "utf8");
41999
- await fs14__namespace.chmod(filePath, 384);
42165
+ await fs15__namespace.writeFile(filePath, encrypted, "utf8");
42166
+ await fs15__namespace.chmod(filePath, 384);
42000
42167
  }
42001
42168
  async getToken(key) {
42002
42169
  const filePath = this.getFilePath(key);
42003
42170
  try {
42004
- const encrypted = await fs14__namespace.readFile(filePath, "utf8");
42171
+ const encrypted = await fs15__namespace.readFile(filePath, "utf8");
42005
42172
  const decrypted = decrypt(encrypted, this.encryptionKey);
42006
42173
  return JSON.parse(decrypted);
42007
42174
  } catch (error) {
@@ -42010,7 +42177,7 @@ var FileStorage = class {
42010
42177
  }
42011
42178
  console.error("Failed to read/decrypt token file:", error);
42012
42179
  try {
42013
- await fs14__namespace.unlink(filePath);
42180
+ await fs15__namespace.unlink(filePath);
42014
42181
  } catch {
42015
42182
  }
42016
42183
  return null;
@@ -42019,7 +42186,7 @@ var FileStorage = class {
42019
42186
  async deleteToken(key) {
42020
42187
  const filePath = this.getFilePath(key);
42021
42188
  try {
42022
- await fs14__namespace.unlink(filePath);
42189
+ await fs15__namespace.unlink(filePath);
42023
42190
  } catch (error) {
42024
42191
  if (error.code !== "ENOENT") {
42025
42192
  throw error;
@@ -42029,7 +42196,7 @@ var FileStorage = class {
42029
42196
  async hasToken(key) {
42030
42197
  const filePath = this.getFilePath(key);
42031
42198
  try {
42032
- await fs14__namespace.access(filePath);
42199
+ await fs15__namespace.access(filePath);
42033
42200
  return true;
42034
42201
  } catch {
42035
42202
  return false;
@@ -42040,7 +42207,7 @@ var FileStorage = class {
42040
42207
  */
42041
42208
  async listTokens() {
42042
42209
  try {
42043
- const files = await fs14__namespace.readdir(this.directory);
42210
+ const files = await fs15__namespace.readdir(this.directory);
42044
42211
  return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
42045
42212
  } catch {
42046
42213
  return [];
@@ -42051,10 +42218,10 @@ var FileStorage = class {
42051
42218
  */
42052
42219
  async clearAll() {
42053
42220
  try {
42054
- const files = await fs14__namespace.readdir(this.directory);
42221
+ const files = await fs15__namespace.readdir(this.directory);
42055
42222
  const tokenFiles = files.filter((f) => f.endsWith(".token"));
42056
42223
  await Promise.all(
42057
- tokenFiles.map((f) => fs14__namespace.unlink(path3__namespace.join(this.directory, f)).catch(() => {
42224
+ tokenFiles.map((f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
42058
42225
  }))
42059
42226
  );
42060
42227
  } catch {
@@ -42322,22 +42489,26 @@ var ConnectorConfigStore = class {
42322
42489
  * Encrypt secrets in ConnectorAuth based on auth type
42323
42490
  */
42324
42491
  encryptAuthSecrets(auth2) {
42492
+ const encryptedExtra = this.encryptExtra(auth2.extra);
42325
42493
  switch (auth2.type) {
42326
42494
  case "api_key":
42327
42495
  return {
42328
42496
  ...auth2,
42329
- apiKey: this.encryptValue(auth2.apiKey)
42497
+ apiKey: this.encryptValue(auth2.apiKey),
42498
+ ...encryptedExtra ? { extra: encryptedExtra } : {}
42330
42499
  };
42331
42500
  case "oauth":
42332
42501
  return {
42333
42502
  ...auth2,
42334
42503
  clientSecret: auth2.clientSecret ? this.encryptValue(auth2.clientSecret) : void 0,
42335
- privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0
42504
+ privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0,
42505
+ ...encryptedExtra ? { extra: encryptedExtra } : {}
42336
42506
  };
42337
42507
  case "jwt":
42338
42508
  return {
42339
42509
  ...auth2,
42340
- privateKey: this.encryptValue(auth2.privateKey)
42510
+ privateKey: this.encryptValue(auth2.privateKey),
42511
+ ...encryptedExtra ? { extra: encryptedExtra } : {}
42341
42512
  };
42342
42513
  default:
42343
42514
  return auth2;
@@ -42347,27 +42518,53 @@ var ConnectorConfigStore = class {
42347
42518
  * Decrypt secrets in ConnectorAuth based on auth type
42348
42519
  */
42349
42520
  decryptAuthSecrets(auth2) {
42521
+ const decryptedExtra = this.decryptExtra(auth2.extra);
42350
42522
  switch (auth2.type) {
42351
42523
  case "api_key":
42352
42524
  return {
42353
42525
  ...auth2,
42354
- apiKey: this.decryptValue(auth2.apiKey)
42526
+ apiKey: this.decryptValue(auth2.apiKey),
42527
+ ...decryptedExtra ? { extra: decryptedExtra } : {}
42355
42528
  };
42356
42529
  case "oauth":
42357
42530
  return {
42358
42531
  ...auth2,
42359
42532
  clientSecret: auth2.clientSecret ? this.decryptValue(auth2.clientSecret) : void 0,
42360
- privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0
42533
+ privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0,
42534
+ ...decryptedExtra ? { extra: decryptedExtra } : {}
42361
42535
  };
42362
42536
  case "jwt":
42363
42537
  return {
42364
42538
  ...auth2,
42365
- privateKey: this.decryptValue(auth2.privateKey)
42539
+ privateKey: this.decryptValue(auth2.privateKey),
42540
+ ...decryptedExtra ? { extra: decryptedExtra } : {}
42366
42541
  };
42367
42542
  default:
42368
42543
  return auth2;
42369
42544
  }
42370
42545
  }
42546
+ /**
42547
+ * Encrypt all values in an extra Record (vendor-specific credentials)
42548
+ */
42549
+ encryptExtra(extra) {
42550
+ if (!extra || Object.keys(extra).length === 0) return void 0;
42551
+ const result = {};
42552
+ for (const [key, value] of Object.entries(extra)) {
42553
+ result[key] = this.encryptValue(value);
42554
+ }
42555
+ return result;
42556
+ }
42557
+ /**
42558
+ * Decrypt all values in an extra Record (vendor-specific credentials)
42559
+ */
42560
+ decryptExtra(extra) {
42561
+ if (!extra || Object.keys(extra).length === 0) return void 0;
42562
+ const result = {};
42563
+ for (const [key, value] of Object.entries(extra)) {
42564
+ result[key] = this.decryptValue(value);
42565
+ }
42566
+ return result;
42567
+ }
42371
42568
  /**
42372
42569
  * Encrypt a single value if not already encrypted
42373
42570
  */
@@ -42445,20 +42642,20 @@ var FileConnectorStorage = class {
42445
42642
  throw new Error("FileConnectorStorage requires a directory path");
42446
42643
  }
42447
42644
  this.directory = config.directory;
42448
- this.indexPath = path3__namespace.join(this.directory, "_index.json");
42645
+ this.indexPath = path2__namespace.join(this.directory, "_index.json");
42449
42646
  }
42450
42647
  async save(name, stored) {
42451
42648
  await this.ensureDirectory();
42452
42649
  const filePath = this.getFilePath(name);
42453
42650
  const json = JSON.stringify(stored, null, 2);
42454
- await fs14__namespace.writeFile(filePath, json, "utf8");
42455
- await fs14__namespace.chmod(filePath, 384);
42651
+ await fs15__namespace.writeFile(filePath, json, "utf8");
42652
+ await fs15__namespace.chmod(filePath, 384);
42456
42653
  await this.updateIndex(name, "add");
42457
42654
  }
42458
42655
  async get(name) {
42459
42656
  const filePath = this.getFilePath(name);
42460
42657
  try {
42461
- const json = await fs14__namespace.readFile(filePath, "utf8");
42658
+ const json = await fs15__namespace.readFile(filePath, "utf8");
42462
42659
  return JSON.parse(json);
42463
42660
  } catch (error) {
42464
42661
  const err = error;
@@ -42471,7 +42668,7 @@ var FileConnectorStorage = class {
42471
42668
  async delete(name) {
42472
42669
  const filePath = this.getFilePath(name);
42473
42670
  try {
42474
- await fs14__namespace.unlink(filePath);
42671
+ await fs15__namespace.unlink(filePath);
42475
42672
  await this.updateIndex(name, "remove");
42476
42673
  return true;
42477
42674
  } catch (error) {
@@ -42485,7 +42682,7 @@ var FileConnectorStorage = class {
42485
42682
  async has(name) {
42486
42683
  const filePath = this.getFilePath(name);
42487
42684
  try {
42488
- await fs14__namespace.access(filePath);
42685
+ await fs15__namespace.access(filePath);
42489
42686
  return true;
42490
42687
  } catch {
42491
42688
  return false;
@@ -42511,13 +42708,13 @@ var FileConnectorStorage = class {
42511
42708
  */
42512
42709
  async clear() {
42513
42710
  try {
42514
- const files = await fs14__namespace.readdir(this.directory);
42711
+ const files = await fs15__namespace.readdir(this.directory);
42515
42712
  const connectorFiles = files.filter(
42516
42713
  (f) => f.endsWith(".connector.json") || f === "_index.json"
42517
42714
  );
42518
42715
  await Promise.all(
42519
42716
  connectorFiles.map(
42520
- (f) => fs14__namespace.unlink(path3__namespace.join(this.directory, f)).catch(() => {
42717
+ (f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
42521
42718
  })
42522
42719
  )
42523
42720
  );
@@ -42530,7 +42727,7 @@ var FileConnectorStorage = class {
42530
42727
  */
42531
42728
  getFilePath(name) {
42532
42729
  const hash = this.hashName(name);
42533
- return path3__namespace.join(this.directory, `${hash}.connector.json`);
42730
+ return path2__namespace.join(this.directory, `${hash}.connector.json`);
42534
42731
  }
42535
42732
  /**
42536
42733
  * Hash connector name to prevent enumeration
@@ -42544,8 +42741,8 @@ var FileConnectorStorage = class {
42544
42741
  async ensureDirectory() {
42545
42742
  if (this.initialized) return;
42546
42743
  try {
42547
- await fs14__namespace.mkdir(this.directory, { recursive: true });
42548
- await fs14__namespace.chmod(this.directory, 448);
42744
+ await fs15__namespace.mkdir(this.directory, { recursive: true });
42745
+ await fs15__namespace.chmod(this.directory, 448);
42549
42746
  this.initialized = true;
42550
42747
  } catch {
42551
42748
  this.initialized = true;
@@ -42556,7 +42753,7 @@ var FileConnectorStorage = class {
42556
42753
  */
42557
42754
  async loadIndex() {
42558
42755
  try {
42559
- const json = await fs14__namespace.readFile(this.indexPath, "utf8");
42756
+ const json = await fs15__namespace.readFile(this.indexPath, "utf8");
42560
42757
  return JSON.parse(json);
42561
42758
  } catch {
42562
42759
  return { connectors: {} };
@@ -42574,8 +42771,8 @@ var FileConnectorStorage = class {
42574
42771
  delete index.connectors[hash];
42575
42772
  }
42576
42773
  const json = JSON.stringify(index, null, 2);
42577
- await fs14__namespace.writeFile(this.indexPath, json, "utf8");
42578
- await fs14__namespace.chmod(this.indexPath, 384);
42774
+ await fs15__namespace.writeFile(this.indexPath, json, "utf8");
42775
+ await fs15__namespace.chmod(this.indexPath, 384);
42579
42776
  }
42580
42777
  };
42581
42778
 
@@ -42620,11 +42817,19 @@ function buildAuthConfig(authTemplate, credentials) {
42620
42817
  if (!credentials.apiKey) {
42621
42818
  throw new Error("API key is required for api_key auth");
42622
42819
  }
42820
+ const standardApiKeyFields = /* @__PURE__ */ new Set(["apiKey", "headerName", "headerPrefix"]);
42821
+ const extra = {};
42822
+ for (const field of authTemplate.optionalFields ?? []) {
42823
+ if (!standardApiKeyFields.has(field) && credentials[field]) {
42824
+ extra[field] = credentials[field];
42825
+ }
42826
+ }
42623
42827
  return {
42624
42828
  type: "api_key",
42625
42829
  apiKey: credentials.apiKey,
42626
42830
  headerName: defaults.headerName ?? "Authorization",
42627
- headerPrefix: defaults.headerPrefix ?? "Bearer"
42831
+ headerPrefix: defaults.headerPrefix ?? "Bearer",
42832
+ ...Object.keys(extra).length > 0 ? { extra } : {}
42628
42833
  };
42629
42834
  }
42630
42835
  if (!authTemplate.flow) {
@@ -42894,8 +43099,9 @@ var slackTemplate = {
42894
43099
  id: "bot-token",
42895
43100
  name: "Bot Token",
42896
43101
  type: "api_key",
42897
- description: "Internal workspace bot - get from OAuth & Permissions page of your Slack app",
43102
+ description: "Internal workspace bot - get from OAuth & Permissions page of your Slack app. For Socket Mode bots, also provide appToken and signingSecret in extra fields.",
42898
43103
  requiredFields: ["apiKey"],
43104
+ optionalFields: ["appToken", "signingSecret"],
42899
43105
  defaults: {
42900
43106
  type: "api_key",
42901
43107
  headerName: "Authorization",
@@ -44733,14 +44939,14 @@ function createMessageWithImages(text, imageUrls, role = "user" /* USER */) {
44733
44939
  var execAsync = util.promisify(child_process.exec);
44734
44940
  function cleanupTempFile(filePath) {
44735
44941
  try {
44736
- if (fs15__namespace.existsSync(filePath)) {
44737
- fs15__namespace.unlinkSync(filePath);
44942
+ if (fs16__namespace.existsSync(filePath)) {
44943
+ fs16__namespace.unlinkSync(filePath);
44738
44944
  }
44739
44945
  } catch {
44740
44946
  }
44741
44947
  }
44742
44948
  async function readClipboardImage() {
44743
- const platform2 = os__namespace.platform();
44949
+ const platform2 = os2__namespace.platform();
44744
44950
  try {
44745
44951
  switch (platform2) {
44746
44952
  case "darwin":
@@ -44763,7 +44969,7 @@ async function readClipboardImage() {
44763
44969
  }
44764
44970
  }
44765
44971
  async function readClipboardImageMac() {
44766
- const tempFile = path3__namespace.join(os__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
44972
+ const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
44767
44973
  try {
44768
44974
  try {
44769
44975
  await execAsync(`pngpaste "${tempFile}"`);
@@ -44785,7 +44991,7 @@ async function readClipboardImageMac() {
44785
44991
  end try
44786
44992
  `;
44787
44993
  const { stdout } = await execAsync(`osascript -e '${script}'`);
44788
- if (stdout.includes("success") || fs15__namespace.existsSync(tempFile)) {
44994
+ if (stdout.includes("success") || fs16__namespace.existsSync(tempFile)) {
44789
44995
  return await convertFileToDataUri(tempFile);
44790
44996
  }
44791
44997
  return {
@@ -44798,18 +45004,18 @@ async function readClipboardImageMac() {
44798
45004
  }
44799
45005
  }
44800
45006
  async function readClipboardImageLinux() {
44801
- const tempFile = path3__namespace.join(os__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
45007
+ const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
44802
45008
  try {
44803
45009
  try {
44804
45010
  await execAsync(`xclip -selection clipboard -t image/png -o > "${tempFile}"`);
44805
- if (fs15__namespace.existsSync(tempFile) && fs15__namespace.statSync(tempFile).size > 0) {
45011
+ if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
44806
45012
  return await convertFileToDataUri(tempFile);
44807
45013
  }
44808
45014
  } catch {
44809
45015
  }
44810
45016
  try {
44811
45017
  await execAsync(`wl-paste -t image/png > "${tempFile}"`);
44812
- if (fs15__namespace.existsSync(tempFile) && fs15__namespace.statSync(tempFile).size > 0) {
45018
+ if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
44813
45019
  return await convertFileToDataUri(tempFile);
44814
45020
  }
44815
45021
  } catch {
@@ -44823,7 +45029,7 @@ async function readClipboardImageLinux() {
44823
45029
  }
44824
45030
  }
44825
45031
  async function readClipboardImageWindows() {
44826
- const tempFile = path3__namespace.join(os__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
45032
+ const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
44827
45033
  try {
44828
45034
  const psScript = `
44829
45035
  Add-Type -AssemblyName System.Windows.Forms;
@@ -44836,7 +45042,7 @@ async function readClipboardImageWindows() {
44836
45042
  }
44837
45043
  `;
44838
45044
  await execAsync(`powershell -Command "${psScript}"`);
44839
- if (fs15__namespace.existsSync(tempFile) && fs15__namespace.statSync(tempFile).size > 0) {
45045
+ if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
44840
45046
  return await convertFileToDataUri(tempFile);
44841
45047
  }
44842
45048
  return {
@@ -44849,7 +45055,7 @@ async function readClipboardImageWindows() {
44849
45055
  }
44850
45056
  async function convertFileToDataUri(filePath) {
44851
45057
  try {
44852
- const imageBuffer = fs15__namespace.readFileSync(filePath);
45058
+ const imageBuffer = fs16__namespace.readFileSync(filePath);
44853
45059
  const base64Image = imageBuffer.toString("base64");
44854
45060
  const magic = imageBuffer.slice(0, 4).toString("hex");
44855
45061
  let mimeType = "image/png";
@@ -44876,7 +45082,7 @@ async function convertFileToDataUri(filePath) {
44876
45082
  }
44877
45083
  }
44878
45084
  async function hasClipboardImage() {
44879
- const platform2 = os__namespace.platform();
45085
+ const platform2 = os2__namespace.platform();
44880
45086
  try {
44881
45087
  switch (platform2) {
44882
45088
  case "darwin":
@@ -45094,17 +45300,24 @@ __export(tools_exports, {
45094
45300
  ConnectorTools: () => ConnectorTools,
45095
45301
  DEFAULT_FILESYSTEM_CONFIG: () => DEFAULT_FILESYSTEM_CONFIG,
45096
45302
  DEFAULT_SHELL_CONFIG: () => DEFAULT_SHELL_CONFIG,
45097
- FileMediaOutputHandler: () => FileMediaOutputHandler,
45303
+ FileMediaOutputHandler: () => FileMediaStorage,
45098
45304
  ToolRegistry: () => ToolRegistry,
45099
45305
  bash: () => bash,
45100
45306
  createBashTool: () => createBashTool,
45307
+ createCreatePRTool: () => createCreatePRTool,
45101
45308
  createEditFileTool: () => createEditFileTool,
45102
45309
  createExecuteJavaScriptTool: () => createExecuteJavaScriptTool,
45310
+ createGetPRTool: () => createGetPRTool,
45311
+ createGitHubReadFileTool: () => createGitHubReadFileTool,
45103
45312
  createGlobTool: () => createGlobTool,
45104
45313
  createGrepTool: () => createGrepTool,
45105
45314
  createImageGenerationTool: () => createImageGenerationTool,
45106
45315
  createListDirectoryTool: () => createListDirectoryTool,
45316
+ createPRCommentsTool: () => createPRCommentsTool,
45317
+ createPRFilesTool: () => createPRFilesTool,
45107
45318
  createReadFileTool: () => createReadFileTool,
45319
+ createSearchCodeTool: () => createSearchCodeTool,
45320
+ createSearchFilesTool: () => createSearchFilesTool,
45108
45321
  createSpeechToTextTool: () => createSpeechToTextTool,
45109
45322
  createTextToSpeechTool: () => createTextToSpeechTool,
45110
45323
  createVideoTools: () => createVideoTools,
@@ -45116,6 +45329,7 @@ __export(tools_exports, {
45116
45329
  getAllBuiltInTools: () => getAllBuiltInTools,
45117
45330
  getBackgroundOutput: () => getBackgroundOutput,
45118
45331
  getMediaOutputHandler: () => getMediaOutputHandler,
45332
+ getMediaStorage: () => getMediaStorage,
45119
45333
  getToolByName: () => getToolByName,
45120
45334
  getToolCategories: () => getToolCategories,
45121
45335
  getToolRegistry: () => getToolRegistry,
@@ -45128,15 +45342,18 @@ __export(tools_exports, {
45128
45342
  jsonManipulator: () => jsonManipulator,
45129
45343
  killBackgroundProcess: () => killBackgroundProcess,
45130
45344
  listDirectory: () => listDirectory,
45131
- readFile: () => readFile4,
45345
+ parseRepository: () => parseRepository,
45346
+ readFile: () => readFile5,
45347
+ resolveRepository: () => resolveRepository,
45132
45348
  setMediaOutputHandler: () => setMediaOutputHandler,
45349
+ setMediaStorage: () => setMediaStorage,
45133
45350
  toolRegistry: () => toolRegistry,
45134
45351
  validatePath: () => validatePath,
45135
45352
  webFetch: () => webFetch,
45136
45353
  webFetchJS: () => webFetchJS,
45137
45354
  webScrape: () => webScrape,
45138
45355
  webSearch: () => webSearch,
45139
- writeFile: () => writeFile4
45356
+ writeFile: () => writeFile5
45140
45357
  });
45141
45358
  var DEFAULT_FILESYSTEM_CONFIG = {
45142
45359
  workingDirectory: process.cwd(),
@@ -45195,15 +45412,15 @@ function validatePath(inputPath, config = {}) {
45195
45412
  const blockedDirs = config.blockedDirectories || DEFAULT_FILESYSTEM_CONFIG.blockedDirectories;
45196
45413
  let expandedPath = inputPath;
45197
45414
  if (inputPath.startsWith("~/")) {
45198
- expandedPath = path3.resolve(os.homedir(), inputPath.slice(2));
45415
+ expandedPath = path2.resolve(os2.homedir(), inputPath.slice(2));
45199
45416
  } else if (inputPath === "~") {
45200
- expandedPath = os.homedir();
45417
+ expandedPath = os2.homedir();
45201
45418
  }
45202
45419
  let resolvedPath;
45203
- if (path3.isAbsolute(expandedPath)) {
45204
- resolvedPath = path3.normalize(expandedPath);
45420
+ if (path2.isAbsolute(expandedPath)) {
45421
+ resolvedPath = path2.normalize(expandedPath);
45205
45422
  } else {
45206
- resolvedPath = path3.resolve(workingDir, expandedPath);
45423
+ resolvedPath = path2.resolve(workingDir, expandedPath);
45207
45424
  }
45208
45425
  const pathSegments = resolvedPath.split("/").filter(Boolean);
45209
45426
  for (const blocked of blockedDirs) {
@@ -45216,7 +45433,7 @@ function validatePath(inputPath, config = {}) {
45216
45433
  };
45217
45434
  }
45218
45435
  } else {
45219
- const blockedPath = path3.isAbsolute(blocked) ? blocked : path3.resolve(workingDir, blocked);
45436
+ const blockedPath = path2.isAbsolute(blocked) ? blocked : path2.resolve(workingDir, blocked);
45220
45437
  if (resolvedPath.startsWith(blockedPath + "/") || resolvedPath === blockedPath) {
45221
45438
  return {
45222
45439
  valid: false,
@@ -45229,7 +45446,7 @@ function validatePath(inputPath, config = {}) {
45229
45446
  if (allowedDirs.length > 0) {
45230
45447
  let isAllowed = false;
45231
45448
  for (const allowed of allowedDirs) {
45232
- const allowedPath = path3.isAbsolute(allowed) ? allowed : path3.resolve(workingDir, allowed);
45449
+ const allowedPath = path2.isAbsolute(allowed) ? allowed : path2.resolve(workingDir, allowed);
45233
45450
  if (resolvedPath.startsWith(allowedPath + "/") || resolvedPath === allowedPath) {
45234
45451
  isAllowed = true;
45235
45452
  break;
@@ -45247,9 +45464,9 @@ function validatePath(inputPath, config = {}) {
45247
45464
  }
45248
45465
  function expandTilde(inputPath) {
45249
45466
  if (inputPath.startsWith("~/")) {
45250
- return path3.resolve(os.homedir(), inputPath.slice(2));
45467
+ return path2.resolve(os2.homedir(), inputPath.slice(2));
45251
45468
  } else if (inputPath === "~") {
45252
- return os.homedir();
45469
+ return os2.homedir();
45253
45470
  }
45254
45471
  return inputPath;
45255
45472
  }
@@ -45324,7 +45541,7 @@ EXAMPLES:
45324
45541
  };
45325
45542
  }
45326
45543
  const resolvedPath = validation.resolvedPath;
45327
- if (!fs15.existsSync(resolvedPath)) {
45544
+ if (!fs16.existsSync(resolvedPath)) {
45328
45545
  return {
45329
45546
  success: false,
45330
45547
  error: `File not found: ${file_path}`,
@@ -45332,7 +45549,7 @@ EXAMPLES:
45332
45549
  };
45333
45550
  }
45334
45551
  try {
45335
- const stats = await fs14.stat(resolvedPath);
45552
+ const stats = await fs15.stat(resolvedPath);
45336
45553
  if (!stats.isFile()) {
45337
45554
  return {
45338
45555
  success: false,
@@ -45348,7 +45565,7 @@ EXAMPLES:
45348
45565
  size: stats.size
45349
45566
  };
45350
45567
  }
45351
- const content = await fs14.readFile(resolvedPath, "utf-8");
45568
+ const content = await fs15.readFile(resolvedPath, "utf-8");
45352
45569
  const allLines = content.split("\n");
45353
45570
  const totalLines = allLines.length;
45354
45571
  const startIndex = Math.max(0, offset - 1);
@@ -45389,7 +45606,7 @@ EXAMPLES:
45389
45606
  }
45390
45607
  };
45391
45608
  }
45392
- var readFile4 = createReadFileTool();
45609
+ var readFile5 = createReadFileTool();
45393
45610
  function createWriteFileTool(config = {}) {
45394
45611
  const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
45395
45612
  return {
@@ -45453,13 +45670,13 @@ EXAMPLES:
45453
45670
  };
45454
45671
  }
45455
45672
  const resolvedPath = validation.resolvedPath;
45456
- const fileExists = fs15.existsSync(resolvedPath);
45673
+ const fileExists = fs16.existsSync(resolvedPath);
45457
45674
  try {
45458
- const parentDir = path3.dirname(resolvedPath);
45459
- if (!fs15.existsSync(parentDir)) {
45460
- await fs14.mkdir(parentDir, { recursive: true });
45675
+ const parentDir = path2.dirname(resolvedPath);
45676
+ if (!fs16.existsSync(parentDir)) {
45677
+ await fs15.mkdir(parentDir, { recursive: true });
45461
45678
  }
45462
- await fs14.writeFile(resolvedPath, content, "utf-8");
45679
+ await fs15.writeFile(resolvedPath, content, "utf-8");
45463
45680
  return {
45464
45681
  success: true,
45465
45682
  path: file_path,
@@ -45476,7 +45693,7 @@ EXAMPLES:
45476
45693
  }
45477
45694
  };
45478
45695
  }
45479
- var writeFile4 = createWriteFileTool();
45696
+ var writeFile5 = createWriteFileTool();
45480
45697
  function createEditFileTool(config = {}) {
45481
45698
  const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
45482
45699
  return {
@@ -45562,7 +45779,7 @@ EXAMPLES:
45562
45779
  };
45563
45780
  }
45564
45781
  const resolvedPath = validation.resolvedPath;
45565
- if (!fs15.existsSync(resolvedPath)) {
45782
+ if (!fs16.existsSync(resolvedPath)) {
45566
45783
  return {
45567
45784
  success: false,
45568
45785
  error: `File not found: ${file_path}`,
@@ -45570,7 +45787,7 @@ EXAMPLES:
45570
45787
  };
45571
45788
  }
45572
45789
  try {
45573
- const content = await fs14.readFile(resolvedPath, "utf-8");
45790
+ const content = await fs15.readFile(resolvedPath, "utf-8");
45574
45791
  let occurrences = 0;
45575
45792
  let searchIndex = 0;
45576
45793
  while (true) {
@@ -45609,7 +45826,7 @@ EXAMPLES:
45609
45826
  } else {
45610
45827
  newContent = content.replace(old_string, new_string);
45611
45828
  }
45612
- await fs14.writeFile(resolvedPath, newContent, "utf-8");
45829
+ await fs15.writeFile(resolvedPath, newContent, "utf-8");
45613
45830
  const diffPreview = generateDiffPreview(old_string, new_string);
45614
45831
  return {
45615
45832
  success: true,
@@ -45665,11 +45882,11 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
45665
45882
  return results;
45666
45883
  }
45667
45884
  try {
45668
- const entries = await fs14.readdir(dir, { withFileTypes: true });
45885
+ const entries = await fs15.readdir(dir, { withFileTypes: true });
45669
45886
  for (const entry of entries) {
45670
45887
  if (results.length >= config.maxResults) break;
45671
- const fullPath = path3.join(dir, entry.name);
45672
- const relativePath = path3.relative(baseDir, fullPath);
45888
+ const fullPath = path2.join(dir, entry.name);
45889
+ const relativePath = path2.relative(baseDir, fullPath);
45673
45890
  if (entry.isDirectory()) {
45674
45891
  const isBlocked = config.blockedDirectories.some(
45675
45892
  (blocked) => entry.name === blocked || relativePath.includes(`/${blocked}/`) || relativePath.startsWith(`${blocked}/`)
@@ -45679,7 +45896,7 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
45679
45896
  } else if (entry.isFile()) {
45680
45897
  if (matchGlobPattern(pattern, relativePath)) {
45681
45898
  try {
45682
- const stats = await fs14.stat(fullPath);
45899
+ const stats = await fs15.stat(fullPath);
45683
45900
  results.push({
45684
45901
  path: relativePath,
45685
45902
  mtime: stats.mtimeMs
@@ -45761,7 +45978,7 @@ WHEN TO USE:
45761
45978
  };
45762
45979
  }
45763
45980
  const resolvedDir = validation.resolvedPath;
45764
- if (!fs15.existsSync(resolvedDir)) {
45981
+ if (!fs16.existsSync(resolvedDir)) {
45765
45982
  return {
45766
45983
  success: false,
45767
45984
  error: `Directory not found: ${searchDir}`
@@ -45816,9 +46033,9 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
45816
46033
  return files;
45817
46034
  }
45818
46035
  try {
45819
- const entries = await fs14.readdir(dir, { withFileTypes: true });
46036
+ const entries = await fs15.readdir(dir, { withFileTypes: true });
45820
46037
  for (const entry of entries) {
45821
- const fullPath = path3.join(dir, entry.name);
46038
+ const fullPath = path2.join(dir, entry.name);
45822
46039
  if (entry.isDirectory()) {
45823
46040
  const isBlocked = config.blockedDirectories.some(
45824
46041
  (blocked) => entry.name === blocked
@@ -45830,7 +46047,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
45830
46047
  if (fileType) {
45831
46048
  const extensions = FILE_TYPE_MAP[fileType.toLowerCase()];
45832
46049
  if (extensions) {
45833
- const ext = path3.extname(entry.name).toLowerCase();
46050
+ const ext = path2.extname(entry.name).toLowerCase();
45834
46051
  if (!extensions.includes(ext)) continue;
45835
46052
  }
45836
46053
  }
@@ -45849,7 +46066,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
45849
46066
  async function searchFile(filePath, regex, contextBefore, contextAfter) {
45850
46067
  const matches = [];
45851
46068
  try {
45852
- const content = await fs14.readFile(filePath, "utf-8");
46069
+ const content = await fs15.readFile(filePath, "utf-8");
45853
46070
  const lines = content.split("\n");
45854
46071
  for (let i = 0; i < lines.length; i++) {
45855
46072
  const line = lines[i] ?? "";
@@ -45990,7 +46207,7 @@ WHEN TO USE:
45990
46207
  };
45991
46208
  }
45992
46209
  const resolvedPath = validation.resolvedPath;
45993
- if (!fs15.existsSync(resolvedPath)) {
46210
+ if (!fs16.existsSync(resolvedPath)) {
45994
46211
  return {
45995
46212
  success: false,
45996
46213
  error: `Path not found: ${searchPath}`
@@ -46006,7 +46223,7 @@ WHEN TO USE:
46006
46223
  };
46007
46224
  }
46008
46225
  try {
46009
- const stats = await fs14.stat(resolvedPath);
46226
+ const stats = await fs15.stat(resolvedPath);
46010
46227
  let filesToSearch;
46011
46228
  if (stats.isFile()) {
46012
46229
  filesToSearch = [resolvedPath];
@@ -46032,7 +46249,7 @@ WHEN TO USE:
46032
46249
  );
46033
46250
  if (matches.length > 0) {
46034
46251
  filesMatched++;
46035
- const relativePath = path3.relative(resolvedPath, file) || file;
46252
+ const relativePath = path2.relative(resolvedPath, file) || file;
46036
46253
  for (const match of matches) {
46037
46254
  match.file = relativePath;
46038
46255
  }
@@ -46094,11 +46311,11 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
46094
46311
  return entries;
46095
46312
  }
46096
46313
  try {
46097
- const dirEntries = await fs14.readdir(dir, { withFileTypes: true });
46314
+ const dirEntries = await fs15.readdir(dir, { withFileTypes: true });
46098
46315
  for (const entry of dirEntries) {
46099
46316
  if (entries.length >= config.maxResults) break;
46100
- const fullPath = path3.join(dir, entry.name);
46101
- const relativePath = path3.relative(baseDir, fullPath);
46317
+ const fullPath = path2.join(dir, entry.name);
46318
+ const relativePath = path2.relative(baseDir, fullPath);
46102
46319
  if (entry.isDirectory() && config.blockedDirectories.includes(entry.name)) {
46103
46320
  continue;
46104
46321
  }
@@ -46112,7 +46329,7 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
46112
46329
  }
46113
46330
  if (filter === "directories" && !isDir) continue;
46114
46331
  try {
46115
- const stats = await fs14.stat(fullPath);
46332
+ const stats = await fs15.stat(fullPath);
46116
46333
  const dirEntry = {
46117
46334
  name: entry.name,
46118
46335
  path: relativePath,
@@ -46208,14 +46425,14 @@ EXAMPLES:
46208
46425
  };
46209
46426
  }
46210
46427
  const resolvedPath = validation.resolvedPath;
46211
- if (!fs15.existsSync(resolvedPath)) {
46428
+ if (!fs16.existsSync(resolvedPath)) {
46212
46429
  return {
46213
46430
  success: false,
46214
46431
  error: `Directory not found: ${path6}`
46215
46432
  };
46216
46433
  }
46217
46434
  try {
46218
- const stats = await fs14.stat(resolvedPath);
46435
+ const stats = await fs15.stat(resolvedPath);
46219
46436
  if (!stats.isDirectory()) {
46220
46437
  return {
46221
46438
  success: false,
@@ -46403,7 +46620,8 @@ EXAMPLES:
46403
46620
  shell: mergedConfig.shell,
46404
46621
  cwd: mergedConfig.workingDirectory,
46405
46622
  env,
46406
- stdio: ["pipe", "pipe", "pipe"]
46623
+ stdio: ["pipe", "pipe", "pipe"],
46624
+ detached: true
46407
46625
  });
46408
46626
  if (run_in_background && mergedConfig.allowBackground) {
46409
46627
  const bgId = generateBackgroundId();
@@ -46430,14 +46648,27 @@ EXAMPLES:
46430
46648
  let stdout = "";
46431
46649
  let stderr = "";
46432
46650
  let killed = false;
46651
+ const killProcessGroup = (signal) => {
46652
+ try {
46653
+ if (childProcess.pid) {
46654
+ process.kill(-childProcess.pid, signal);
46655
+ }
46656
+ } catch {
46657
+ try {
46658
+ childProcess.kill(signal);
46659
+ } catch {
46660
+ }
46661
+ }
46662
+ };
46663
+ const GRACEFUL_KILL_WAIT_MS = 3e3;
46433
46664
  const timeoutId = setTimeout(() => {
46434
46665
  killed = true;
46435
- childProcess.kill("SIGTERM");
46666
+ killProcessGroup("SIGTERM");
46436
46667
  setTimeout(() => {
46437
46668
  if (!childProcess.killed) {
46438
- childProcess.kill("SIGKILL");
46669
+ killProcessGroup("SIGKILL");
46439
46670
  }
46440
- }, 5e3);
46671
+ }, GRACEFUL_KILL_WAIT_MS);
46441
46672
  }, effectiveTimeout);
46442
46673
  childProcess.stdout.on("data", (data) => {
46443
46674
  stdout += data.toString();
@@ -46451,8 +46682,28 @@ EXAMPLES:
46451
46682
  stderr = stderr.slice(-mergedConfig.maxOutputSize);
46452
46683
  }
46453
46684
  });
46454
- childProcess.on("close", (code, signal) => {
46685
+ let resolved = false;
46686
+ const safeResolve = (result) => {
46687
+ if (resolved) return;
46688
+ resolved = true;
46455
46689
  clearTimeout(timeoutId);
46690
+ clearTimeout(hardTimeoutId);
46691
+ resolve4(result);
46692
+ };
46693
+ const HARD_TIMEOUT_GRACE_MS = 5e3;
46694
+ const hardTimeoutId = setTimeout(() => {
46695
+ if (!resolved) {
46696
+ killProcessGroup("SIGKILL");
46697
+ safeResolve({
46698
+ success: false,
46699
+ stdout,
46700
+ stderr,
46701
+ duration: Date.now() - startTime,
46702
+ error: `Command timed out after ${effectiveTimeout}ms (hard timeout: process group did not exit)`
46703
+ });
46704
+ }
46705
+ }, effectiveTimeout + GRACEFUL_KILL_WAIT_MS + HARD_TIMEOUT_GRACE_MS);
46706
+ childProcess.on("close", (code, signal) => {
46456
46707
  const duration = Date.now() - startTime;
46457
46708
  let truncated = false;
46458
46709
  if (stdout.length > mergedConfig.maxOutputSize) {
@@ -46464,7 +46715,7 @@ EXAMPLES:
46464
46715
  truncated = true;
46465
46716
  }
46466
46717
  if (killed) {
46467
- resolve4({
46718
+ safeResolve({
46468
46719
  success: false,
46469
46720
  stdout,
46470
46721
  stderr,
@@ -46475,7 +46726,7 @@ EXAMPLES:
46475
46726
  error: `Command timed out after ${effectiveTimeout}ms`
46476
46727
  });
46477
46728
  } else {
46478
- resolve4({
46729
+ safeResolve({
46479
46730
  success: code === 0,
46480
46731
  stdout,
46481
46732
  stderr,
@@ -46488,8 +46739,7 @@ EXAMPLES:
46488
46739
  }
46489
46740
  });
46490
46741
  childProcess.on("error", (error) => {
46491
- clearTimeout(timeoutId);
46492
- resolve4({
46742
+ safeResolve({
46493
46743
  success: false,
46494
46744
  error: `Failed to execute command: ${error.message}`,
46495
46745
  duration: Date.now() - startTime
@@ -47755,8 +48005,8 @@ async function tryNative(args, startTime, attemptedMethods) {
47755
48005
  method: "native",
47756
48006
  title: result.title,
47757
48007
  content: cleanContent,
47758
- // Note: raw HTML not available with native method (returns markdown instead)
47759
- markdown: args.includeMarkdown ? cleanContent : void 0,
48008
+ // Native method already returns markdown-like content no separate markdown field needed
48009
+ // (would just duplicate content and waste tokens)
47760
48010
  qualityScore: result.qualityScore,
47761
48011
  durationMs: Date.now() - startTime,
47762
48012
  attemptedMethods,
@@ -47792,8 +48042,7 @@ async function tryJS(args, startTime, attemptedMethods) {
47792
48042
  method: "js",
47793
48043
  title: result.title,
47794
48044
  content: cleanContent,
47795
- // Note: raw HTML not available with JS method (returns markdown instead)
47796
- markdown: args.includeMarkdown ? cleanContent : void 0,
48045
+ // JS method already returns markdown-like content no separate markdown field needed
47797
48046
  qualityScore: result.success ? 80 : 0,
47798
48047
  durationMs: Date.now() - startTime,
47799
48048
  attemptedMethods,
@@ -47825,8 +48074,11 @@ async function tryAPI(connectorName, args, startTime, attemptedMethods) {
47825
48074
  includeLinks: args.includeLinks
47826
48075
  };
47827
48076
  const result = await provider.scrape(args.url, options);
47828
- const cleanContent = stripBase64DataUris(result.result?.content || "");
47829
- const cleanMarkdown = result.result?.markdown ? stripBase64DataUris(result.result.markdown) : void 0;
48077
+ const rawContent = result.result?.content || "";
48078
+ const rawMarkdown = result.result?.markdown;
48079
+ const cleanContent = stripBase64DataUris(rawContent);
48080
+ const cleanMarkdown = rawMarkdown ? stripBase64DataUris(rawMarkdown) : void 0;
48081
+ const isDuplicate = !!cleanMarkdown && cleanContent === cleanMarkdown;
47830
48082
  return {
47831
48083
  success: result.success,
47832
48084
  url: args.url,
@@ -47836,7 +48088,7 @@ async function tryAPI(connectorName, args, startTime, attemptedMethods) {
47836
48088
  content: cleanContent,
47837
48089
  html: result.result?.html,
47838
48090
  // Keep raw HTML as-is (only used if explicitly requested)
47839
- markdown: cleanMarkdown,
48091
+ markdown: isDuplicate ? void 0 : cleanMarkdown,
47840
48092
  metadata: result.result?.metadata,
47841
48093
  links: result.result?.links,
47842
48094
  qualityScore: result.success ? 90 : 0,
@@ -48051,68 +48303,25 @@ async function executeInVM(code, input, timeout, logs) {
48051
48303
  const result = await resultPromise;
48052
48304
  return result !== void 0 ? result : sandbox.output;
48053
48305
  }
48054
- var MIME_TYPES = {
48055
- png: "image/png",
48056
- jpeg: "image/jpeg",
48057
- jpg: "image/jpeg",
48058
- webp: "image/webp",
48059
- gif: "image/gif",
48060
- mp4: "video/mp4",
48061
- webm: "video/webm",
48062
- mp3: "audio/mpeg",
48063
- wav: "audio/wav",
48064
- opus: "audio/opus",
48065
- ogg: "audio/ogg",
48066
- aac: "audio/aac",
48067
- flac: "audio/flac",
48068
- pcm: "audio/pcm"
48069
- };
48070
- var FileMediaOutputHandler = class {
48071
- outputDir;
48072
- initialized = false;
48073
- constructor(outputDir) {
48074
- this.outputDir = outputDir ?? path3__namespace.join(os__namespace.tmpdir(), "oneringai-media");
48075
- }
48076
- async save(data, metadata) {
48077
- if (!this.initialized) {
48078
- await fs14__namespace.mkdir(this.outputDir, { recursive: true });
48079
- this.initialized = true;
48080
- }
48081
- const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
48082
- const filePath = path3__namespace.join(this.outputDir, filename);
48083
- await fs14__namespace.writeFile(filePath, data);
48084
- const format = metadata.format.toLowerCase();
48085
- const mimeType = MIME_TYPES[format] ?? `application/octet-stream`;
48086
- return {
48087
- location: filePath,
48088
- mimeType,
48089
- size: data.length
48090
- };
48091
- }
48092
- generateFilename(metadata) {
48093
- const timestamp = Date.now();
48094
- const random2 = crypto2__namespace.randomBytes(4).toString("hex");
48095
- const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
48096
- return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
48097
- }
48098
- };
48099
48306
 
48100
48307
  // src/tools/multimedia/config.ts
48101
- var _outputHandler = null;
48102
- function getMediaOutputHandler() {
48103
- if (!_outputHandler) {
48104
- _outputHandler = new FileMediaOutputHandler();
48308
+ var _storage = null;
48309
+ function getMediaStorage() {
48310
+ if (!_storage) {
48311
+ _storage = new FileMediaStorage();
48105
48312
  }
48106
- return _outputHandler;
48313
+ return _storage;
48107
48314
  }
48108
- function setMediaOutputHandler(handler) {
48109
- _outputHandler = handler;
48315
+ function setMediaStorage(storage) {
48316
+ _storage = storage;
48110
48317
  }
48318
+ var getMediaOutputHandler = getMediaStorage;
48319
+ var setMediaOutputHandler = setMediaStorage;
48111
48320
 
48112
48321
  // src/tools/multimedia/imageGeneration.ts
48113
- function createImageGenerationTool(connector, outputHandler) {
48322
+ function createImageGenerationTool(connector, storage, userId) {
48114
48323
  const vendor = connector.vendor;
48115
- const handler = outputHandler ?? getMediaOutputHandler();
48324
+ const handler = storage ?? getMediaStorage();
48116
48325
  const vendorModels = vendor ? getImageModelsByVendor(vendor) : [];
48117
48326
  const modelNames = vendorModels.map((m) => m.name);
48118
48327
  const properties = {
@@ -48185,8 +48394,9 @@ function createImageGenerationTool(connector, outputHandler) {
48185
48394
  }
48186
48395
  }
48187
48396
  },
48188
- execute: async (args) => {
48397
+ execute: async (args, context) => {
48189
48398
  try {
48399
+ const effectiveUserId = userId ?? context?.userId;
48190
48400
  const imageGen = ImageGeneration.create({ connector });
48191
48401
  const response = await imageGen.generate({
48192
48402
  prompt: args.prompt,
@@ -48217,7 +48427,8 @@ function createImageGenerationTool(connector, outputHandler) {
48217
48427
  format,
48218
48428
  model: modelName,
48219
48429
  vendor: vendor || "unknown",
48220
- index: response.data.length > 1 ? i : void 0
48430
+ index: response.data.length > 1 ? i : void 0,
48431
+ userId: effectiveUserId
48221
48432
  });
48222
48433
  images.push({
48223
48434
  location: result.location,
@@ -48244,9 +48455,9 @@ function createImageGenerationTool(connector, outputHandler) {
48244
48455
 
48245
48456
  // src/tools/multimedia/videoGeneration.ts
48246
48457
  var videoGenInstances = /* @__PURE__ */ new Map();
48247
- function createVideoTools(connector, outputHandler) {
48458
+ function createVideoTools(connector, storage, userId) {
48248
48459
  const vendor = connector.vendor;
48249
- const handler = outputHandler ?? getMediaOutputHandler();
48460
+ const handler = storage ?? getMediaStorage();
48250
48461
  const vendorModels = vendor ? getVideoModelsByVendor(vendor) : [];
48251
48462
  const modelNames = vendorModels.map((m) => m.name);
48252
48463
  const generateProperties = {
@@ -48310,7 +48521,7 @@ function createVideoTools(connector, outputHandler) {
48310
48521
  }
48311
48522
  }
48312
48523
  },
48313
- execute: async (args) => {
48524
+ execute: async (args, _context) => {
48314
48525
  try {
48315
48526
  const videoGen = VideoGeneration.create({ connector });
48316
48527
  const response = await videoGen.generate({
@@ -48359,8 +48570,9 @@ function createVideoTools(connector, outputHandler) {
48359
48570
  }
48360
48571
  }
48361
48572
  },
48362
- execute: async (args) => {
48573
+ execute: async (args, context) => {
48363
48574
  try {
48575
+ const effectiveUserId = userId ?? context?.userId;
48364
48576
  let videoGen = videoGenInstances.get(args.jobId);
48365
48577
  if (!videoGen) {
48366
48578
  videoGen = VideoGeneration.create({ connector });
@@ -48386,7 +48598,8 @@ function createVideoTools(connector, outputHandler) {
48386
48598
  type: "video",
48387
48599
  format,
48388
48600
  model: modelName,
48389
- vendor: vendor || "unknown"
48601
+ vendor: vendor || "unknown",
48602
+ userId: effectiveUserId
48390
48603
  });
48391
48604
  videoGenInstances.delete(args.jobId);
48392
48605
  return {
@@ -48434,9 +48647,9 @@ function createVideoTools(connector, outputHandler) {
48434
48647
  }
48435
48648
 
48436
48649
  // src/tools/multimedia/textToSpeech.ts
48437
- function createTextToSpeechTool(connector, outputHandler) {
48650
+ function createTextToSpeechTool(connector, storage, userId) {
48438
48651
  const vendor = connector.vendor;
48439
- const handler = outputHandler ?? getMediaOutputHandler();
48652
+ const handler = storage ?? getMediaStorage();
48440
48653
  const vendorModels = vendor ? getTTSModelsByVendor(vendor) : [];
48441
48654
  const modelNames = vendorModels.map((m) => m.name);
48442
48655
  const properties = {
@@ -48497,8 +48710,9 @@ function createTextToSpeechTool(connector, outputHandler) {
48497
48710
  }
48498
48711
  }
48499
48712
  },
48500
- execute: async (args) => {
48713
+ execute: async (args, context) => {
48501
48714
  try {
48715
+ const effectiveUserId = userId ?? context?.userId;
48502
48716
  const tts = TextToSpeech.create({
48503
48717
  connector,
48504
48718
  model: args.model,
@@ -48512,7 +48726,8 @@ function createTextToSpeechTool(connector, outputHandler) {
48512
48726
  type: "audio",
48513
48727
  format,
48514
48728
  model: args.model || modelNames[0] || "unknown",
48515
- vendor: vendor || "unknown"
48729
+ vendor: vendor || "unknown",
48730
+ userId: effectiveUserId
48516
48731
  });
48517
48732
  return {
48518
48733
  success: true,
@@ -48535,14 +48750,17 @@ function createTextToSpeechTool(connector, outputHandler) {
48535
48750
  }
48536
48751
  };
48537
48752
  }
48538
- function createSpeechToTextTool(connector) {
48753
+
48754
+ // src/tools/multimedia/speechToText.ts
48755
+ function createSpeechToTextTool(connector, storage, _userId) {
48539
48756
  const vendor = connector.vendor;
48757
+ const handler = storage ?? getMediaStorage();
48540
48758
  const vendorModels = vendor ? getSTTModelsByVendor(vendor) : [];
48541
48759
  const modelNames = vendorModels.map((m) => m.name);
48542
48760
  const properties = {
48543
- audioFilePath: {
48761
+ audioSource: {
48544
48762
  type: "string",
48545
- description: "Path to the audio file to transcribe"
48763
+ description: "Path or location of the audio file to transcribe (file path, storage location, etc.)"
48546
48764
  }
48547
48765
  };
48548
48766
  if (modelNames.length > 0) {
@@ -48570,13 +48788,19 @@ function createSpeechToTextTool(connector) {
48570
48788
  parameters: {
48571
48789
  type: "object",
48572
48790
  properties,
48573
- required: ["audioFilePath"]
48791
+ required: ["audioSource"]
48574
48792
  }
48575
48793
  }
48576
48794
  },
48577
- execute: async (args) => {
48795
+ execute: async (args, _context) => {
48578
48796
  try {
48579
- const audioBuffer = await fs14__namespace.readFile(args.audioFilePath);
48797
+ const audioBuffer = await handler.read(args.audioSource);
48798
+ if (!audioBuffer) {
48799
+ return {
48800
+ success: false,
48801
+ error: `Audio not found at: ${args.audioSource}`
48802
+ };
48803
+ }
48580
48804
  const stt = SpeechToText.create({
48581
48805
  connector,
48582
48806
  model: args.model,
@@ -48598,7 +48822,7 @@ function createSpeechToTextTool(connector) {
48598
48822
  };
48599
48823
  }
48600
48824
  },
48601
- describeCall: (args) => args.audioFilePath,
48825
+ describeCall: (args) => args.audioSource,
48602
48826
  permission: {
48603
48827
  scope: "session",
48604
48828
  riskLevel: "low",
@@ -48613,21 +48837,22 @@ var VENDOR_CAPABILITIES = {
48613
48837
  [Vendor.Google]: ["image", "video", "tts"],
48614
48838
  [Vendor.Grok]: ["image", "video"]
48615
48839
  };
48616
- function registerMultimediaTools() {
48840
+ function registerMultimediaTools(storage) {
48617
48841
  for (const [vendor, capabilities] of Object.entries(VENDOR_CAPABILITIES)) {
48618
- ConnectorTools.registerService(vendor, (connector, _userId) => {
48842
+ ConnectorTools.registerService(vendor, (connector, userId) => {
48843
+ const handler = getMediaStorage();
48619
48844
  const tools = [];
48620
48845
  if (capabilities.includes("image")) {
48621
- tools.push(createImageGenerationTool(connector));
48846
+ tools.push(createImageGenerationTool(connector, handler, userId));
48622
48847
  }
48623
48848
  if (capabilities.includes("video")) {
48624
- tools.push(...createVideoTools(connector));
48849
+ tools.push(...createVideoTools(connector, handler, userId));
48625
48850
  }
48626
48851
  if (capabilities.includes("tts")) {
48627
- tools.push(createTextToSpeechTool(connector));
48852
+ tools.push(createTextToSpeechTool(connector, handler, userId));
48628
48853
  }
48629
48854
  if (capabilities.includes("stt")) {
48630
- tools.push(createSpeechToTextTool(connector));
48855
+ tools.push(createSpeechToTextTool(connector, handler));
48631
48856
  }
48632
48857
  return tools;
48633
48858
  });
@@ -48637,6 +48862,851 @@ function registerMultimediaTools() {
48637
48862
  // src/tools/multimedia/index.ts
48638
48863
  registerMultimediaTools();
48639
48864
 
48865
+ // src/tools/github/types.ts
48866
+ function parseRepository(input) {
48867
+ if (!input || input.trim().length === 0) {
48868
+ throw new Error("Repository cannot be empty");
48869
+ }
48870
+ const trimmed = input.trim();
48871
+ try {
48872
+ const url2 = new URL(trimmed);
48873
+ if (url2.hostname === "github.com" || url2.hostname === "www.github.com") {
48874
+ const segments = url2.pathname.split("/").filter(Boolean);
48875
+ if (segments.length >= 2) {
48876
+ return { owner: segments[0], repo: segments[1].replace(/\.git$/, "") };
48877
+ }
48878
+ }
48879
+ } catch {
48880
+ }
48881
+ const parts = trimmed.split("/");
48882
+ if (parts.length === 2 && parts[0].length > 0 && parts[1].length > 0) {
48883
+ return { owner: parts[0], repo: parts[1] };
48884
+ }
48885
+ throw new Error(
48886
+ `Invalid repository format: "${input}". Expected "owner/repo" or "https://github.com/owner/repo"`
48887
+ );
48888
+ }
48889
+ function resolveRepository(repository, connector) {
48890
+ const repoStr = repository ?? connector.getOptions().defaultRepository;
48891
+ if (!repoStr) {
48892
+ return {
48893
+ success: false,
48894
+ error: 'No repository specified. Provide a "repository" parameter (e.g., "owner/repo") or configure defaultRepository on the connector.'
48895
+ };
48896
+ }
48897
+ try {
48898
+ return { success: true, repo: parseRepository(repoStr) };
48899
+ } catch (err) {
48900
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
48901
+ }
48902
+ }
48903
+ var GitHubAPIError = class extends Error {
48904
+ constructor(status, statusText, body) {
48905
+ const msg = typeof body === "object" && body !== null && "message" in body ? body.message : statusText;
48906
+ super(`GitHub API error ${status}: ${msg}`);
48907
+ this.status = status;
48908
+ this.statusText = statusText;
48909
+ this.body = body;
48910
+ this.name = "GitHubAPIError";
48911
+ }
48912
+ };
48913
+ async function githubFetch(connector, endpoint, options) {
48914
+ let url2 = endpoint;
48915
+ if (options?.queryParams && Object.keys(options.queryParams).length > 0) {
48916
+ const params = new URLSearchParams();
48917
+ for (const [key, value] of Object.entries(options.queryParams)) {
48918
+ params.append(key, String(value));
48919
+ }
48920
+ url2 += (url2.includes("?") ? "&" : "?") + params.toString();
48921
+ }
48922
+ const headers = {
48923
+ "Accept": options?.accept ?? "application/vnd.github+json",
48924
+ "X-GitHub-Api-Version": "2022-11-28"
48925
+ };
48926
+ if (options?.body) {
48927
+ headers["Content-Type"] = "application/json";
48928
+ }
48929
+ const response = await connector.fetch(
48930
+ url2,
48931
+ {
48932
+ method: options?.method ?? "GET",
48933
+ headers,
48934
+ body: options?.body ? JSON.stringify(options.body) : void 0
48935
+ },
48936
+ options?.userId
48937
+ );
48938
+ const text = await response.text();
48939
+ let data;
48940
+ try {
48941
+ data = JSON.parse(text);
48942
+ } catch {
48943
+ data = text;
48944
+ }
48945
+ if (!response.ok) {
48946
+ throw new GitHubAPIError(response.status, response.statusText, data);
48947
+ }
48948
+ return data;
48949
+ }
48950
+
48951
+ // src/tools/github/searchFiles.ts
48952
+ function matchGlobPattern2(pattern, filePath) {
48953
+ let regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, ".").replace(/\{\{GLOBSTAR\}\}/g, ".*");
48954
+ regexPattern = "^" + regexPattern + "$";
48955
+ try {
48956
+ const regex = new RegExp(regexPattern);
48957
+ return regex.test(filePath);
48958
+ } catch {
48959
+ return false;
48960
+ }
48961
+ }
48962
+ function createSearchFilesTool(connector, userId) {
48963
+ return {
48964
+ definition: {
48965
+ type: "function",
48966
+ function: {
48967
+ name: "search_files",
48968
+ description: `Search for files by name/path pattern in a GitHub repository.
48969
+
48970
+ USAGE:
48971
+ - Supports glob patterns like "**/*.ts", "src/**/*.tsx"
48972
+ - Returns matching file paths sorted alphabetically
48973
+ - Uses the repository's file tree for fast matching
48974
+
48975
+ PATTERN SYNTAX:
48976
+ - * matches any characters except /
48977
+ - ** matches any characters including /
48978
+ - ? matches a single character
48979
+
48980
+ EXAMPLES:
48981
+ - Find all TypeScript files: { "pattern": "**/*.ts" }
48982
+ - Find files in src: { "pattern": "src/**/*.{ts,tsx}" }
48983
+ - Find package.json: { "pattern": "**/package.json" }
48984
+ - Search specific branch: { "pattern": "**/*.ts", "ref": "develop" }`,
48985
+ parameters: {
48986
+ type: "object",
48987
+ properties: {
48988
+ repository: {
48989
+ type: "string",
48990
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
48991
+ },
48992
+ pattern: {
48993
+ type: "string",
48994
+ description: 'Glob pattern to match files (e.g., "**/*.ts", "src/**/*.tsx")'
48995
+ },
48996
+ ref: {
48997
+ type: "string",
48998
+ description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
48999
+ }
49000
+ },
49001
+ required: ["pattern"]
49002
+ }
49003
+ }
49004
+ },
49005
+ describeCall: (args) => {
49006
+ const parts = [args.pattern];
49007
+ if (args.repository) parts.push(`in ${args.repository}`);
49008
+ if (args.ref) parts.push(`@${args.ref}`);
49009
+ return parts.join(" ");
49010
+ },
49011
+ permission: {
49012
+ scope: "session",
49013
+ riskLevel: "low",
49014
+ approvalMessage: `Search files in a GitHub repository via ${connector.displayName}`
49015
+ },
49016
+ execute: async (args) => {
49017
+ const resolved = resolveRepository(args.repository, connector);
49018
+ if (!resolved.success) {
49019
+ return { success: false, error: resolved.error };
49020
+ }
49021
+ const { owner, repo } = resolved.repo;
49022
+ try {
49023
+ let ref = args.ref;
49024
+ if (!ref) {
49025
+ const repoInfo = await githubFetch(
49026
+ connector,
49027
+ `/repos/${owner}/${repo}`,
49028
+ { userId }
49029
+ );
49030
+ ref = repoInfo.default_branch;
49031
+ }
49032
+ const tree = await githubFetch(
49033
+ connector,
49034
+ `/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`,
49035
+ { userId }
49036
+ );
49037
+ const matching = tree.tree.filter(
49038
+ (entry) => entry.type === "blob" && matchGlobPattern2(args.pattern, entry.path)
49039
+ ).map((entry) => ({
49040
+ path: entry.path,
49041
+ size: entry.size ?? 0,
49042
+ type: entry.type
49043
+ })).sort((a, b) => a.path.localeCompare(b.path));
49044
+ return {
49045
+ success: true,
49046
+ files: matching,
49047
+ count: matching.length,
49048
+ truncated: tree.truncated
49049
+ };
49050
+ } catch (error) {
49051
+ return {
49052
+ success: false,
49053
+ error: `Failed to search files: ${error instanceof Error ? error.message : String(error)}`
49054
+ };
49055
+ }
49056
+ }
49057
+ };
49058
+ }
49059
+
49060
+ // src/tools/github/searchCode.ts
49061
+ function createSearchCodeTool(connector, userId) {
49062
+ return {
49063
+ definition: {
49064
+ type: "function",
49065
+ function: {
49066
+ name: "search_code",
49067
+ description: `Search for code content across a GitHub repository.
49068
+
49069
+ USAGE:
49070
+ - Search by keyword, function name, class name, or any text
49071
+ - Filter by language, path, or file extension
49072
+ - Returns matching files with text fragments showing context
49073
+
49074
+ RATE LIMITS:
49075
+ - GitHub's code search API is limited to 30 requests per minute
49076
+ - Results may be incomplete for very large repositories
49077
+
49078
+ EXAMPLES:
49079
+ - Find function: { "query": "function handleAuth", "language": "typescript" }
49080
+ - Find imports: { "query": "import React", "extension": "tsx" }
49081
+ - Search in path: { "query": "TODO", "path": "src/utils" }
49082
+ - Limit results: { "query": "console.log", "limit": 10 }`,
49083
+ parameters: {
49084
+ type: "object",
49085
+ properties: {
49086
+ repository: {
49087
+ type: "string",
49088
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49089
+ },
49090
+ query: {
49091
+ type: "string",
49092
+ description: "Search query \u2014 keyword, function name, or any text to find in code"
49093
+ },
49094
+ language: {
49095
+ type: "string",
49096
+ description: 'Filter by programming language (e.g., "typescript", "python", "go")'
49097
+ },
49098
+ path: {
49099
+ type: "string",
49100
+ description: 'Filter by file path prefix (e.g., "src/", "lib/utils")'
49101
+ },
49102
+ extension: {
49103
+ type: "string",
49104
+ description: 'Filter by file extension without dot (e.g., "ts", "py", "go")'
49105
+ },
49106
+ limit: {
49107
+ type: "number",
49108
+ description: "Maximum number of results (default: 30, max: 100)"
49109
+ }
49110
+ },
49111
+ required: ["query"]
49112
+ }
49113
+ }
49114
+ },
49115
+ describeCall: (args) => {
49116
+ const parts = [`"${args.query}"`];
49117
+ if (args.language) parts.push(`lang:${args.language}`);
49118
+ if (args.repository) parts.push(`in ${args.repository}`);
49119
+ return parts.join(" ");
49120
+ },
49121
+ permission: {
49122
+ scope: "session",
49123
+ riskLevel: "low",
49124
+ approvalMessage: `Search code in a GitHub repository via ${connector.displayName}`
49125
+ },
49126
+ execute: async (args) => {
49127
+ const resolved = resolveRepository(args.repository, connector);
49128
+ if (!resolved.success) {
49129
+ return { success: false, error: resolved.error };
49130
+ }
49131
+ const { owner, repo } = resolved.repo;
49132
+ try {
49133
+ const qualifiers = [`repo:${owner}/${repo}`];
49134
+ if (args.language) qualifiers.push(`language:${args.language}`);
49135
+ if (args.path) qualifiers.push(`path:${args.path}`);
49136
+ if (args.extension) qualifiers.push(`extension:${args.extension}`);
49137
+ const q = `${args.query} ${qualifiers.join(" ")}`;
49138
+ const perPage = Math.min(args.limit ?? 30, 100);
49139
+ const result = await githubFetch(
49140
+ connector,
49141
+ `/search/code`,
49142
+ {
49143
+ userId,
49144
+ // Request text-match fragments
49145
+ accept: "application/vnd.github.text-match+json",
49146
+ queryParams: { q, per_page: perPage }
49147
+ }
49148
+ );
49149
+ const matches = result.items.map((item) => ({
49150
+ file: item.path,
49151
+ fragment: item.text_matches?.[0]?.fragment
49152
+ }));
49153
+ return {
49154
+ success: true,
49155
+ matches,
49156
+ count: result.total_count,
49157
+ truncated: result.incomplete_results || result.total_count > perPage
49158
+ };
49159
+ } catch (error) {
49160
+ return {
49161
+ success: false,
49162
+ error: `Failed to search code: ${error instanceof Error ? error.message : String(error)}`
49163
+ };
49164
+ }
49165
+ }
49166
+ };
49167
+ }
49168
+
49169
+ // src/tools/github/readFile.ts
49170
+ function createGitHubReadFileTool(connector, userId) {
49171
+ return {
49172
+ definition: {
49173
+ type: "function",
49174
+ function: {
49175
+ name: "read_file",
49176
+ description: `Read file content from a GitHub repository.
49177
+
49178
+ USAGE:
49179
+ - Reads a file and returns content with line numbers
49180
+ - Supports line range selection with offset/limit for large files
49181
+ - By default reads up to 2000 lines from the beginning
49182
+
49183
+ EXAMPLES:
49184
+ - Read entire file: { "path": "src/index.ts" }
49185
+ - Read specific branch: { "path": "README.md", "ref": "develop" }
49186
+ - Read lines 100-200: { "path": "src/app.ts", "offset": 100, "limit": 100 }
49187
+ - Specific repo: { "repository": "owner/repo", "path": "package.json" }
49188
+
49189
+ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (>5MB) may be truncated.`,
49190
+ parameters: {
49191
+ type: "object",
49192
+ properties: {
49193
+ repository: {
49194
+ type: "string",
49195
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49196
+ },
49197
+ path: {
49198
+ type: "string",
49199
+ description: 'File path within the repository (e.g., "src/index.ts")'
49200
+ },
49201
+ ref: {
49202
+ type: "string",
49203
+ description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
49204
+ },
49205
+ offset: {
49206
+ type: "number",
49207
+ description: "Line number to start reading from (1-indexed). Only provide if the file is too large."
49208
+ },
49209
+ limit: {
49210
+ type: "number",
49211
+ description: "Number of lines to read (default: 2000). Only provide if the file is too large."
49212
+ }
49213
+ },
49214
+ required: ["path"]
49215
+ }
49216
+ }
49217
+ },
49218
+ describeCall: (args) => {
49219
+ const parts = [args.path];
49220
+ if (args.repository) parts.push(`in ${args.repository}`);
49221
+ if (args.ref) parts.push(`@${args.ref}`);
49222
+ if (args.offset && args.limit) parts.push(`[lines ${args.offset}-${args.offset + args.limit}]`);
49223
+ return parts.join(" ");
49224
+ },
49225
+ permission: {
49226
+ scope: "session",
49227
+ riskLevel: "low",
49228
+ approvalMessage: `Read a file from a GitHub repository via ${connector.displayName}`
49229
+ },
49230
+ execute: async (args) => {
49231
+ const resolved = resolveRepository(args.repository, connector);
49232
+ if (!resolved.success) {
49233
+ return { success: false, error: resolved.error };
49234
+ }
49235
+ const { owner, repo } = resolved.repo;
49236
+ try {
49237
+ let fileContent;
49238
+ let fileSha;
49239
+ let fileSize;
49240
+ const refParam = args.ref ? `?ref=${encodeURIComponent(args.ref)}` : "";
49241
+ const contentResp = await githubFetch(
49242
+ connector,
49243
+ `/repos/${owner}/${repo}/contents/${args.path}${refParam}`,
49244
+ { userId }
49245
+ );
49246
+ if (contentResp.type !== "file") {
49247
+ return {
49248
+ success: false,
49249
+ error: `Path is not a file: ${args.path} (type: ${contentResp.type}). Use search_files to explore the repository.`,
49250
+ path: args.path
49251
+ };
49252
+ }
49253
+ fileSha = contentResp.sha;
49254
+ fileSize = contentResp.size;
49255
+ if (contentResp.content && contentResp.encoding === "base64") {
49256
+ fileContent = Buffer.from(contentResp.content, "base64").toString("utf-8");
49257
+ } else if (contentResp.git_url) {
49258
+ const blob = await githubFetch(
49259
+ connector,
49260
+ contentResp.git_url,
49261
+ { userId }
49262
+ );
49263
+ fileContent = Buffer.from(blob.content, "base64").toString("utf-8");
49264
+ fileSize = blob.size;
49265
+ } else {
49266
+ return {
49267
+ success: false,
49268
+ error: `Cannot read file content: ${args.path} (no content or git_url in response)`,
49269
+ path: args.path
49270
+ };
49271
+ }
49272
+ const offset = args.offset ?? 1;
49273
+ const limit = args.limit ?? 2e3;
49274
+ const allLines = fileContent.split("\n");
49275
+ const totalLines = allLines.length;
49276
+ const startIndex = Math.max(0, offset - 1);
49277
+ const endIndex = Math.min(totalLines, startIndex + limit);
49278
+ const selectedLines = allLines.slice(startIndex, endIndex);
49279
+ const lineNumberWidth = String(endIndex).length;
49280
+ const formattedLines = selectedLines.map((line, i) => {
49281
+ const lineNum = startIndex + i + 1;
49282
+ const paddedNum = String(lineNum).padStart(lineNumberWidth, " ");
49283
+ const truncatedLine = line.length > 2e3 ? line.substring(0, 2e3) + "..." : line;
49284
+ return `${paddedNum} ${truncatedLine}`;
49285
+ });
49286
+ const truncated = endIndex < totalLines;
49287
+ const result = formattedLines.join("\n");
49288
+ return {
49289
+ success: true,
49290
+ content: result,
49291
+ path: args.path,
49292
+ size: fileSize,
49293
+ lines: totalLines,
49294
+ truncated,
49295
+ sha: fileSha
49296
+ };
49297
+ } catch (error) {
49298
+ return {
49299
+ success: false,
49300
+ error: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
49301
+ path: args.path
49302
+ };
49303
+ }
49304
+ }
49305
+ };
49306
+ }
49307
+
49308
+ // src/tools/github/getPR.ts
49309
+ function createGetPRTool(connector, userId) {
49310
+ return {
49311
+ definition: {
49312
+ type: "function",
49313
+ function: {
49314
+ name: "get_pr",
49315
+ description: `Get full details of a pull request from a GitHub repository.
49316
+
49317
+ Returns: title, description, state, author, labels, reviewers, merge status, branches, file stats, and more.
49318
+
49319
+ EXAMPLES:
49320
+ - Get PR: { "pull_number": 123 }
49321
+ - Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
49322
+ parameters: {
49323
+ type: "object",
49324
+ properties: {
49325
+ repository: {
49326
+ type: "string",
49327
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49328
+ },
49329
+ pull_number: {
49330
+ type: "number",
49331
+ description: "Pull request number"
49332
+ }
49333
+ },
49334
+ required: ["pull_number"]
49335
+ }
49336
+ }
49337
+ },
49338
+ describeCall: (args) => {
49339
+ const parts = [`#${args.pull_number}`];
49340
+ if (args.repository) parts.push(`in ${args.repository}`);
49341
+ return parts.join(" ");
49342
+ },
49343
+ permission: {
49344
+ scope: "session",
49345
+ riskLevel: "low",
49346
+ approvalMessage: `Get pull request details from GitHub via ${connector.displayName}`
49347
+ },
49348
+ execute: async (args) => {
49349
+ const resolved = resolveRepository(args.repository, connector);
49350
+ if (!resolved.success) {
49351
+ return { success: false, error: resolved.error };
49352
+ }
49353
+ const { owner, repo } = resolved.repo;
49354
+ try {
49355
+ const pr = await githubFetch(
49356
+ connector,
49357
+ `/repos/${owner}/${repo}/pulls/${args.pull_number}`,
49358
+ { userId }
49359
+ );
49360
+ return {
49361
+ success: true,
49362
+ data: {
49363
+ number: pr.number,
49364
+ title: pr.title,
49365
+ body: pr.body,
49366
+ state: pr.state,
49367
+ draft: pr.draft,
49368
+ author: pr.user.login,
49369
+ labels: pr.labels.map((l) => l.name),
49370
+ reviewers: pr.requested_reviewers.map((r) => r.login),
49371
+ mergeable: pr.mergeable,
49372
+ head: pr.head.ref,
49373
+ base: pr.base.ref,
49374
+ url: pr.html_url,
49375
+ created_at: pr.created_at,
49376
+ updated_at: pr.updated_at,
49377
+ additions: pr.additions,
49378
+ deletions: pr.deletions,
49379
+ changed_files: pr.changed_files
49380
+ }
49381
+ };
49382
+ } catch (error) {
49383
+ return {
49384
+ success: false,
49385
+ error: `Failed to get PR: ${error instanceof Error ? error.message : String(error)}`
49386
+ };
49387
+ }
49388
+ }
49389
+ };
49390
+ }
49391
+
49392
+ // src/tools/github/prFiles.ts
49393
+ function createPRFilesTool(connector, userId) {
49394
+ return {
49395
+ definition: {
49396
+ type: "function",
49397
+ function: {
49398
+ name: "pr_files",
49399
+ description: `Get the files changed in a pull request with diffs.
49400
+
49401
+ Returns: filename, status (added/modified/removed/renamed), additions, deletions, and patch (diff) content for each file.
49402
+
49403
+ EXAMPLES:
49404
+ - Get files: { "pull_number": 123 }
49405
+ - Specific repo: { "repository": "owner/repo", "pull_number": 456 }
49406
+
49407
+ NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent for binary files.`,
49408
+ parameters: {
49409
+ type: "object",
49410
+ properties: {
49411
+ repository: {
49412
+ type: "string",
49413
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49414
+ },
49415
+ pull_number: {
49416
+ type: "number",
49417
+ description: "Pull request number"
49418
+ }
49419
+ },
49420
+ required: ["pull_number"]
49421
+ }
49422
+ }
49423
+ },
49424
+ describeCall: (args) => {
49425
+ const parts = [`files for #${args.pull_number}`];
49426
+ if (args.repository) parts.push(`in ${args.repository}`);
49427
+ return parts.join(" ");
49428
+ },
49429
+ permission: {
49430
+ scope: "session",
49431
+ riskLevel: "low",
49432
+ approvalMessage: `Get PR changed files from GitHub via ${connector.displayName}`
49433
+ },
49434
+ execute: async (args) => {
49435
+ const resolved = resolveRepository(args.repository, connector);
49436
+ if (!resolved.success) {
49437
+ return { success: false, error: resolved.error };
49438
+ }
49439
+ const { owner, repo } = resolved.repo;
49440
+ try {
49441
+ const files = await githubFetch(
49442
+ connector,
49443
+ `/repos/${owner}/${repo}/pulls/${args.pull_number}/files`,
49444
+ {
49445
+ userId,
49446
+ queryParams: { per_page: 100 }
49447
+ }
49448
+ );
49449
+ return {
49450
+ success: true,
49451
+ files: files.map((f) => ({
49452
+ filename: f.filename,
49453
+ status: f.status,
49454
+ additions: f.additions,
49455
+ deletions: f.deletions,
49456
+ changes: f.changes,
49457
+ patch: f.patch
49458
+ })),
49459
+ count: files.length
49460
+ };
49461
+ } catch (error) {
49462
+ return {
49463
+ success: false,
49464
+ error: `Failed to get PR files: ${error instanceof Error ? error.message : String(error)}`
49465
+ };
49466
+ }
49467
+ }
49468
+ };
49469
+ }
49470
+
49471
+ // src/tools/github/prComments.ts
49472
+ function createPRCommentsTool(connector, userId) {
49473
+ return {
49474
+ definition: {
49475
+ type: "function",
49476
+ function: {
49477
+ name: "pr_comments",
49478
+ description: `Get all comments and reviews on a pull request.
49479
+
49480
+ Returns a unified list of:
49481
+ - **review_comment**: Line-level comments on specific code (includes file path and line number)
49482
+ - **review**: Full reviews (approve/request changes/comment)
49483
+ - **comment**: General comments on the PR (issue-level)
49484
+
49485
+ All entries are sorted by creation date (oldest first).
49486
+
49487
+ EXAMPLES:
49488
+ - Get comments: { "pull_number": 123 }
49489
+ - Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
49490
+ parameters: {
49491
+ type: "object",
49492
+ properties: {
49493
+ repository: {
49494
+ type: "string",
49495
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49496
+ },
49497
+ pull_number: {
49498
+ type: "number",
49499
+ description: "Pull request number"
49500
+ }
49501
+ },
49502
+ required: ["pull_number"]
49503
+ }
49504
+ }
49505
+ },
49506
+ describeCall: (args) => {
49507
+ const parts = [`comments for #${args.pull_number}`];
49508
+ if (args.repository) parts.push(`in ${args.repository}`);
49509
+ return parts.join(" ");
49510
+ },
49511
+ permission: {
49512
+ scope: "session",
49513
+ riskLevel: "low",
49514
+ approvalMessage: `Get PR comments and reviews from GitHub via ${connector.displayName}`
49515
+ },
49516
+ execute: async (args) => {
49517
+ const resolved = resolveRepository(args.repository, connector);
49518
+ if (!resolved.success) {
49519
+ return { success: false, error: resolved.error };
49520
+ }
49521
+ const { owner, repo } = resolved.repo;
49522
+ try {
49523
+ const basePath = `/repos/${owner}/${repo}`;
49524
+ const queryOpts = { userId, queryParams: { per_page: 100 } };
49525
+ const [reviewComments, reviews, issueComments] = await Promise.all([
49526
+ githubFetch(
49527
+ connector,
49528
+ `${basePath}/pulls/${args.pull_number}/comments`,
49529
+ queryOpts
49530
+ ),
49531
+ githubFetch(
49532
+ connector,
49533
+ `${basePath}/pulls/${args.pull_number}/reviews`,
49534
+ queryOpts
49535
+ ),
49536
+ githubFetch(
49537
+ connector,
49538
+ `${basePath}/issues/${args.pull_number}/comments`,
49539
+ queryOpts
49540
+ )
49541
+ ]);
49542
+ const allComments = [];
49543
+ for (const rc of reviewComments) {
49544
+ allComments.push({
49545
+ id: rc.id,
49546
+ type: "review_comment",
49547
+ author: rc.user.login,
49548
+ body: rc.body,
49549
+ created_at: rc.created_at,
49550
+ path: rc.path,
49551
+ line: rc.line ?? rc.original_line ?? void 0
49552
+ });
49553
+ }
49554
+ for (const r of reviews) {
49555
+ if (!r.body && r.state === "APPROVED") continue;
49556
+ allComments.push({
49557
+ id: r.id,
49558
+ type: "review",
49559
+ author: r.user.login,
49560
+ body: r.body || `[${r.state}]`,
49561
+ created_at: r.submitted_at,
49562
+ state: r.state
49563
+ });
49564
+ }
49565
+ for (const ic of issueComments) {
49566
+ allComments.push({
49567
+ id: ic.id,
49568
+ type: "comment",
49569
+ author: ic.user.login,
49570
+ body: ic.body,
49571
+ created_at: ic.created_at
49572
+ });
49573
+ }
49574
+ allComments.sort(
49575
+ (a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
49576
+ );
49577
+ return {
49578
+ success: true,
49579
+ comments: allComments,
49580
+ count: allComments.length
49581
+ };
49582
+ } catch (error) {
49583
+ return {
49584
+ success: false,
49585
+ error: `Failed to get PR comments: ${error instanceof Error ? error.message : String(error)}`
49586
+ };
49587
+ }
49588
+ }
49589
+ };
49590
+ }
49591
+
49592
+ // src/tools/github/createPR.ts
49593
+ function createCreatePRTool(connector, userId) {
49594
+ return {
49595
+ definition: {
49596
+ type: "function",
49597
+ function: {
49598
+ name: "create_pr",
49599
+ description: `Create a pull request on a GitHub repository.
49600
+
49601
+ USAGE:
49602
+ - Specify source branch (head) and target branch (base)
49603
+ - Optionally create as draft
49604
+
49605
+ EXAMPLES:
49606
+ - Create PR: { "title": "Add feature", "head": "feature-branch", "base": "main" }
49607
+ - Draft PR: { "title": "WIP: Refactor", "head": "refactor", "base": "develop", "draft": true }
49608
+ - With body: { "title": "Fix bug #42", "body": "Fixes the login issue\\n\\n## Changes\\n- Fixed auth flow", "head": "fix/42", "base": "main" }`,
49609
+ parameters: {
49610
+ type: "object",
49611
+ properties: {
49612
+ repository: {
49613
+ type: "string",
49614
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49615
+ },
49616
+ title: {
49617
+ type: "string",
49618
+ description: "Pull request title"
49619
+ },
49620
+ body: {
49621
+ type: "string",
49622
+ description: "Pull request description/body (Markdown supported)"
49623
+ },
49624
+ head: {
49625
+ type: "string",
49626
+ description: "Source branch name (the branch with your changes)"
49627
+ },
49628
+ base: {
49629
+ type: "string",
49630
+ description: 'Target branch name (the branch you want to merge into, e.g., "main")'
49631
+ },
49632
+ draft: {
49633
+ type: "boolean",
49634
+ description: "Create as a draft pull request (default: false)"
49635
+ }
49636
+ },
49637
+ required: ["title", "head", "base"]
49638
+ }
49639
+ }
49640
+ },
49641
+ describeCall: (args) => {
49642
+ const parts = [args.title];
49643
+ if (args.repository) parts.push(`in ${args.repository}`);
49644
+ return parts.join(" ");
49645
+ },
49646
+ permission: {
49647
+ scope: "session",
49648
+ riskLevel: "medium",
49649
+ approvalMessage: `Create a pull request on GitHub via ${connector.displayName}`
49650
+ },
49651
+ execute: async (args) => {
49652
+ const resolved = resolveRepository(args.repository, connector);
49653
+ if (!resolved.success) {
49654
+ return { success: false, error: resolved.error };
49655
+ }
49656
+ const { owner, repo } = resolved.repo;
49657
+ try {
49658
+ const pr = await githubFetch(
49659
+ connector,
49660
+ `/repos/${owner}/${repo}/pulls`,
49661
+ {
49662
+ method: "POST",
49663
+ userId,
49664
+ body: {
49665
+ title: args.title,
49666
+ body: args.body,
49667
+ head: args.head,
49668
+ base: args.base,
49669
+ draft: args.draft ?? false
49670
+ }
49671
+ }
49672
+ );
49673
+ return {
49674
+ success: true,
49675
+ data: {
49676
+ number: pr.number,
49677
+ url: pr.html_url,
49678
+ state: pr.state,
49679
+ title: pr.title
49680
+ }
49681
+ };
49682
+ } catch (error) {
49683
+ return {
49684
+ success: false,
49685
+ error: `Failed to create PR: ${error instanceof Error ? error.message : String(error)}`
49686
+ };
49687
+ }
49688
+ }
49689
+ };
49690
+ }
49691
+
49692
+ // src/tools/github/register.ts
49693
+ function registerGitHubTools() {
49694
+ ConnectorTools.registerService("github", (connector, userId) => {
49695
+ return [
49696
+ createSearchFilesTool(connector, userId),
49697
+ createSearchCodeTool(connector, userId),
49698
+ createGitHubReadFileTool(connector, userId),
49699
+ createGetPRTool(connector, userId),
49700
+ createPRFilesTool(connector, userId),
49701
+ createPRCommentsTool(connector, userId),
49702
+ createCreatePRTool(connector, userId)
49703
+ ];
49704
+ });
49705
+ }
49706
+
49707
+ // src/tools/github/index.ts
49708
+ registerGitHubTools();
49709
+
48640
49710
  // src/tools/registry.generated.ts
48641
49711
  var toolRegistry = [
48642
49712
  {
@@ -48690,7 +49760,7 @@ var toolRegistry = [
48690
49760
  displayName: "Read File",
48691
49761
  category: "filesystem",
48692
49762
  description: "Read content from a file on the local filesystem.",
48693
- tool: readFile4,
49763
+ tool: readFile5,
48694
49764
  safeByDefault: true
48695
49765
  },
48696
49766
  {
@@ -48699,7 +49769,7 @@ var toolRegistry = [
48699
49769
  displayName: "Write File",
48700
49770
  category: "filesystem",
48701
49771
  description: "Write content to a file on the local filesystem.",
48702
- tool: writeFile4,
49772
+ tool: writeFile5,
48703
49773
  safeByDefault: false
48704
49774
  },
48705
49775
  {
@@ -48928,8 +49998,8 @@ var ToolRegistry = class {
48928
49998
 
48929
49999
  // src/tools/index.ts
48930
50000
  var developerTools = [
48931
- readFile4,
48932
- writeFile4,
50001
+ readFile5,
50002
+ writeFile5,
48933
50003
  editFile,
48934
50004
  glob,
48935
50005
  grep,
@@ -49153,7 +50223,8 @@ exports.ExternalDependencyHandler = ExternalDependencyHandler;
49153
50223
  exports.FileAgentDefinitionStorage = FileAgentDefinitionStorage;
49154
50224
  exports.FileConnectorStorage = FileConnectorStorage;
49155
50225
  exports.FileContextStorage = FileContextStorage;
49156
- exports.FileMediaOutputHandler = FileMediaOutputHandler;
50226
+ exports.FileMediaOutputHandler = FileMediaStorage;
50227
+ exports.FileMediaStorage = FileMediaStorage;
49157
50228
  exports.FilePersistentInstructionsStorage = FilePersistentInstructionsStorage;
49158
50229
  exports.FileStorage = FileStorage;
49159
50230
  exports.HookManager = HookManager;
@@ -49259,11 +50330,15 @@ exports.createAgentStorage = createAgentStorage;
49259
50330
  exports.createAuthenticatedFetch = createAuthenticatedFetch;
49260
50331
  exports.createBashTool = createBashTool;
49261
50332
  exports.createConnectorFromTemplate = createConnectorFromTemplate;
50333
+ exports.createCreatePRTool = createCreatePRTool;
49262
50334
  exports.createEditFileTool = createEditFileTool;
49263
50335
  exports.createEstimator = createEstimator;
49264
50336
  exports.createExecuteJavaScriptTool = createExecuteJavaScriptTool;
49265
50337
  exports.createFileAgentDefinitionStorage = createFileAgentDefinitionStorage;
49266
50338
  exports.createFileContextStorage = createFileContextStorage;
50339
+ exports.createFileMediaStorage = createFileMediaStorage;
50340
+ exports.createGetPRTool = createGetPRTool;
50341
+ exports.createGitHubReadFileTool = createGitHubReadFileTool;
49267
50342
  exports.createGlobTool = createGlobTool;
49268
50343
  exports.createGrepTool = createGrepTool;
49269
50344
  exports.createImageGenerationTool = createImageGenerationTool;
@@ -49271,9 +50346,13 @@ exports.createImageProvider = createImageProvider;
49271
50346
  exports.createListDirectoryTool = createListDirectoryTool;
49272
50347
  exports.createMessageWithImages = createMessageWithImages;
49273
50348
  exports.createMetricsCollector = createMetricsCollector;
50349
+ exports.createPRCommentsTool = createPRCommentsTool;
50350
+ exports.createPRFilesTool = createPRFilesTool;
49274
50351
  exports.createPlan = createPlan;
49275
50352
  exports.createProvider = createProvider;
49276
50353
  exports.createReadFileTool = createReadFileTool;
50354
+ exports.createSearchCodeTool = createSearchCodeTool;
50355
+ exports.createSearchFilesTool = createSearchFilesTool;
49277
50356
  exports.createSpeechToTextTool = createSpeechToTextTool;
49278
50357
  exports.createTask = createTask;
49279
50358
  exports.createTextMessage = createTextMessage;
@@ -49313,6 +50392,7 @@ exports.getImageModelInfo = getImageModelInfo;
49313
50392
  exports.getImageModelsByVendor = getImageModelsByVendor;
49314
50393
  exports.getImageModelsWithFeature = getImageModelsWithFeature;
49315
50394
  exports.getMediaOutputHandler = getMediaOutputHandler;
50395
+ exports.getMediaStorage = getMediaStorage;
49316
50396
  exports.getModelInfo = getModelInfo;
49317
50397
  exports.getModelsByVendor = getModelsByVendor;
49318
50398
  exports.getNextExecutableTasks = getNextExecutableTasks;
@@ -49335,6 +50415,7 @@ exports.getToolsByCategory = getToolsByCategory;
49335
50415
  exports.getToolsRequiringConnector = getToolsRequiringConnector;
49336
50416
  exports.getVendorAuthTemplate = getVendorAuthTemplate;
49337
50417
  exports.getVendorColor = getVendorColor;
50418
+ exports.getVendorDefaultBaseURL = getVendorDefaultBaseURL;
49338
50419
  exports.getVendorInfo = getVendorInfo;
49339
50420
  exports.getVendorLogo = getVendorLogo;
49340
50421
  exports.getVendorLogoCdnUrl = getVendorLogoCdnUrl;
@@ -49373,15 +50454,18 @@ exports.listVendors = listVendors;
49373
50454
  exports.listVendorsByAuthType = listVendorsByAuthType;
49374
50455
  exports.listVendorsByCategory = listVendorsByCategory;
49375
50456
  exports.listVendorsWithLogos = listVendorsWithLogos;
50457
+ exports.parseRepository = parseRepository;
49376
50458
  exports.readClipboardImage = readClipboardImage;
49377
- exports.readFile = readFile4;
50459
+ exports.readFile = readFile5;
49378
50460
  exports.registerScrapeProvider = registerScrapeProvider;
49379
50461
  exports.resolveConnector = resolveConnector;
49380
50462
  exports.resolveDependencies = resolveDependencies;
50463
+ exports.resolveRepository = resolveRepository;
49381
50464
  exports.retryWithBackoff = retryWithBackoff;
49382
50465
  exports.scopeEquals = scopeEquals;
49383
50466
  exports.scopeMatches = scopeMatches;
49384
50467
  exports.setMediaOutputHandler = setMediaOutputHandler;
50468
+ exports.setMediaStorage = setMediaStorage;
49385
50469
  exports.setMetricsCollector = setMetricsCollector;
49386
50470
  exports.simpleTokenEstimator = simpleTokenEstimator;
49387
50471
  exports.toConnectorOptions = toConnectorOptions;
@@ -49389,6 +50473,6 @@ exports.toolRegistry = toolRegistry;
49389
50473
  exports.tools = tools_exports;
49390
50474
  exports.updateTaskStatus = updateTaskStatus;
49391
50475
  exports.validatePath = validatePath;
49392
- exports.writeFile = writeFile4;
50476
+ exports.writeFile = writeFile5;
49393
50477
  //# sourceMappingURL=index.cjs.map
49394
50478
  //# sourceMappingURL=index.cjs.map