@everworker/oneringai 0.1.2 → 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.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import * as crypto2 from 'crypto';
2
2
  import { randomUUID } from 'crypto';
3
3
  import { importPKCS8, SignJWT } from 'jose';
4
- import * as fs15 from 'fs';
4
+ import * as fs16 from 'fs';
5
5
  import { promises, existsSync } from 'fs';
6
6
  import { EventEmitter } from 'eventemitter3';
7
- import * as path3 from 'path';
7
+ import * as path2 from 'path';
8
8
  import { join, resolve, dirname, relative, isAbsolute, normalize, extname } from 'path';
9
- import * as os from 'os';
9
+ import * as os2 from 'os';
10
10
  import { homedir } from 'os';
11
- import OpenAI2 from 'openai';
11
+ import OpenAI3 from 'openai';
12
12
  import Anthropic from '@anthropic-ai/sdk';
13
13
  import { GoogleGenAI } from '@google/genai';
14
14
  import 'zod/v3';
@@ -16,7 +16,7 @@ import * as z4mini from 'zod/v4-mini';
16
16
  import * as z from 'zod/v4';
17
17
  import process2 from 'process';
18
18
  import { PassThrough } from 'stream';
19
- import * as fs14 from 'fs/promises';
19
+ import * as fs15 from 'fs/promises';
20
20
  import { stat, readFile, mkdir, writeFile, readdir } from 'fs/promises';
21
21
  import * as simpleIcons from 'simple-icons';
22
22
  import { exec, spawn } from 'child_process';
@@ -600,7 +600,7 @@ var init_JWTBearer = __esm({
600
600
  this.privateKey = config.privateKey;
601
601
  } else if (config.privateKeyPath) {
602
602
  try {
603
- this.privateKey = fs15.readFileSync(config.privateKeyPath, "utf8");
603
+ this.privateKey = fs16.readFileSync(config.privateKeyPath, "utf8");
604
604
  } catch (error) {
605
605
  throw new Error(`Failed to read private key from ${config.privateKeyPath}: ${error.message}`);
606
606
  }
@@ -1250,11 +1250,11 @@ var init_Logger = __esm({
1250
1250
  */
1251
1251
  initFileStream(filePath) {
1252
1252
  try {
1253
- const dir = path3.dirname(filePath);
1254
- if (!fs15.existsSync(dir)) {
1255
- fs15.mkdirSync(dir, { recursive: true });
1253
+ const dir = path2.dirname(filePath);
1254
+ if (!fs16.existsSync(dir)) {
1255
+ fs16.mkdirSync(dir, { recursive: true });
1256
1256
  }
1257
- this.fileStream = fs15.createWriteStream(filePath, {
1257
+ this.fileStream = fs16.createWriteStream(filePath, {
1258
1258
  flags: "a",
1259
1259
  // append mode
1260
1260
  encoding: "utf8"
@@ -14524,12 +14524,12 @@ var require_dist = __commonJS({
14524
14524
  throw new Error(`Unknown format "${name}"`);
14525
14525
  return f;
14526
14526
  };
14527
- function addFormats(ajv, list, fs18, exportName) {
14527
+ function addFormats(ajv, list, fs17, exportName) {
14528
14528
  var _a;
14529
14529
  var _b;
14530
14530
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14531
14531
  for (const f of list)
14532
- ajv.addFormat(f, fs18[f]);
14532
+ ajv.addFormat(f, fs17[f]);
14533
14533
  }
14534
14534
  module.exports = exports$1 = formatsPlugin;
14535
14535
  Object.defineProperty(exports$1, "__esModule", { value: true });
@@ -14542,7 +14542,7 @@ var require_windows = __commonJS({
14542
14542
  "node_modules/isexe/windows.js"(exports$1, module) {
14543
14543
  module.exports = isexe;
14544
14544
  isexe.sync = sync;
14545
- var fs18 = __require("fs");
14545
+ var fs17 = __require("fs");
14546
14546
  function checkPathExt(path6, options) {
14547
14547
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
14548
14548
  if (!pathext) {
@@ -14560,19 +14560,19 @@ var require_windows = __commonJS({
14560
14560
  }
14561
14561
  return false;
14562
14562
  }
14563
- function checkStat(stat5, path6, options) {
14564
- if (!stat5.isSymbolicLink() && !stat5.isFile()) {
14563
+ function checkStat(stat6, path6, options) {
14564
+ if (!stat6.isSymbolicLink() && !stat6.isFile()) {
14565
14565
  return false;
14566
14566
  }
14567
14567
  return checkPathExt(path6, options);
14568
14568
  }
14569
14569
  function isexe(path6, options, cb) {
14570
- fs18.stat(path6, function(er, stat5) {
14571
- cb(er, er ? false : checkStat(stat5, path6, options));
14570
+ fs17.stat(path6, function(er, stat6) {
14571
+ cb(er, er ? false : checkStat(stat6, path6, options));
14572
14572
  });
14573
14573
  }
14574
14574
  function sync(path6, options) {
14575
- return checkStat(fs18.statSync(path6), path6, options);
14575
+ return checkStat(fs17.statSync(path6), path6, options);
14576
14576
  }
14577
14577
  }
14578
14578
  });
@@ -14582,22 +14582,22 @@ var require_mode = __commonJS({
14582
14582
  "node_modules/isexe/mode.js"(exports$1, module) {
14583
14583
  module.exports = isexe;
14584
14584
  isexe.sync = sync;
14585
- var fs18 = __require("fs");
14585
+ var fs17 = __require("fs");
14586
14586
  function isexe(path6, options, cb) {
14587
- fs18.stat(path6, function(er, stat5) {
14588
- cb(er, er ? false : checkStat(stat5, options));
14587
+ fs17.stat(path6, function(er, stat6) {
14588
+ cb(er, er ? false : checkStat(stat6, options));
14589
14589
  });
14590
14590
  }
14591
14591
  function sync(path6, options) {
14592
- return checkStat(fs18.statSync(path6), options);
14592
+ return checkStat(fs17.statSync(path6), options);
14593
14593
  }
14594
- function checkStat(stat5, options) {
14595
- return stat5.isFile() && checkMode(stat5, options);
14594
+ function checkStat(stat6, options) {
14595
+ return stat6.isFile() && checkMode(stat6, options);
14596
14596
  }
14597
- function checkMode(stat5, options) {
14598
- var mod = stat5.mode;
14599
- var uid = stat5.uid;
14600
- var gid = stat5.gid;
14597
+ function checkMode(stat6, options) {
14598
+ var mod = stat6.mode;
14599
+ var uid = stat6.uid;
14600
+ var gid = stat6.gid;
14601
14601
  var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
14602
14602
  var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
14603
14603
  var u = parseInt("100", 8);
@@ -14871,16 +14871,16 @@ var require_shebang_command = __commonJS({
14871
14871
  // node_modules/cross-spawn/lib/util/readShebang.js
14872
14872
  var require_readShebang = __commonJS({
14873
14873
  "node_modules/cross-spawn/lib/util/readShebang.js"(exports$1, module) {
14874
- var fs18 = __require("fs");
14874
+ var fs17 = __require("fs");
14875
14875
  var shebangCommand = require_shebang_command();
14876
14876
  function readShebang(command) {
14877
14877
  const size = 150;
14878
14878
  const buffer = Buffer.alloc(size);
14879
14879
  let fd;
14880
14880
  try {
14881
- fd = fs18.openSync(command, "r");
14882
- fs18.readSync(fd, buffer, 0, size, 0);
14883
- fs18.closeSync(fd);
14881
+ fd = fs17.openSync(command, "r");
14882
+ fs17.readSync(fd, buffer, 0, size, 0);
14883
+ fs17.closeSync(fd);
14884
14884
  } catch (e) {
14885
14885
  }
14886
14886
  return shebangCommand(buffer.toString());
@@ -15058,8 +15058,8 @@ var DEFAULT_ALLOWLIST = [
15058
15058
  "context_list",
15059
15059
  // Persistent instructions tools
15060
15060
  "instructions_set",
15061
- "instructions_append",
15062
- "instructions_get",
15061
+ "instructions_remove",
15062
+ "instructions_list",
15063
15063
  "instructions_clear",
15064
15064
  // Meta-tools (internal coordination)
15065
15065
  "_start_planning",
@@ -15989,13 +15989,26 @@ var ToolManager = class extends EventEmitter {
15989
15989
  pipeline;
15990
15990
  /** Optional tool context for execution (set by agent before runs) */
15991
15991
  _toolContext;
15992
- constructor() {
15992
+ /** Hard timeout for tool execution (0 = disabled) */
15993
+ _toolExecutionTimeout;
15994
+ constructor(config) {
15993
15995
  super();
15996
+ this._toolExecutionTimeout = config?.toolExecutionTimeout ?? 0;
15994
15997
  this.namespaceIndex.set("default", /* @__PURE__ */ new Set());
15995
15998
  this.toolLogger = logger.child({ component: "ToolManager" });
15996
15999
  this.pipeline = new ToolExecutionPipeline();
15997
16000
  this.pipeline.use(new ResultNormalizerPlugin());
15998
16001
  }
16002
+ /**
16003
+ * Get or set the hard tool execution timeout in milliseconds.
16004
+ * 0 = disabled (relies on tool's own timeout).
16005
+ */
16006
+ get toolExecutionTimeout() {
16007
+ return this._toolExecutionTimeout;
16008
+ }
16009
+ set toolExecutionTimeout(value) {
16010
+ this._toolExecutionTimeout = Math.max(0, value);
16011
+ }
15999
16012
  /**
16000
16013
  * Access the execution pipeline for plugin management.
16001
16014
  *
@@ -16493,7 +16506,7 @@ var ToolManager = class extends EventEmitter {
16493
16506
  const startTime = Date.now();
16494
16507
  metrics.increment("tool.executed", 1, { tool: toolName });
16495
16508
  try {
16496
- const result = await breaker.execute(async () => {
16509
+ const executionPromise = breaker.execute(async () => {
16497
16510
  const toolWithContext = {
16498
16511
  ...registration.tool,
16499
16512
  execute: async (pipelineArgs) => {
@@ -16502,6 +16515,7 @@ var ToolManager = class extends EventEmitter {
16502
16515
  };
16503
16516
  return await this.pipeline.execute(toolWithContext, args);
16504
16517
  });
16518
+ const result = this._toolExecutionTimeout > 0 ? await this.withHardTimeout(executionPromise, toolName, this._toolExecutionTimeout) : await executionPromise;
16505
16519
  const duration = Date.now() - startTime;
16506
16520
  this.recordExecution(toolName, duration, true);
16507
16521
  const resultSummary = this.summarizeResult(result);
@@ -16564,6 +16578,29 @@ var ToolManager = class extends EventEmitter {
16564
16578
  return this.list();
16565
16579
  }
16566
16580
  // ==========================================================================
16581
+ // Hard Timeout
16582
+ // ==========================================================================
16583
+ /**
16584
+ * Wrap a promise with a hard timeout safety net.
16585
+ * If the promise doesn't resolve within the timeout, throws ToolExecutionError.
16586
+ */
16587
+ async withHardTimeout(promise, toolName, timeoutMs) {
16588
+ let timeoutId;
16589
+ const timeoutPromise = new Promise((_, reject) => {
16590
+ timeoutId = setTimeout(() => {
16591
+ reject(new ToolExecutionError(
16592
+ toolName,
16593
+ `Tool execution hard timeout after ${timeoutMs}ms (safety net - tool's own timeout may have failed)`
16594
+ ));
16595
+ }, timeoutMs);
16596
+ });
16597
+ try {
16598
+ return await Promise.race([promise, timeoutPromise]);
16599
+ } finally {
16600
+ clearTimeout(timeoutId);
16601
+ }
16602
+ }
16603
+ // ==========================================================================
16567
16604
  // Circuit Breaker Management
16568
16605
  // ==========================================================================
16569
16606
  /**
@@ -19633,22 +19670,45 @@ function sanitizeAgentId(agentId) {
19633
19670
  var FilePersistentInstructionsStorage = class {
19634
19671
  directory;
19635
19672
  filePath;
19673
+ legacyFilePath;
19636
19674
  agentId;
19637
19675
  constructor(config) {
19638
19676
  this.agentId = config.agentId;
19639
19677
  const sanitizedId = sanitizeAgentId(config.agentId);
19640
19678
  const baseDir = config.baseDirectory ?? getDefaultBaseDirectory();
19641
- const filename = config.filename ?? "custom_instructions.md";
19679
+ const filename = config.filename ?? "custom_instructions.json";
19642
19680
  this.directory = join(baseDir, sanitizedId);
19643
19681
  this.filePath = join(this.directory, filename);
19682
+ this.legacyFilePath = join(this.directory, "custom_instructions.md");
19644
19683
  }
19645
19684
  /**
19646
- * Load instructions from file
19685
+ * Load instruction entries from file.
19686
+ * Falls back to legacy .md file migration if JSON not found.
19647
19687
  */
19648
19688
  async load() {
19649
19689
  try {
19650
- const content = await promises.readFile(this.filePath, "utf-8");
19651
- return content.trim() || null;
19690
+ const raw = await promises.readFile(this.filePath, "utf-8");
19691
+ const data = JSON.parse(raw);
19692
+ if (data.version === 2 && Array.isArray(data.entries)) {
19693
+ return data.entries.length > 0 ? data.entries : null;
19694
+ }
19695
+ return null;
19696
+ } catch (error) {
19697
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
19698
+ throw error;
19699
+ }
19700
+ }
19701
+ try {
19702
+ const content = await promises.readFile(this.legacyFilePath, "utf-8");
19703
+ const trimmed = content.trim();
19704
+ if (!trimmed) return null;
19705
+ const now = Date.now();
19706
+ return [{
19707
+ id: "legacy_instructions",
19708
+ content: trimmed,
19709
+ createdAt: now,
19710
+ updatedAt: now
19711
+ }];
19652
19712
  } catch (error) {
19653
19713
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
19654
19714
  return null;
@@ -19657,14 +19717,19 @@ var FilePersistentInstructionsStorage = class {
19657
19717
  }
19658
19718
  }
19659
19719
  /**
19660
- * Save instructions to file
19661
- * Creates directory if it doesn't exist
19720
+ * Save instruction entries to file as JSON.
19721
+ * Creates directory if it doesn't exist.
19722
+ * Cleans up legacy .md file if present.
19662
19723
  */
19663
- async save(content) {
19724
+ async save(entries) {
19664
19725
  await this.ensureDirectory();
19726
+ const data = {
19727
+ version: 2,
19728
+ entries
19729
+ };
19665
19730
  const tempPath = `${this.filePath}.tmp`;
19666
19731
  try {
19667
- await promises.writeFile(tempPath, content, "utf-8");
19732
+ await promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
19668
19733
  await promises.rename(tempPath, this.filePath);
19669
19734
  } catch (error) {
19670
19735
  try {
@@ -19673,9 +19738,10 @@ var FilePersistentInstructionsStorage = class {
19673
19738
  }
19674
19739
  throw error;
19675
19740
  }
19741
+ await this.removeLegacyFile();
19676
19742
  }
19677
19743
  /**
19678
- * Delete instructions file
19744
+ * Delete instructions file (and legacy .md if exists)
19679
19745
  */
19680
19746
  async delete() {
19681
19747
  try {
@@ -19685,16 +19751,22 @@ var FilePersistentInstructionsStorage = class {
19685
19751
  throw error;
19686
19752
  }
19687
19753
  }
19754
+ await this.removeLegacyFile();
19688
19755
  }
19689
19756
  /**
19690
- * Check if instructions file exists
19757
+ * Check if instructions file exists (JSON or legacy .md)
19691
19758
  */
19692
19759
  async exists() {
19693
19760
  try {
19694
19761
  await promises.access(this.filePath);
19695
19762
  return true;
19696
19763
  } catch {
19697
- return false;
19764
+ try {
19765
+ await promises.access(this.legacyFilePath);
19766
+ return true;
19767
+ } catch {
19768
+ return false;
19769
+ }
19698
19770
  }
19699
19771
  }
19700
19772
  /**
@@ -19721,58 +19793,79 @@ var FilePersistentInstructionsStorage = class {
19721
19793
  }
19722
19794
  }
19723
19795
  }
19796
+ /**
19797
+ * Remove legacy .md file if it exists
19798
+ */
19799
+ async removeLegacyFile() {
19800
+ try {
19801
+ await promises.unlink(this.legacyFilePath);
19802
+ } catch (error) {
19803
+ if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
19804
+ console.warn(`Failed to remove legacy instructions file: ${this.legacyFilePath}`);
19805
+ }
19806
+ }
19807
+ }
19724
19808
  };
19725
19809
 
19726
19810
  // src/core/context-nextgen/plugins/PersistentInstructionsPluginNextGen.ts
19727
- var DEFAULT_MAX_LENGTH = 5e4;
19811
+ var DEFAULT_MAX_TOTAL_LENGTH = 5e4;
19812
+ var DEFAULT_MAX_ENTRIES = 50;
19813
+ var KEY_MAX_LENGTH = 100;
19814
+ var KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
19728
19815
  var PERSISTENT_INSTRUCTIONS_INSTRUCTIONS = `Persistent Instructions are stored on disk and survive across sessions.
19816
+ Each instruction is a keyed entry that can be independently managed.
19729
19817
 
19730
19818
  **To modify:**
19731
- - \`instructions_set(content)\`: Replace all instructions
19732
- - \`instructions_append(section)\`: Add a section
19733
- - \`instructions_clear(confirm: true)\`: Remove all (destructive!)
19819
+ - \`instructions_set(key, content)\`: Add or update a single instruction by key
19820
+ - \`instructions_remove(key)\`: Remove a single instruction by key
19821
+ - \`instructions_list()\`: List all instructions with keys and content
19822
+ - \`instructions_clear(confirm: true)\`: Remove all instructions (destructive!)
19734
19823
 
19735
19824
  **Use for:** Agent personality, user preferences, learned rules, guidelines.`;
19736
19825
  var instructionsSetDefinition = {
19737
19826
  type: "function",
19738
19827
  function: {
19739
19828
  name: "instructions_set",
19740
- description: `Set or replace all custom instructions. Persists across sessions.
19741
- IMPORTANT: This replaces ALL existing instructions.`,
19829
+ description: `Add or update a single persistent instruction by key. Persists across sessions.
19830
+ If the key exists, it will be updated. If not, a new entry is created.`,
19742
19831
  parameters: {
19743
19832
  type: "object",
19744
19833
  properties: {
19834
+ key: {
19835
+ type: "string",
19836
+ description: "Unique key for the instruction (alphanumeric, dash, underscore; max 100 chars)"
19837
+ },
19745
19838
  content: {
19746
19839
  type: "string",
19747
- description: "Full instructions content (markdown supported)"
19840
+ description: "Instruction content (markdown supported)"
19748
19841
  }
19749
19842
  },
19750
- required: ["content"]
19843
+ required: ["key", "content"]
19751
19844
  }
19752
19845
  }
19753
19846
  };
19754
- var instructionsAppendDefinition = {
19847
+ var instructionsRemoveDefinition = {
19755
19848
  type: "function",
19756
19849
  function: {
19757
- name: "instructions_append",
19758
- description: "Append a section to existing instructions.",
19850
+ name: "instructions_remove",
19851
+ description: "Remove a single persistent instruction by key.",
19759
19852
  parameters: {
19760
19853
  type: "object",
19761
19854
  properties: {
19762
- section: {
19855
+ key: {
19763
19856
  type: "string",
19764
- description: "Section to append (will add newlines before)"
19857
+ description: "Key of the instruction to remove"
19765
19858
  }
19766
19859
  },
19767
- required: ["section"]
19860
+ required: ["key"]
19768
19861
  }
19769
19862
  }
19770
19863
  };
19771
- var instructionsGetDefinition = {
19864
+ var instructionsListDefinition = {
19772
19865
  type: "function",
19773
19866
  function: {
19774
- name: "instructions_get",
19775
- description: "Get current custom instructions.",
19867
+ name: "instructions_list",
19868
+ description: "List all persistent instructions with their keys and content.",
19776
19869
  parameters: {
19777
19870
  type: "object",
19778
19871
  properties: {},
@@ -19784,7 +19877,7 @@ var instructionsClearDefinition = {
19784
19877
  type: "function",
19785
19878
  function: {
19786
19879
  name: "instructions_clear",
19787
- description: "Clear all custom instructions (DESTRUCTIVE). Requires confirmation.",
19880
+ description: "Clear all persistent instructions (DESTRUCTIVE). Requires confirmation.",
19788
19881
  parameters: {
19789
19882
  type: "object",
19790
19883
  properties: {
@@ -19797,13 +19890,22 @@ var instructionsClearDefinition = {
19797
19890
  }
19798
19891
  }
19799
19892
  };
19893
+ function validateKey(key) {
19894
+ if (typeof key !== "string") return "Key must be a string";
19895
+ const trimmed = key.trim();
19896
+ if (trimmed.length === 0) return "Key cannot be empty";
19897
+ if (trimmed.length > KEY_MAX_LENGTH) return `Key exceeds maximum length (${KEY_MAX_LENGTH} chars)`;
19898
+ if (!KEY_PATTERN.test(trimmed)) return "Key must contain only alphanumeric characters, dashes, and underscores";
19899
+ return null;
19900
+ }
19800
19901
  var PersistentInstructionsPluginNextGen = class {
19801
19902
  name = "persistent_instructions";
19802
- _content = null;
19903
+ _entries = /* @__PURE__ */ new Map();
19803
19904
  _initialized = false;
19804
19905
  _destroyed = false;
19805
19906
  storage;
19806
- maxLength;
19907
+ maxTotalLength;
19908
+ maxEntries;
19807
19909
  agentId;
19808
19910
  estimator = simpleTokenEstimator;
19809
19911
  _tokenCache = null;
@@ -19813,7 +19915,8 @@ var PersistentInstructionsPluginNextGen = class {
19813
19915
  throw new Error("PersistentInstructionsPluginNextGen requires agentId");
19814
19916
  }
19815
19917
  this.agentId = config.agentId;
19816
- this.maxLength = config.maxLength ?? DEFAULT_MAX_LENGTH;
19918
+ this.maxTotalLength = config.maxTotalLength ?? DEFAULT_MAX_TOTAL_LENGTH;
19919
+ this.maxEntries = config.maxEntries ?? DEFAULT_MAX_ENTRIES;
19817
19920
  this.storage = config.storage ?? new FilePersistentInstructionsStorage({
19818
19921
  agentId: config.agentId
19819
19922
  });
@@ -19826,14 +19929,16 @@ var PersistentInstructionsPluginNextGen = class {
19826
19929
  }
19827
19930
  async getContent() {
19828
19931
  await this.ensureInitialized();
19829
- if (!this._content) {
19932
+ if (this._entries.size === 0) {
19933
+ this._tokenCache = 0;
19830
19934
  return null;
19831
19935
  }
19832
- this._tokenCache = this.estimator.estimateTokens(this._content);
19833
- return this._content;
19936
+ const rendered = this.renderContent();
19937
+ this._tokenCache = this.estimator.estimateTokens(rendered);
19938
+ return rendered;
19834
19939
  }
19835
19940
  getContents() {
19836
- return this._content;
19941
+ return new Map(this._entries);
19837
19942
  }
19838
19943
  getTokenSize() {
19839
19944
  return this._tokenCache ?? 0;
@@ -19853,32 +19958,54 @@ var PersistentInstructionsPluginNextGen = class {
19853
19958
  getTools() {
19854
19959
  return [
19855
19960
  this.createInstructionsSetTool(),
19856
- this.createInstructionsAppendTool(),
19857
- this.createInstructionsGetTool(),
19961
+ this.createInstructionsRemoveTool(),
19962
+ this.createInstructionsListTool(),
19858
19963
  this.createInstructionsClearTool()
19859
19964
  ];
19860
19965
  }
19861
19966
  destroy() {
19862
19967
  if (this._destroyed) return;
19863
- this._content = null;
19968
+ this._entries.clear();
19864
19969
  this._destroyed = true;
19865
19970
  this._tokenCache = null;
19866
19971
  }
19867
19972
  getState() {
19868
19973
  return {
19869
- content: this._content,
19870
- agentId: this.agentId
19974
+ entries: Array.from(this._entries.values()),
19975
+ agentId: this.agentId,
19976
+ version: 2
19871
19977
  };
19872
19978
  }
19873
19979
  restoreState(state) {
19980
+ if (!state || typeof state !== "object") return;
19874
19981
  const s = state;
19875
- if (!s) return;
19876
- this._content = s.content;
19877
- this._initialized = true;
19878
- this._tokenCache = null;
19982
+ if ("version" in s && s.version === 2 && Array.isArray(s.entries)) {
19983
+ this._entries.clear();
19984
+ for (const entry of s.entries) {
19985
+ this._entries.set(entry.id, entry);
19986
+ }
19987
+ this._initialized = true;
19988
+ this._tokenCache = null;
19989
+ return;
19990
+ }
19991
+ if ("content" in s) {
19992
+ this._entries.clear();
19993
+ const content = s.content;
19994
+ if (content) {
19995
+ const now = Date.now();
19996
+ this._entries.set("legacy_instructions", {
19997
+ id: "legacy_instructions",
19998
+ content,
19999
+ createdAt: now,
20000
+ updatedAt: now
20001
+ });
20002
+ }
20003
+ this._initialized = true;
20004
+ this._tokenCache = null;
20005
+ }
19879
20006
  }
19880
20007
  // ============================================================================
19881
- // Content Management
20008
+ // Public API
19882
20009
  // ============================================================================
19883
20010
  /**
19884
20011
  * Initialize by loading from storage (called lazily)
@@ -19886,66 +20013,99 @@ var PersistentInstructionsPluginNextGen = class {
19886
20013
  async initialize() {
19887
20014
  if (this._initialized || this._destroyed) return;
19888
20015
  try {
19889
- this._content = await this.storage.load();
20016
+ const entries = await this.storage.load();
20017
+ this._entries.clear();
20018
+ if (entries) {
20019
+ for (const entry of entries) {
20020
+ this._entries.set(entry.id, entry);
20021
+ }
20022
+ }
19890
20023
  this._initialized = true;
19891
20024
  } catch (error) {
19892
20025
  console.warn(`Failed to load persistent instructions for agent '${this.agentId}':`, error);
19893
- this._content = null;
20026
+ this._entries.clear();
19894
20027
  this._initialized = true;
19895
20028
  }
19896
20029
  this._tokenCache = null;
19897
20030
  }
19898
20031
  /**
19899
- * Set entire instructions content (replaces existing)
20032
+ * Add or update an instruction entry by key
19900
20033
  */
19901
- async set(content) {
20034
+ async set(key, content) {
19902
20035
  this.assertNotDestroyed();
19903
- if (content.length > this.maxLength) {
20036
+ await this.ensureInitialized();
20037
+ const keyError = validateKey(key);
20038
+ if (keyError) return false;
20039
+ const trimmedContent = content.trim();
20040
+ if (trimmedContent.length === 0) return false;
20041
+ if (!this._entries.has(key) && this._entries.size >= this.maxEntries) {
19904
20042
  return false;
19905
20043
  }
19906
- this._content = content.trim() || null;
19907
- if (this._content) {
19908
- await this.storage.save(this._content);
19909
- } else {
19910
- await this.storage.delete();
20044
+ const currentTotal = this.calculateTotalContentLength();
20045
+ const existingLength = this._entries.get(key)?.content.length ?? 0;
20046
+ const newTotal = currentTotal - existingLength + trimmedContent.length;
20047
+ if (newTotal > this.maxTotalLength) {
20048
+ return false;
19911
20049
  }
20050
+ const now = Date.now();
20051
+ const existing = this._entries.get(key);
20052
+ this._entries.set(key, {
20053
+ id: key,
20054
+ content: trimmedContent,
20055
+ createdAt: existing?.createdAt ?? now,
20056
+ updatedAt: now
20057
+ });
20058
+ await this.persistToStorage();
19912
20059
  this._tokenCache = null;
19913
20060
  return true;
19914
20061
  }
19915
20062
  /**
19916
- * Append a section to existing instructions
20063
+ * Remove an instruction entry by key
19917
20064
  */
19918
- async append(section) {
20065
+ async remove(key) {
19919
20066
  this.assertNotDestroyed();
19920
20067
  await this.ensureInitialized();
19921
- const trimmedSection = section.trim();
19922
- if (!trimmedSection) return true;
19923
- const currentContent = this._content || "";
19924
- const newContent = currentContent ? `${currentContent}
19925
-
19926
- ${trimmedSection}` : trimmedSection;
19927
- if (newContent.length > this.maxLength) {
19928
- return false;
20068
+ if (!this._entries.has(key)) return false;
20069
+ this._entries.delete(key);
20070
+ if (this._entries.size === 0) {
20071
+ await this.storage.delete();
20072
+ } else {
20073
+ await this.persistToStorage();
19929
20074
  }
19930
- this._content = newContent;
19931
- await this.storage.save(this._content);
19932
20075
  this._tokenCache = null;
19933
20076
  return true;
19934
20077
  }
19935
20078
  /**
19936
- * Get current content
20079
+ * Get one entry by key, or all entries if no key provided
19937
20080
  */
19938
- async get() {
20081
+ async get(key) {
19939
20082
  this.assertNotDestroyed();
19940
20083
  await this.ensureInitialized();
19941
- return this._content;
20084
+ if (key !== void 0) {
20085
+ return this._entries.get(key) ?? null;
20086
+ }
20087
+ if (this._entries.size === 0) return null;
20088
+ return this.getSortedEntries();
19942
20089
  }
19943
20090
  /**
19944
- * Clear all instructions
20091
+ * List metadata for all entries
20092
+ */
20093
+ async list() {
20094
+ this.assertNotDestroyed();
20095
+ await this.ensureInitialized();
20096
+ return this.getSortedEntries().map((entry) => ({
20097
+ key: entry.id,
20098
+ contentLength: entry.content.length,
20099
+ createdAt: entry.createdAt,
20100
+ updatedAt: entry.updatedAt
20101
+ }));
20102
+ }
20103
+ /**
20104
+ * Clear all instruction entries
19945
20105
  */
19946
20106
  async clear() {
19947
20107
  this.assertNotDestroyed();
19948
- this._content = null;
20108
+ this._entries.clear();
19949
20109
  await this.storage.delete();
19950
20110
  this._tokenCache = null;
19951
20111
  }
@@ -19968,6 +20128,35 @@ ${trimmedSection}` : trimmedSection;
19968
20128
  throw new Error("PersistentInstructionsPluginNextGen is destroyed");
19969
20129
  }
19970
20130
  }
20131
+ /**
20132
+ * Persist current entries to storage
20133
+ */
20134
+ async persistToStorage() {
20135
+ await this.storage.save(Array.from(this._entries.values()));
20136
+ }
20137
+ /**
20138
+ * Calculate total content length across all entries
20139
+ */
20140
+ calculateTotalContentLength() {
20141
+ let total = 0;
20142
+ for (const entry of this._entries.values()) {
20143
+ total += entry.content.length;
20144
+ }
20145
+ return total;
20146
+ }
20147
+ /**
20148
+ * Get entries sorted by createdAt (oldest first)
20149
+ */
20150
+ getSortedEntries() {
20151
+ return Array.from(this._entries.values()).sort((a, b) => a.createdAt - b.createdAt);
20152
+ }
20153
+ /**
20154
+ * Render all entries as markdown for context injection
20155
+ */
20156
+ renderContent() {
20157
+ return this.getSortedEntries().map((entry) => `### ${entry.id}
20158
+ ${entry.content}`).join("\n\n");
20159
+ }
19971
20160
  // ============================================================================
19972
20161
  // Tool Factories
19973
20162
  // ============================================================================
@@ -19975,60 +20164,84 @@ ${trimmedSection}` : trimmedSection;
19975
20164
  return {
19976
20165
  definition: instructionsSetDefinition,
19977
20166
  execute: async (args) => {
20167
+ const key = args.key;
19978
20168
  const content = args.content;
20169
+ const keyError = validateKey(key);
20170
+ if (keyError) {
20171
+ return { error: keyError };
20172
+ }
19979
20173
  if (!content || content.trim().length === 0) {
19980
- return { error: "Content cannot be empty. Use instructions_clear to remove." };
20174
+ return { error: "Content cannot be empty. Use instructions_remove to delete an entry." };
19981
20175
  }
19982
- const success = await this.set(content);
20176
+ const isUpdate = this._entries.has(key.trim());
20177
+ const success = await this.set(key.trim(), content);
19983
20178
  if (!success) {
19984
- return { error: `Content exceeds maximum length (${this.maxLength} chars)` };
20179
+ if (!isUpdate && this._entries.size >= this.maxEntries) {
20180
+ return { error: `Maximum number of entries reached (${this.maxEntries})` };
20181
+ }
20182
+ return { error: `Content would exceed maximum total length (${this.maxTotalLength} chars)` };
19985
20183
  }
19986
20184
  return {
19987
20185
  success: true,
19988
- message: "Custom instructions updated",
19989
- length: content.length
20186
+ message: isUpdate ? `Instruction '${key.trim()}' updated` : `Instruction '${key.trim()}' added`,
20187
+ key: key.trim(),
20188
+ contentLength: content.trim().length
19990
20189
  };
19991
20190
  },
19992
20191
  permission: { scope: "always", riskLevel: "low" },
19993
- describeCall: () => "set instructions"
20192
+ describeCall: (args) => `set instruction '${args.key}'`
19994
20193
  };
19995
20194
  }
19996
- createInstructionsAppendTool() {
20195
+ createInstructionsRemoveTool() {
19997
20196
  return {
19998
- definition: instructionsAppendDefinition,
20197
+ definition: instructionsRemoveDefinition,
19999
20198
  execute: async (args) => {
20000
- const section = args.section;
20001
- if (!section || section.trim().length === 0) {
20002
- return { error: "Section cannot be empty" };
20199
+ const key = args.key;
20200
+ if (!key || typeof key !== "string" || key.trim().length === 0) {
20201
+ return { error: "Key is required" };
20003
20202
  }
20004
- const success = await this.append(section);
20203
+ const success = await this.remove(key.trim());
20005
20204
  if (!success) {
20006
- return { error: `Would exceed maximum length (${this.maxLength} chars)` };
20205
+ return { error: `Instruction '${key.trim()}' not found` };
20007
20206
  }
20008
20207
  return {
20009
20208
  success: true,
20010
- message: "Section appended to instructions",
20011
- newLength: this._content?.length ?? 0
20209
+ message: `Instruction '${key.trim()}' removed`,
20210
+ key: key.trim()
20012
20211
  };
20013
20212
  },
20014
20213
  permission: { scope: "always", riskLevel: "low" },
20015
- describeCall: () => "append to instructions"
20214
+ describeCall: (args) => `remove instruction '${args.key}'`
20016
20215
  };
20017
20216
  }
20018
- createInstructionsGetTool() {
20217
+ createInstructionsListTool() {
20019
20218
  return {
20020
- definition: instructionsGetDefinition,
20219
+ definition: instructionsListDefinition,
20021
20220
  execute: async () => {
20022
- const content = await this.get();
20221
+ const entries = await this.list();
20222
+ const all = await this.get();
20223
+ if (entries.length === 0) {
20224
+ return {
20225
+ count: 0,
20226
+ entries: [],
20227
+ message: "(no custom instructions set)"
20228
+ };
20229
+ }
20230
+ const allEntries = all;
20023
20231
  return {
20024
- hasContent: content !== null,
20025
- content: content ?? "(no custom instructions set)",
20026
- length: content?.length ?? 0,
20232
+ count: entries.length,
20233
+ entries: allEntries.map((e) => ({
20234
+ key: e.id,
20235
+ content: e.content,
20236
+ contentLength: e.content.length,
20237
+ createdAt: e.createdAt,
20238
+ updatedAt: e.updatedAt
20239
+ })),
20027
20240
  agentId: this.agentId
20028
20241
  };
20029
20242
  },
20030
20243
  permission: { scope: "always", riskLevel: "low" },
20031
- describeCall: () => "get instructions"
20244
+ describeCall: () => "list instructions"
20032
20245
  };
20033
20246
  }
20034
20247
  createInstructionsClearTool() {
@@ -20041,7 +20254,7 @@ ${trimmedSection}` : trimmedSection;
20041
20254
  await this.clear();
20042
20255
  return {
20043
20256
  success: true,
20044
- message: "Custom instructions cleared"
20257
+ message: "All custom instructions cleared"
20045
20258
  };
20046
20259
  },
20047
20260
  permission: { scope: "once", riskLevel: "medium" },
@@ -20766,7 +20979,9 @@ var AgentContextNextGen = class _AgentContextNextGen extends EventEmitter {
20766
20979
  this._agentId = this._config.agentId;
20767
20980
  this._storage = config.storage;
20768
20981
  this._compactionStrategy = config.compactionStrategy ?? StrategyRegistry.create(this._config.strategy);
20769
- this._tools = new ToolManager();
20982
+ this._tools = new ToolManager(
20983
+ config.toolExecutionTimeout ? { toolExecutionTimeout: config.toolExecutionTimeout } : void 0
20984
+ );
20770
20985
  if (config.tools) {
20771
20986
  for (const tool of config.tools) {
20772
20987
  this._tools.register(tool);
@@ -22502,7 +22717,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
22502
22717
  streamConverter;
22503
22718
  constructor(config) {
22504
22719
  super(config);
22505
- this.client = new OpenAI2({
22720
+ this.client = new OpenAI3({
22506
22721
  apiKey: this.getApiKey(),
22507
22722
  baseURL: this.getBaseURL(),
22508
22723
  organization: config.organization,
@@ -24232,7 +24447,9 @@ var GoogleTextProvider = class extends BaseTextProvider {
24232
24447
  constructor(config) {
24233
24448
  super(config);
24234
24449
  this.client = new GoogleGenAI({
24235
- apiKey: this.getApiKey()
24450
+ apiKey: this.getApiKey(),
24451
+ // Pass custom baseURL for proxy support (e.g. when routing through EW proxy)
24452
+ ...config.baseURL ? { httpOptions: { baseUrl: config.baseURL } } : {}
24236
24453
  });
24237
24454
  this.converter = new GoogleConverter();
24238
24455
  this.streamConverter = new GoogleStreamConverter();
@@ -24529,6 +24746,30 @@ var GenericOpenAIProvider = class extends OpenAITextProvider {
24529
24746
  };
24530
24747
 
24531
24748
  // src/core/createProvider.ts
24749
+ var VENDOR_DEFAULT_URLS = (() => {
24750
+ const map = /* @__PURE__ */ new Map();
24751
+ try {
24752
+ map.set(Vendor.OpenAI, new OpenAI3({ apiKey: "_" }).baseURL);
24753
+ } catch {
24754
+ }
24755
+ try {
24756
+ map.set(Vendor.Anthropic, new Anthropic({ apiKey: "_" }).baseURL);
24757
+ } catch {
24758
+ }
24759
+ map.set(Vendor.Google, "https://generativelanguage.googleapis.com");
24760
+ map.set(Vendor.GoogleVertex, "https://us-central1-aiplatform.googleapis.com");
24761
+ map.set(Vendor.Groq, "https://api.groq.com/openai/v1");
24762
+ map.set(Vendor.Together, "https://api.together.xyz/v1");
24763
+ map.set(Vendor.Perplexity, "https://api.perplexity.ai");
24764
+ map.set(Vendor.Grok, "https://api.x.ai/v1");
24765
+ map.set(Vendor.DeepSeek, "https://api.deepseek.com/v1");
24766
+ map.set(Vendor.Mistral, "https://api.mistral.ai/v1");
24767
+ map.set(Vendor.Ollama, "http://localhost:11434/v1");
24768
+ return map;
24769
+ })();
24770
+ function getVendorDefaultBaseURL(vendor) {
24771
+ return VENDOR_DEFAULT_URLS.get(vendor);
24772
+ }
24532
24773
  function createProvider(connector) {
24533
24774
  const injectedProvider = connector.getOptions().provider;
24534
24775
  if (injectedProvider && typeof injectedProvider.generate === "function") {
@@ -24563,39 +24804,15 @@ function createProvider(connector) {
24563
24804
  });
24564
24805
  // OpenAI-compatible providers (use connector.name for unique identification)
24565
24806
  case Vendor.Groq:
24566
- return new GenericOpenAIProvider(connector.name, {
24567
- ...config,
24568
- baseURL: config.baseURL || "https://api.groq.com/openai/v1"
24569
- });
24570
24807
  case Vendor.Together:
24571
- return new GenericOpenAIProvider(connector.name, {
24572
- ...config,
24573
- baseURL: config.baseURL || "https://api.together.xyz/v1"
24574
- });
24575
24808
  case Vendor.Perplexity:
24576
- return new GenericOpenAIProvider(connector.name, {
24577
- ...config,
24578
- baseURL: config.baseURL || "https://api.perplexity.ai"
24579
- });
24580
24809
  case Vendor.Grok:
24581
- return new GenericOpenAIProvider(connector.name, {
24582
- ...config,
24583
- baseURL: config.baseURL || "https://api.x.ai/v1"
24584
- });
24585
24810
  case Vendor.DeepSeek:
24586
- return new GenericOpenAIProvider(connector.name, {
24587
- ...config,
24588
- baseURL: config.baseURL || "https://api.deepseek.com/v1"
24589
- });
24590
24811
  case Vendor.Mistral:
24591
- return new GenericOpenAIProvider(connector.name, {
24592
- ...config,
24593
- baseURL: config.baseURL || "https://api.mistral.ai/v1"
24594
- });
24595
24812
  case Vendor.Ollama:
24596
24813
  return new GenericOpenAIProvider(connector.name, {
24597
24814
  ...config,
24598
- baseURL: config.baseURL || "http://localhost:11434/v1"
24815
+ baseURL: config.baseURL || getVendorDefaultBaseURL(vendor)
24599
24816
  });
24600
24817
  case Vendor.Custom:
24601
24818
  if (!config.baseURL) {
@@ -24707,7 +24924,10 @@ var BaseAgent = class extends EventEmitter {
24707
24924
  agentId: config.name,
24708
24925
  // Include storage and sessionId if session config is provided
24709
24926
  storage: config.session?.storage,
24927
+ // Thread tool execution timeout to ToolManager
24928
+ toolExecutionTimeout: config.toolExecutionTimeout,
24710
24929
  // Subclasses can add systemPrompt via their config
24930
+ // Note: context-level toolExecutionTimeout overrides agent-level if both set
24711
24931
  ...typeof config.context === "object" && config.context !== null ? config.context : {}
24712
24932
  };
24713
24933
  return AgentContextNextGen.create(contextConfig);
@@ -27179,8 +27399,8 @@ var Agent = class _Agent extends BaseAgent {
27179
27399
  throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
27180
27400
  }
27181
27401
  try {
27182
- const fs18 = __require("fs");
27183
- const content = fs18.readFileSync(configPath, "utf-8");
27402
+ const fs17 = __require("fs");
27403
+ const content = fs17.readFileSync(configPath, "utf-8");
27184
27404
  let config = JSON.parse(content);
27185
27405
  config = this.interpolateEnvVars(config);
27186
27406
  this.validate(config);
@@ -27209,10 +27429,10 @@ var Agent = class _Agent extends BaseAgent {
27209
27429
  * Find configuration file synchronously
27210
27430
  */
27211
27431
  static findConfigSync() {
27212
- const fs18 = __require("fs");
27432
+ const fs17 = __require("fs");
27213
27433
  for (const path6 of this.DEFAULT_PATHS) {
27214
27434
  try {
27215
- fs18.accessSync(resolve(path6));
27435
+ fs17.accessSync(resolve(path6));
27216
27436
  return resolve(path6);
27217
27437
  } catch {
27218
27438
  }
@@ -33159,7 +33379,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
33159
33379
  client;
33160
33380
  constructor(config) {
33161
33381
  super({ apiKey: config.auth.apiKey, ...config });
33162
- this.client = new OpenAI2({
33382
+ this.client = new OpenAI3({
33163
33383
  apiKey: config.auth.apiKey,
33164
33384
  baseURL: config.baseURL,
33165
33385
  organization: config.organization,
@@ -33242,7 +33462,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
33242
33462
  * Handle OpenAI API errors
33243
33463
  */
33244
33464
  handleError(error) {
33245
- if (error instanceof OpenAI2.APIError) {
33465
+ if (error instanceof OpenAI3.APIError) {
33246
33466
  const status = error.status;
33247
33467
  const message = error.message || "Unknown OpenAI API error";
33248
33468
  if (status === 401) {
@@ -33274,7 +33494,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
33274
33494
  client;
33275
33495
  constructor(config) {
33276
33496
  super({ apiKey: config.auth.apiKey, ...config });
33277
- this.client = new OpenAI2({
33497
+ this.client = new OpenAI3({
33278
33498
  apiKey: config.auth.apiKey,
33279
33499
  baseURL: config.baseURL,
33280
33500
  organization: config.organization,
@@ -33376,7 +33596,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
33376
33596
  if (Buffer.isBuffer(audio)) {
33377
33597
  return new File([new Uint8Array(audio)], "audio.wav", { type: "audio/wav" });
33378
33598
  } else if (typeof audio === "string") {
33379
- return fs15.createReadStream(audio);
33599
+ return fs16.createReadStream(audio);
33380
33600
  } else {
33381
33601
  throw new Error("Invalid audio input: must be Buffer or file path");
33382
33602
  }
@@ -33435,7 +33655,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
33435
33655
  * Handle OpenAI API errors
33436
33656
  */
33437
33657
  handleError(error) {
33438
- if (error instanceof OpenAI2.APIError) {
33658
+ if (error instanceof OpenAI3.APIError) {
33439
33659
  const status = error.status;
33440
33660
  const message = error.message || "Unknown OpenAI API error";
33441
33661
  if (status === 401) {
@@ -33929,7 +34149,7 @@ var TextToSpeech = class _TextToSpeech {
33929
34149
  */
33930
34150
  async toFile(text, filePath, options) {
33931
34151
  const response = await this.synthesize(text, options);
33932
- await fs14.writeFile(filePath, response.audio);
34152
+ await fs15.writeFile(filePath, response.audio);
33933
34153
  }
33934
34154
  // ======================== Introspection Methods ========================
33935
34155
  /**
@@ -34277,7 +34497,7 @@ var SpeechToText = class _SpeechToText {
34277
34497
  * @param options - Optional transcription parameters
34278
34498
  */
34279
34499
  async transcribeFile(filePath, options) {
34280
- const audio = await fs14.readFile(filePath);
34500
+ const audio = await fs15.readFile(filePath);
34281
34501
  return this.transcribe(audio, options);
34282
34502
  }
34283
34503
  /**
@@ -34441,7 +34661,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
34441
34661
  client;
34442
34662
  constructor(config) {
34443
34663
  super({ apiKey: config.auth.apiKey, ...config });
34444
- this.client = new OpenAI2({
34664
+ this.client = new OpenAI3({
34445
34665
  apiKey: config.auth.apiKey,
34446
34666
  baseURL: config.baseURL,
34447
34667
  organization: config.organization,
@@ -34603,7 +34823,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
34603
34823
  if (Buffer.isBuffer(image)) {
34604
34824
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
34605
34825
  }
34606
- return fs15.createReadStream(image);
34826
+ return fs16.createReadStream(image);
34607
34827
  }
34608
34828
  /**
34609
34829
  * Handle OpenAI API errors
@@ -34750,8 +34970,8 @@ var GoogleImageProvider = class extends BaseMediaProvider {
34750
34970
  if (Buffer.isBuffer(image)) {
34751
34971
  imageBytes = image.toString("base64");
34752
34972
  } else {
34753
- const fs18 = await import('fs');
34754
- const buffer = fs18.readFileSync(image);
34973
+ const fs17 = await import('fs');
34974
+ const buffer = fs17.readFileSync(image);
34755
34975
  imageBytes = buffer.toString("base64");
34756
34976
  }
34757
34977
  return {
@@ -34801,7 +35021,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
34801
35021
  client;
34802
35022
  constructor(config) {
34803
35023
  super({ apiKey: config.auth.apiKey, ...config });
34804
- this.client = new OpenAI2({
35024
+ this.client = new OpenAI3({
34805
35025
  apiKey: config.auth.apiKey,
34806
35026
  baseURL: config.baseURL || GROK_API_BASE_URL,
34807
35027
  timeout: config.timeout,
@@ -34912,7 +35132,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
34912
35132
  if (Buffer.isBuffer(image)) {
34913
35133
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
34914
35134
  }
34915
- return fs15.createReadStream(image);
35135
+ return fs16.createReadStream(image);
34916
35136
  }
34917
35137
  /**
34918
35138
  * Handle API errors
@@ -36114,7 +36334,7 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
36114
36334
  client;
36115
36335
  constructor(config) {
36116
36336
  super({ apiKey: config.auth.apiKey, ...config });
36117
- this.client = new OpenAI2({
36337
+ this.client = new OpenAI3({
36118
36338
  apiKey: config.auth.apiKey,
36119
36339
  baseURL: config.baseURL,
36120
36340
  organization: config.organization,
@@ -36362,8 +36582,8 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
36362
36582
  return new File([new Uint8Array(image)], "input.png", { type: "image/png" });
36363
36583
  }
36364
36584
  if (!image.startsWith("http")) {
36365
- const fs18 = await import('fs');
36366
- const data = fs18.readFileSync(image);
36585
+ const fs17 = await import('fs');
36586
+ const data = fs17.readFileSync(image);
36367
36587
  return new File([new Uint8Array(data)], "input.png", { type: "image/png" });
36368
36588
  }
36369
36589
  const response = await fetch(image);
@@ -36541,7 +36761,7 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
36541
36761
  if (video.videoBytes) {
36542
36762
  buffer = Buffer.from(video.videoBytes, "base64");
36543
36763
  } else if (video.uri) {
36544
- const fs18 = await import('fs/promises');
36764
+ const fs17 = await import('fs/promises');
36545
36765
  const os3 = await import('os');
36546
36766
  const path6 = await import('path');
36547
36767
  const tempDir = os3.tmpdir();
@@ -36552,11 +36772,11 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
36552
36772
  // Pass as GeneratedVideo
36553
36773
  downloadPath: tempFile
36554
36774
  });
36555
- buffer = await fs18.readFile(tempFile);
36556
- await fs18.unlink(tempFile).catch(() => {
36775
+ buffer = await fs17.readFile(tempFile);
36776
+ await fs17.unlink(tempFile).catch(() => {
36557
36777
  });
36558
36778
  } catch (downloadError) {
36559
- await fs18.unlink(tempFile).catch(() => {
36779
+ await fs17.unlink(tempFile).catch(() => {
36560
36780
  });
36561
36781
  throw new ProviderError(
36562
36782
  "google",
@@ -36678,8 +36898,8 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
36678
36898
  if (image.startsWith("http://") || image.startsWith("https://")) {
36679
36899
  return { imageUri: image };
36680
36900
  }
36681
- const fs18 = await import('fs/promises');
36682
- const data = await fs18.readFile(image);
36901
+ const fs17 = await import('fs/promises');
36902
+ const data = await fs17.readFile(image);
36683
36903
  return {
36684
36904
  imageBytes: data.toString("base64")
36685
36905
  };
@@ -36986,8 +37206,8 @@ var GrokImagineProvider = class extends BaseMediaProvider {
36986
37206
  if (image.startsWith("http") || image.startsWith("data:")) {
36987
37207
  return image;
36988
37208
  }
36989
- const fs18 = await import('fs');
36990
- const data = fs18.readFileSync(image);
37209
+ const fs17 = await import('fs');
37210
+ const data = fs17.readFileSync(image);
36991
37211
  const base64 = data.toString("base64");
36992
37212
  const ext = image.split(".").pop()?.toLowerCase() || "png";
36993
37213
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext}`;
@@ -40724,6 +40944,126 @@ var FileAgentDefinitionStorage = class {
40724
40944
  function createFileAgentDefinitionStorage(config) {
40725
40945
  return new FileAgentDefinitionStorage(config);
40726
40946
  }
40947
+ var MIME_TYPES = {
40948
+ png: "image/png",
40949
+ jpeg: "image/jpeg",
40950
+ jpg: "image/jpeg",
40951
+ webp: "image/webp",
40952
+ gif: "image/gif",
40953
+ mp4: "video/mp4",
40954
+ webm: "video/webm",
40955
+ mp3: "audio/mpeg",
40956
+ wav: "audio/wav",
40957
+ opus: "audio/opus",
40958
+ ogg: "audio/ogg",
40959
+ aac: "audio/aac",
40960
+ flac: "audio/flac",
40961
+ pcm: "audio/pcm"
40962
+ };
40963
+ var MEDIA_TYPE_PREFIXES = ["image", "video", "audio"];
40964
+ var FileMediaStorage = class {
40965
+ outputDir;
40966
+ initialized = false;
40967
+ constructor(config) {
40968
+ this.outputDir = config?.outputDir ?? path2.join(os2.tmpdir(), "oneringai-media");
40969
+ }
40970
+ async save(data, metadata) {
40971
+ const dir = metadata.userId ? path2.join(this.outputDir, metadata.userId) : this.outputDir;
40972
+ await fs15.mkdir(dir, { recursive: true });
40973
+ const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
40974
+ const filePath = path2.join(dir, filename);
40975
+ await fs15.writeFile(filePath, data);
40976
+ const format = metadata.format.toLowerCase();
40977
+ const mimeType = MIME_TYPES[format] ?? "application/octet-stream";
40978
+ return {
40979
+ location: filePath,
40980
+ mimeType,
40981
+ size: data.length
40982
+ };
40983
+ }
40984
+ async read(location) {
40985
+ try {
40986
+ return await fs15.readFile(location);
40987
+ } catch (err) {
40988
+ if (err.code === "ENOENT") {
40989
+ return null;
40990
+ }
40991
+ throw err;
40992
+ }
40993
+ }
40994
+ async delete(location) {
40995
+ try {
40996
+ await fs15.unlink(location);
40997
+ } catch (err) {
40998
+ if (err.code === "ENOENT") {
40999
+ return;
41000
+ }
41001
+ throw err;
41002
+ }
41003
+ }
41004
+ async exists(location) {
41005
+ try {
41006
+ await fs15.access(location);
41007
+ return true;
41008
+ } catch {
41009
+ return false;
41010
+ }
41011
+ }
41012
+ async list(options) {
41013
+ await this.ensureDir();
41014
+ let entries = [];
41015
+ const files = await fs15.readdir(this.outputDir);
41016
+ for (const file of files) {
41017
+ const filePath = path2.join(this.outputDir, file);
41018
+ try {
41019
+ const stat6 = await fs15.stat(filePath);
41020
+ if (!stat6.isFile()) continue;
41021
+ const ext = path2.extname(file).slice(1).toLowerCase();
41022
+ const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
41023
+ let type;
41024
+ for (const prefix of MEDIA_TYPE_PREFIXES) {
41025
+ if (file.startsWith(`${prefix}_`)) {
41026
+ type = prefix;
41027
+ break;
41028
+ }
41029
+ }
41030
+ entries.push({
41031
+ location: filePath,
41032
+ mimeType,
41033
+ size: stat6.size,
41034
+ type,
41035
+ createdAt: stat6.birthtime
41036
+ });
41037
+ } catch {
41038
+ }
41039
+ }
41040
+ if (options?.type) {
41041
+ entries = entries.filter((e) => e.type === options.type);
41042
+ }
41043
+ entries.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
41044
+ const offset = options?.offset ?? 0;
41045
+ const limit = options?.limit ?? entries.length;
41046
+ return entries.slice(offset, offset + limit);
41047
+ }
41048
+ getPath() {
41049
+ return this.outputDir;
41050
+ }
41051
+ generateFilename(metadata) {
41052
+ const timestamp = Date.now();
41053
+ const random2 = crypto2.randomBytes(4).toString("hex");
41054
+ const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
41055
+ return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
41056
+ }
41057
+ async ensureDir() {
41058
+ if (!this.initialized) {
41059
+ await fs15.mkdir(this.outputDir, { recursive: true });
41060
+ this.initialized = true;
41061
+ }
41062
+ }
41063
+ };
41064
+ function createFileMediaStorage(config) {
41065
+ return new FileMediaStorage(config);
41066
+ }
40727
41067
 
40728
41068
  // src/capabilities/agents/StreamHelpers.ts
40729
41069
  var StreamHelpers = class {
@@ -41646,7 +41986,7 @@ var ConnectorTools = class {
41646
41986
  static createGenericAPITool(connector, options) {
41647
41987
  const toolName = options?.toolName ?? `${connector.name}_api`;
41648
41988
  const userId = options?.userId;
41649
- const description = options?.description ?? `Make an authenticated API call to ${connector.displayName}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}` : " Provide full URL in endpoint.");
41989
+ 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.';
41650
41990
  return {
41651
41991
  definition: {
41652
41992
  type: "function",
@@ -41663,15 +42003,15 @@ var ConnectorTools = class {
41663
42003
  },
41664
42004
  endpoint: {
41665
42005
  type: "string",
41666
- description: "API endpoint (relative to base URL) or full URL"
42006
+ 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.'
41667
42007
  },
41668
42008
  body: {
41669
42009
  type: "object",
41670
- description: "Request body (for POST/PUT/PATCH)"
42010
+ 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.'
41671
42011
  },
41672
42012
  queryParams: {
41673
42013
  type: "object",
41674
- description: "URL query parameters"
42014
+ description: 'URL query parameters (for filtering/pagination on GET requests). Do NOT use for POST/PUT/PATCH data \u2014 use "body" instead.'
41675
42015
  },
41676
42016
  headers: {
41677
42017
  type: "object",
@@ -41736,7 +42076,10 @@ var ConnectorTools = class {
41736
42076
  };
41737
42077
  }
41738
42078
  },
41739
- describeCall: (args) => `${args.method} ${args.endpoint}`,
42079
+ describeCall: (args) => {
42080
+ const bodyInfo = args.body ? ` body=${JSON.stringify(args.body).slice(0, 100)}` : "";
42081
+ return `${args.method} ${args.endpoint}${bodyInfo}`;
42082
+ },
41740
42083
  permission: options?.permission ?? {
41741
42084
  scope: "session",
41742
42085
  riskLevel: "medium",
@@ -41771,8 +42114,8 @@ var FileStorage = class {
41771
42114
  }
41772
42115
  async ensureDirectory() {
41773
42116
  try {
41774
- await fs14.mkdir(this.directory, { recursive: true });
41775
- await fs14.chmod(this.directory, 448);
42117
+ await fs15.mkdir(this.directory, { recursive: true });
42118
+ await fs15.chmod(this.directory, 448);
41776
42119
  } catch (error) {
41777
42120
  }
41778
42121
  }
@@ -41781,20 +42124,20 @@ var FileStorage = class {
41781
42124
  */
41782
42125
  getFilePath(key) {
41783
42126
  const hash = crypto2.createHash("sha256").update(key).digest("hex");
41784
- return path3.join(this.directory, `${hash}.token`);
42127
+ return path2.join(this.directory, `${hash}.token`);
41785
42128
  }
41786
42129
  async storeToken(key, token) {
41787
42130
  await this.ensureDirectory();
41788
42131
  const filePath = this.getFilePath(key);
41789
42132
  const plaintext = JSON.stringify(token);
41790
42133
  const encrypted = encrypt(plaintext, this.encryptionKey);
41791
- await fs14.writeFile(filePath, encrypted, "utf8");
41792
- await fs14.chmod(filePath, 384);
42134
+ await fs15.writeFile(filePath, encrypted, "utf8");
42135
+ await fs15.chmod(filePath, 384);
41793
42136
  }
41794
42137
  async getToken(key) {
41795
42138
  const filePath = this.getFilePath(key);
41796
42139
  try {
41797
- const encrypted = await fs14.readFile(filePath, "utf8");
42140
+ const encrypted = await fs15.readFile(filePath, "utf8");
41798
42141
  const decrypted = decrypt(encrypted, this.encryptionKey);
41799
42142
  return JSON.parse(decrypted);
41800
42143
  } catch (error) {
@@ -41803,7 +42146,7 @@ var FileStorage = class {
41803
42146
  }
41804
42147
  console.error("Failed to read/decrypt token file:", error);
41805
42148
  try {
41806
- await fs14.unlink(filePath);
42149
+ await fs15.unlink(filePath);
41807
42150
  } catch {
41808
42151
  }
41809
42152
  return null;
@@ -41812,7 +42155,7 @@ var FileStorage = class {
41812
42155
  async deleteToken(key) {
41813
42156
  const filePath = this.getFilePath(key);
41814
42157
  try {
41815
- await fs14.unlink(filePath);
42158
+ await fs15.unlink(filePath);
41816
42159
  } catch (error) {
41817
42160
  if (error.code !== "ENOENT") {
41818
42161
  throw error;
@@ -41822,7 +42165,7 @@ var FileStorage = class {
41822
42165
  async hasToken(key) {
41823
42166
  const filePath = this.getFilePath(key);
41824
42167
  try {
41825
- await fs14.access(filePath);
42168
+ await fs15.access(filePath);
41826
42169
  return true;
41827
42170
  } catch {
41828
42171
  return false;
@@ -41833,7 +42176,7 @@ var FileStorage = class {
41833
42176
  */
41834
42177
  async listTokens() {
41835
42178
  try {
41836
- const files = await fs14.readdir(this.directory);
42179
+ const files = await fs15.readdir(this.directory);
41837
42180
  return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
41838
42181
  } catch {
41839
42182
  return [];
@@ -41844,10 +42187,10 @@ var FileStorage = class {
41844
42187
  */
41845
42188
  async clearAll() {
41846
42189
  try {
41847
- const files = await fs14.readdir(this.directory);
42190
+ const files = await fs15.readdir(this.directory);
41848
42191
  const tokenFiles = files.filter((f) => f.endsWith(".token"));
41849
42192
  await Promise.all(
41850
- tokenFiles.map((f) => fs14.unlink(path3.join(this.directory, f)).catch(() => {
42193
+ tokenFiles.map((f) => fs15.unlink(path2.join(this.directory, f)).catch(() => {
41851
42194
  }))
41852
42195
  );
41853
42196
  } catch {
@@ -42115,22 +42458,26 @@ var ConnectorConfigStore = class {
42115
42458
  * Encrypt secrets in ConnectorAuth based on auth type
42116
42459
  */
42117
42460
  encryptAuthSecrets(auth2) {
42461
+ const encryptedExtra = this.encryptExtra(auth2.extra);
42118
42462
  switch (auth2.type) {
42119
42463
  case "api_key":
42120
42464
  return {
42121
42465
  ...auth2,
42122
- apiKey: this.encryptValue(auth2.apiKey)
42466
+ apiKey: this.encryptValue(auth2.apiKey),
42467
+ ...encryptedExtra ? { extra: encryptedExtra } : {}
42123
42468
  };
42124
42469
  case "oauth":
42125
42470
  return {
42126
42471
  ...auth2,
42127
42472
  clientSecret: auth2.clientSecret ? this.encryptValue(auth2.clientSecret) : void 0,
42128
- privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0
42473
+ privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0,
42474
+ ...encryptedExtra ? { extra: encryptedExtra } : {}
42129
42475
  };
42130
42476
  case "jwt":
42131
42477
  return {
42132
42478
  ...auth2,
42133
- privateKey: this.encryptValue(auth2.privateKey)
42479
+ privateKey: this.encryptValue(auth2.privateKey),
42480
+ ...encryptedExtra ? { extra: encryptedExtra } : {}
42134
42481
  };
42135
42482
  default:
42136
42483
  return auth2;
@@ -42140,27 +42487,53 @@ var ConnectorConfigStore = class {
42140
42487
  * Decrypt secrets in ConnectorAuth based on auth type
42141
42488
  */
42142
42489
  decryptAuthSecrets(auth2) {
42490
+ const decryptedExtra = this.decryptExtra(auth2.extra);
42143
42491
  switch (auth2.type) {
42144
42492
  case "api_key":
42145
42493
  return {
42146
42494
  ...auth2,
42147
- apiKey: this.decryptValue(auth2.apiKey)
42495
+ apiKey: this.decryptValue(auth2.apiKey),
42496
+ ...decryptedExtra ? { extra: decryptedExtra } : {}
42148
42497
  };
42149
42498
  case "oauth":
42150
42499
  return {
42151
42500
  ...auth2,
42152
42501
  clientSecret: auth2.clientSecret ? this.decryptValue(auth2.clientSecret) : void 0,
42153
- privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0
42502
+ privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0,
42503
+ ...decryptedExtra ? { extra: decryptedExtra } : {}
42154
42504
  };
42155
42505
  case "jwt":
42156
42506
  return {
42157
42507
  ...auth2,
42158
- privateKey: this.decryptValue(auth2.privateKey)
42508
+ privateKey: this.decryptValue(auth2.privateKey),
42509
+ ...decryptedExtra ? { extra: decryptedExtra } : {}
42159
42510
  };
42160
42511
  default:
42161
42512
  return auth2;
42162
42513
  }
42163
42514
  }
42515
+ /**
42516
+ * Encrypt all values in an extra Record (vendor-specific credentials)
42517
+ */
42518
+ encryptExtra(extra) {
42519
+ if (!extra || Object.keys(extra).length === 0) return void 0;
42520
+ const result = {};
42521
+ for (const [key, value] of Object.entries(extra)) {
42522
+ result[key] = this.encryptValue(value);
42523
+ }
42524
+ return result;
42525
+ }
42526
+ /**
42527
+ * Decrypt all values in an extra Record (vendor-specific credentials)
42528
+ */
42529
+ decryptExtra(extra) {
42530
+ if (!extra || Object.keys(extra).length === 0) return void 0;
42531
+ const result = {};
42532
+ for (const [key, value] of Object.entries(extra)) {
42533
+ result[key] = this.decryptValue(value);
42534
+ }
42535
+ return result;
42536
+ }
42164
42537
  /**
42165
42538
  * Encrypt a single value if not already encrypted
42166
42539
  */
@@ -42238,20 +42611,20 @@ var FileConnectorStorage = class {
42238
42611
  throw new Error("FileConnectorStorage requires a directory path");
42239
42612
  }
42240
42613
  this.directory = config.directory;
42241
- this.indexPath = path3.join(this.directory, "_index.json");
42614
+ this.indexPath = path2.join(this.directory, "_index.json");
42242
42615
  }
42243
42616
  async save(name, stored) {
42244
42617
  await this.ensureDirectory();
42245
42618
  const filePath = this.getFilePath(name);
42246
42619
  const json = JSON.stringify(stored, null, 2);
42247
- await fs14.writeFile(filePath, json, "utf8");
42248
- await fs14.chmod(filePath, 384);
42620
+ await fs15.writeFile(filePath, json, "utf8");
42621
+ await fs15.chmod(filePath, 384);
42249
42622
  await this.updateIndex(name, "add");
42250
42623
  }
42251
42624
  async get(name) {
42252
42625
  const filePath = this.getFilePath(name);
42253
42626
  try {
42254
- const json = await fs14.readFile(filePath, "utf8");
42627
+ const json = await fs15.readFile(filePath, "utf8");
42255
42628
  return JSON.parse(json);
42256
42629
  } catch (error) {
42257
42630
  const err = error;
@@ -42264,7 +42637,7 @@ var FileConnectorStorage = class {
42264
42637
  async delete(name) {
42265
42638
  const filePath = this.getFilePath(name);
42266
42639
  try {
42267
- await fs14.unlink(filePath);
42640
+ await fs15.unlink(filePath);
42268
42641
  await this.updateIndex(name, "remove");
42269
42642
  return true;
42270
42643
  } catch (error) {
@@ -42278,7 +42651,7 @@ var FileConnectorStorage = class {
42278
42651
  async has(name) {
42279
42652
  const filePath = this.getFilePath(name);
42280
42653
  try {
42281
- await fs14.access(filePath);
42654
+ await fs15.access(filePath);
42282
42655
  return true;
42283
42656
  } catch {
42284
42657
  return false;
@@ -42304,13 +42677,13 @@ var FileConnectorStorage = class {
42304
42677
  */
42305
42678
  async clear() {
42306
42679
  try {
42307
- const files = await fs14.readdir(this.directory);
42680
+ const files = await fs15.readdir(this.directory);
42308
42681
  const connectorFiles = files.filter(
42309
42682
  (f) => f.endsWith(".connector.json") || f === "_index.json"
42310
42683
  );
42311
42684
  await Promise.all(
42312
42685
  connectorFiles.map(
42313
- (f) => fs14.unlink(path3.join(this.directory, f)).catch(() => {
42686
+ (f) => fs15.unlink(path2.join(this.directory, f)).catch(() => {
42314
42687
  })
42315
42688
  )
42316
42689
  );
@@ -42323,7 +42696,7 @@ var FileConnectorStorage = class {
42323
42696
  */
42324
42697
  getFilePath(name) {
42325
42698
  const hash = this.hashName(name);
42326
- return path3.join(this.directory, `${hash}.connector.json`);
42699
+ return path2.join(this.directory, `${hash}.connector.json`);
42327
42700
  }
42328
42701
  /**
42329
42702
  * Hash connector name to prevent enumeration
@@ -42337,8 +42710,8 @@ var FileConnectorStorage = class {
42337
42710
  async ensureDirectory() {
42338
42711
  if (this.initialized) return;
42339
42712
  try {
42340
- await fs14.mkdir(this.directory, { recursive: true });
42341
- await fs14.chmod(this.directory, 448);
42713
+ await fs15.mkdir(this.directory, { recursive: true });
42714
+ await fs15.chmod(this.directory, 448);
42342
42715
  this.initialized = true;
42343
42716
  } catch {
42344
42717
  this.initialized = true;
@@ -42349,7 +42722,7 @@ var FileConnectorStorage = class {
42349
42722
  */
42350
42723
  async loadIndex() {
42351
42724
  try {
42352
- const json = await fs14.readFile(this.indexPath, "utf8");
42725
+ const json = await fs15.readFile(this.indexPath, "utf8");
42353
42726
  return JSON.parse(json);
42354
42727
  } catch {
42355
42728
  return { connectors: {} };
@@ -42367,8 +42740,8 @@ var FileConnectorStorage = class {
42367
42740
  delete index.connectors[hash];
42368
42741
  }
42369
42742
  const json = JSON.stringify(index, null, 2);
42370
- await fs14.writeFile(this.indexPath, json, "utf8");
42371
- await fs14.chmod(this.indexPath, 384);
42743
+ await fs15.writeFile(this.indexPath, json, "utf8");
42744
+ await fs15.chmod(this.indexPath, 384);
42372
42745
  }
42373
42746
  };
42374
42747
 
@@ -42413,11 +42786,19 @@ function buildAuthConfig(authTemplate, credentials) {
42413
42786
  if (!credentials.apiKey) {
42414
42787
  throw new Error("API key is required for api_key auth");
42415
42788
  }
42789
+ const standardApiKeyFields = /* @__PURE__ */ new Set(["apiKey", "headerName", "headerPrefix"]);
42790
+ const extra = {};
42791
+ for (const field of authTemplate.optionalFields ?? []) {
42792
+ if (!standardApiKeyFields.has(field) && credentials[field]) {
42793
+ extra[field] = credentials[field];
42794
+ }
42795
+ }
42416
42796
  return {
42417
42797
  type: "api_key",
42418
42798
  apiKey: credentials.apiKey,
42419
42799
  headerName: defaults.headerName ?? "Authorization",
42420
- headerPrefix: defaults.headerPrefix ?? "Bearer"
42800
+ headerPrefix: defaults.headerPrefix ?? "Bearer",
42801
+ ...Object.keys(extra).length > 0 ? { extra } : {}
42421
42802
  };
42422
42803
  }
42423
42804
  if (!authTemplate.flow) {
@@ -42687,8 +43068,9 @@ var slackTemplate = {
42687
43068
  id: "bot-token",
42688
43069
  name: "Bot Token",
42689
43070
  type: "api_key",
42690
- description: "Internal workspace bot - get from OAuth & Permissions page of your Slack app",
43071
+ 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.",
42691
43072
  requiredFields: ["apiKey"],
43073
+ optionalFields: ["appToken", "signingSecret"],
42692
43074
  defaults: {
42693
43075
  type: "api_key",
42694
43076
  headerName: "Authorization",
@@ -44526,14 +44908,14 @@ function createMessageWithImages(text, imageUrls, role = "user" /* USER */) {
44526
44908
  var execAsync = promisify(exec);
44527
44909
  function cleanupTempFile(filePath) {
44528
44910
  try {
44529
- if (fs15.existsSync(filePath)) {
44530
- fs15.unlinkSync(filePath);
44911
+ if (fs16.existsSync(filePath)) {
44912
+ fs16.unlinkSync(filePath);
44531
44913
  }
44532
44914
  } catch {
44533
44915
  }
44534
44916
  }
44535
44917
  async function readClipboardImage() {
44536
- const platform2 = os.platform();
44918
+ const platform2 = os2.platform();
44537
44919
  try {
44538
44920
  switch (platform2) {
44539
44921
  case "darwin":
@@ -44556,7 +44938,7 @@ async function readClipboardImage() {
44556
44938
  }
44557
44939
  }
44558
44940
  async function readClipboardImageMac() {
44559
- const tempFile = path3.join(os.tmpdir(), `clipboard-${Date.now()}.png`);
44941
+ const tempFile = path2.join(os2.tmpdir(), `clipboard-${Date.now()}.png`);
44560
44942
  try {
44561
44943
  try {
44562
44944
  await execAsync(`pngpaste "${tempFile}"`);
@@ -44578,7 +44960,7 @@ async function readClipboardImageMac() {
44578
44960
  end try
44579
44961
  `;
44580
44962
  const { stdout } = await execAsync(`osascript -e '${script}'`);
44581
- if (stdout.includes("success") || fs15.existsSync(tempFile)) {
44963
+ if (stdout.includes("success") || fs16.existsSync(tempFile)) {
44582
44964
  return await convertFileToDataUri(tempFile);
44583
44965
  }
44584
44966
  return {
@@ -44591,18 +44973,18 @@ async function readClipboardImageMac() {
44591
44973
  }
44592
44974
  }
44593
44975
  async function readClipboardImageLinux() {
44594
- const tempFile = path3.join(os.tmpdir(), `clipboard-${Date.now()}.png`);
44976
+ const tempFile = path2.join(os2.tmpdir(), `clipboard-${Date.now()}.png`);
44595
44977
  try {
44596
44978
  try {
44597
44979
  await execAsync(`xclip -selection clipboard -t image/png -o > "${tempFile}"`);
44598
- if (fs15.existsSync(tempFile) && fs15.statSync(tempFile).size > 0) {
44980
+ if (fs16.existsSync(tempFile) && fs16.statSync(tempFile).size > 0) {
44599
44981
  return await convertFileToDataUri(tempFile);
44600
44982
  }
44601
44983
  } catch {
44602
44984
  }
44603
44985
  try {
44604
44986
  await execAsync(`wl-paste -t image/png > "${tempFile}"`);
44605
- if (fs15.existsSync(tempFile) && fs15.statSync(tempFile).size > 0) {
44987
+ if (fs16.existsSync(tempFile) && fs16.statSync(tempFile).size > 0) {
44606
44988
  return await convertFileToDataUri(tempFile);
44607
44989
  }
44608
44990
  } catch {
@@ -44616,7 +44998,7 @@ async function readClipboardImageLinux() {
44616
44998
  }
44617
44999
  }
44618
45000
  async function readClipboardImageWindows() {
44619
- const tempFile = path3.join(os.tmpdir(), `clipboard-${Date.now()}.png`);
45001
+ const tempFile = path2.join(os2.tmpdir(), `clipboard-${Date.now()}.png`);
44620
45002
  try {
44621
45003
  const psScript = `
44622
45004
  Add-Type -AssemblyName System.Windows.Forms;
@@ -44629,7 +45011,7 @@ async function readClipboardImageWindows() {
44629
45011
  }
44630
45012
  `;
44631
45013
  await execAsync(`powershell -Command "${psScript}"`);
44632
- if (fs15.existsSync(tempFile) && fs15.statSync(tempFile).size > 0) {
45014
+ if (fs16.existsSync(tempFile) && fs16.statSync(tempFile).size > 0) {
44633
45015
  return await convertFileToDataUri(tempFile);
44634
45016
  }
44635
45017
  return {
@@ -44642,7 +45024,7 @@ async function readClipboardImageWindows() {
44642
45024
  }
44643
45025
  async function convertFileToDataUri(filePath) {
44644
45026
  try {
44645
- const imageBuffer = fs15.readFileSync(filePath);
45027
+ const imageBuffer = fs16.readFileSync(filePath);
44646
45028
  const base64Image = imageBuffer.toString("base64");
44647
45029
  const magic = imageBuffer.slice(0, 4).toString("hex");
44648
45030
  let mimeType = "image/png";
@@ -44669,7 +45051,7 @@ async function convertFileToDataUri(filePath) {
44669
45051
  }
44670
45052
  }
44671
45053
  async function hasClipboardImage() {
44672
- const platform2 = os.platform();
45054
+ const platform2 = os2.platform();
44673
45055
  try {
44674
45056
  switch (platform2) {
44675
45057
  case "darwin":
@@ -44887,17 +45269,24 @@ __export(tools_exports, {
44887
45269
  ConnectorTools: () => ConnectorTools,
44888
45270
  DEFAULT_FILESYSTEM_CONFIG: () => DEFAULT_FILESYSTEM_CONFIG,
44889
45271
  DEFAULT_SHELL_CONFIG: () => DEFAULT_SHELL_CONFIG,
44890
- FileMediaOutputHandler: () => FileMediaOutputHandler,
45272
+ FileMediaOutputHandler: () => FileMediaStorage,
44891
45273
  ToolRegistry: () => ToolRegistry,
44892
45274
  bash: () => bash,
44893
45275
  createBashTool: () => createBashTool,
45276
+ createCreatePRTool: () => createCreatePRTool,
44894
45277
  createEditFileTool: () => createEditFileTool,
44895
45278
  createExecuteJavaScriptTool: () => createExecuteJavaScriptTool,
45279
+ createGetPRTool: () => createGetPRTool,
45280
+ createGitHubReadFileTool: () => createGitHubReadFileTool,
44896
45281
  createGlobTool: () => createGlobTool,
44897
45282
  createGrepTool: () => createGrepTool,
44898
45283
  createImageGenerationTool: () => createImageGenerationTool,
44899
45284
  createListDirectoryTool: () => createListDirectoryTool,
45285
+ createPRCommentsTool: () => createPRCommentsTool,
45286
+ createPRFilesTool: () => createPRFilesTool,
44900
45287
  createReadFileTool: () => createReadFileTool,
45288
+ createSearchCodeTool: () => createSearchCodeTool,
45289
+ createSearchFilesTool: () => createSearchFilesTool,
44901
45290
  createSpeechToTextTool: () => createSpeechToTextTool,
44902
45291
  createTextToSpeechTool: () => createTextToSpeechTool,
44903
45292
  createVideoTools: () => createVideoTools,
@@ -44909,6 +45298,7 @@ __export(tools_exports, {
44909
45298
  getAllBuiltInTools: () => getAllBuiltInTools,
44910
45299
  getBackgroundOutput: () => getBackgroundOutput,
44911
45300
  getMediaOutputHandler: () => getMediaOutputHandler,
45301
+ getMediaStorage: () => getMediaStorage,
44912
45302
  getToolByName: () => getToolByName,
44913
45303
  getToolCategories: () => getToolCategories,
44914
45304
  getToolRegistry: () => getToolRegistry,
@@ -44921,15 +45311,18 @@ __export(tools_exports, {
44921
45311
  jsonManipulator: () => jsonManipulator,
44922
45312
  killBackgroundProcess: () => killBackgroundProcess,
44923
45313
  listDirectory: () => listDirectory,
44924
- readFile: () => readFile4,
45314
+ parseRepository: () => parseRepository,
45315
+ readFile: () => readFile5,
45316
+ resolveRepository: () => resolveRepository,
44925
45317
  setMediaOutputHandler: () => setMediaOutputHandler,
45318
+ setMediaStorage: () => setMediaStorage,
44926
45319
  toolRegistry: () => toolRegistry,
44927
45320
  validatePath: () => validatePath,
44928
45321
  webFetch: () => webFetch,
44929
45322
  webFetchJS: () => webFetchJS,
44930
45323
  webScrape: () => webScrape,
44931
45324
  webSearch: () => webSearch,
44932
- writeFile: () => writeFile4
45325
+ writeFile: () => writeFile5
44933
45326
  });
44934
45327
  var DEFAULT_FILESYSTEM_CONFIG = {
44935
45328
  workingDirectory: process.cwd(),
@@ -45182,7 +45575,7 @@ EXAMPLES:
45182
45575
  }
45183
45576
  };
45184
45577
  }
45185
- var readFile4 = createReadFileTool();
45578
+ var readFile5 = createReadFileTool();
45186
45579
  function createWriteFileTool(config = {}) {
45187
45580
  const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
45188
45581
  return {
@@ -45269,7 +45662,7 @@ EXAMPLES:
45269
45662
  }
45270
45663
  };
45271
45664
  }
45272
- var writeFile4 = createWriteFileTool();
45665
+ var writeFile5 = createWriteFileTool();
45273
45666
  function createEditFileTool(config = {}) {
45274
45667
  const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
45275
45668
  return {
@@ -46196,7 +46589,8 @@ EXAMPLES:
46196
46589
  shell: mergedConfig.shell,
46197
46590
  cwd: mergedConfig.workingDirectory,
46198
46591
  env,
46199
- stdio: ["pipe", "pipe", "pipe"]
46592
+ stdio: ["pipe", "pipe", "pipe"],
46593
+ detached: true
46200
46594
  });
46201
46595
  if (run_in_background && mergedConfig.allowBackground) {
46202
46596
  const bgId = generateBackgroundId();
@@ -46223,14 +46617,27 @@ EXAMPLES:
46223
46617
  let stdout = "";
46224
46618
  let stderr = "";
46225
46619
  let killed = false;
46620
+ const killProcessGroup = (signal) => {
46621
+ try {
46622
+ if (childProcess.pid) {
46623
+ process.kill(-childProcess.pid, signal);
46624
+ }
46625
+ } catch {
46626
+ try {
46627
+ childProcess.kill(signal);
46628
+ } catch {
46629
+ }
46630
+ }
46631
+ };
46632
+ const GRACEFUL_KILL_WAIT_MS = 3e3;
46226
46633
  const timeoutId = setTimeout(() => {
46227
46634
  killed = true;
46228
- childProcess.kill("SIGTERM");
46635
+ killProcessGroup("SIGTERM");
46229
46636
  setTimeout(() => {
46230
46637
  if (!childProcess.killed) {
46231
- childProcess.kill("SIGKILL");
46638
+ killProcessGroup("SIGKILL");
46232
46639
  }
46233
- }, 5e3);
46640
+ }, GRACEFUL_KILL_WAIT_MS);
46234
46641
  }, effectiveTimeout);
46235
46642
  childProcess.stdout.on("data", (data) => {
46236
46643
  stdout += data.toString();
@@ -46244,8 +46651,28 @@ EXAMPLES:
46244
46651
  stderr = stderr.slice(-mergedConfig.maxOutputSize);
46245
46652
  }
46246
46653
  });
46247
- childProcess.on("close", (code, signal) => {
46654
+ let resolved = false;
46655
+ const safeResolve = (result) => {
46656
+ if (resolved) return;
46657
+ resolved = true;
46248
46658
  clearTimeout(timeoutId);
46659
+ clearTimeout(hardTimeoutId);
46660
+ resolve4(result);
46661
+ };
46662
+ const HARD_TIMEOUT_GRACE_MS = 5e3;
46663
+ const hardTimeoutId = setTimeout(() => {
46664
+ if (!resolved) {
46665
+ killProcessGroup("SIGKILL");
46666
+ safeResolve({
46667
+ success: false,
46668
+ stdout,
46669
+ stderr,
46670
+ duration: Date.now() - startTime,
46671
+ error: `Command timed out after ${effectiveTimeout}ms (hard timeout: process group did not exit)`
46672
+ });
46673
+ }
46674
+ }, effectiveTimeout + GRACEFUL_KILL_WAIT_MS + HARD_TIMEOUT_GRACE_MS);
46675
+ childProcess.on("close", (code, signal) => {
46249
46676
  const duration = Date.now() - startTime;
46250
46677
  let truncated = false;
46251
46678
  if (stdout.length > mergedConfig.maxOutputSize) {
@@ -46257,7 +46684,7 @@ EXAMPLES:
46257
46684
  truncated = true;
46258
46685
  }
46259
46686
  if (killed) {
46260
- resolve4({
46687
+ safeResolve({
46261
46688
  success: false,
46262
46689
  stdout,
46263
46690
  stderr,
@@ -46268,7 +46695,7 @@ EXAMPLES:
46268
46695
  error: `Command timed out after ${effectiveTimeout}ms`
46269
46696
  });
46270
46697
  } else {
46271
- resolve4({
46698
+ safeResolve({
46272
46699
  success: code === 0,
46273
46700
  stdout,
46274
46701
  stderr,
@@ -46281,8 +46708,7 @@ EXAMPLES:
46281
46708
  }
46282
46709
  });
46283
46710
  childProcess.on("error", (error) => {
46284
- clearTimeout(timeoutId);
46285
- resolve4({
46711
+ safeResolve({
46286
46712
  success: false,
46287
46713
  error: `Failed to execute command: ${error.message}`,
46288
46714
  duration: Date.now() - startTime
@@ -47548,8 +47974,8 @@ async function tryNative(args, startTime, attemptedMethods) {
47548
47974
  method: "native",
47549
47975
  title: result.title,
47550
47976
  content: cleanContent,
47551
- // Note: raw HTML not available with native method (returns markdown instead)
47552
- markdown: args.includeMarkdown ? cleanContent : void 0,
47977
+ // Native method already returns markdown-like content no separate markdown field needed
47978
+ // (would just duplicate content and waste tokens)
47553
47979
  qualityScore: result.qualityScore,
47554
47980
  durationMs: Date.now() - startTime,
47555
47981
  attemptedMethods,
@@ -47585,8 +48011,7 @@ async function tryJS(args, startTime, attemptedMethods) {
47585
48011
  method: "js",
47586
48012
  title: result.title,
47587
48013
  content: cleanContent,
47588
- // Note: raw HTML not available with JS method (returns markdown instead)
47589
- markdown: args.includeMarkdown ? cleanContent : void 0,
48014
+ // JS method already returns markdown-like content no separate markdown field needed
47590
48015
  qualityScore: result.success ? 80 : 0,
47591
48016
  durationMs: Date.now() - startTime,
47592
48017
  attemptedMethods,
@@ -47618,8 +48043,11 @@ async function tryAPI(connectorName, args, startTime, attemptedMethods) {
47618
48043
  includeLinks: args.includeLinks
47619
48044
  };
47620
48045
  const result = await provider.scrape(args.url, options);
47621
- const cleanContent = stripBase64DataUris(result.result?.content || "");
47622
- const cleanMarkdown = result.result?.markdown ? stripBase64DataUris(result.result.markdown) : void 0;
48046
+ const rawContent = result.result?.content || "";
48047
+ const rawMarkdown = result.result?.markdown;
48048
+ const cleanContent = stripBase64DataUris(rawContent);
48049
+ const cleanMarkdown = rawMarkdown ? stripBase64DataUris(rawMarkdown) : void 0;
48050
+ const isDuplicate = !!cleanMarkdown && cleanContent === cleanMarkdown;
47623
48051
  return {
47624
48052
  success: result.success,
47625
48053
  url: args.url,
@@ -47629,7 +48057,7 @@ async function tryAPI(connectorName, args, startTime, attemptedMethods) {
47629
48057
  content: cleanContent,
47630
48058
  html: result.result?.html,
47631
48059
  // Keep raw HTML as-is (only used if explicitly requested)
47632
- markdown: cleanMarkdown,
48060
+ markdown: isDuplicate ? void 0 : cleanMarkdown,
47633
48061
  metadata: result.result?.metadata,
47634
48062
  links: result.result?.links,
47635
48063
  qualityScore: result.success ? 90 : 0,
@@ -47844,68 +48272,25 @@ async function executeInVM(code, input, timeout, logs) {
47844
48272
  const result = await resultPromise;
47845
48273
  return result !== void 0 ? result : sandbox.output;
47846
48274
  }
47847
- var MIME_TYPES = {
47848
- png: "image/png",
47849
- jpeg: "image/jpeg",
47850
- jpg: "image/jpeg",
47851
- webp: "image/webp",
47852
- gif: "image/gif",
47853
- mp4: "video/mp4",
47854
- webm: "video/webm",
47855
- mp3: "audio/mpeg",
47856
- wav: "audio/wav",
47857
- opus: "audio/opus",
47858
- ogg: "audio/ogg",
47859
- aac: "audio/aac",
47860
- flac: "audio/flac",
47861
- pcm: "audio/pcm"
47862
- };
47863
- var FileMediaOutputHandler = class {
47864
- outputDir;
47865
- initialized = false;
47866
- constructor(outputDir) {
47867
- this.outputDir = outputDir ?? path3.join(os.tmpdir(), "oneringai-media");
47868
- }
47869
- async save(data, metadata) {
47870
- if (!this.initialized) {
47871
- await fs14.mkdir(this.outputDir, { recursive: true });
47872
- this.initialized = true;
47873
- }
47874
- const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
47875
- const filePath = path3.join(this.outputDir, filename);
47876
- await fs14.writeFile(filePath, data);
47877
- const format = metadata.format.toLowerCase();
47878
- const mimeType = MIME_TYPES[format] ?? `application/octet-stream`;
47879
- return {
47880
- location: filePath,
47881
- mimeType,
47882
- size: data.length
47883
- };
47884
- }
47885
- generateFilename(metadata) {
47886
- const timestamp = Date.now();
47887
- const random2 = crypto2.randomBytes(4).toString("hex");
47888
- const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
47889
- return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
47890
- }
47891
- };
47892
48275
 
47893
48276
  // src/tools/multimedia/config.ts
47894
- var _outputHandler = null;
47895
- function getMediaOutputHandler() {
47896
- if (!_outputHandler) {
47897
- _outputHandler = new FileMediaOutputHandler();
48277
+ var _storage = null;
48278
+ function getMediaStorage() {
48279
+ if (!_storage) {
48280
+ _storage = new FileMediaStorage();
47898
48281
  }
47899
- return _outputHandler;
48282
+ return _storage;
47900
48283
  }
47901
- function setMediaOutputHandler(handler) {
47902
- _outputHandler = handler;
48284
+ function setMediaStorage(storage) {
48285
+ _storage = storage;
47903
48286
  }
48287
+ var getMediaOutputHandler = getMediaStorage;
48288
+ var setMediaOutputHandler = setMediaStorage;
47904
48289
 
47905
48290
  // src/tools/multimedia/imageGeneration.ts
47906
- function createImageGenerationTool(connector, outputHandler) {
48291
+ function createImageGenerationTool(connector, storage, userId) {
47907
48292
  const vendor = connector.vendor;
47908
- const handler = outputHandler ?? getMediaOutputHandler();
48293
+ const handler = storage ?? getMediaStorage();
47909
48294
  const vendorModels = vendor ? getImageModelsByVendor(vendor) : [];
47910
48295
  const modelNames = vendorModels.map((m) => m.name);
47911
48296
  const properties = {
@@ -47978,8 +48363,9 @@ function createImageGenerationTool(connector, outputHandler) {
47978
48363
  }
47979
48364
  }
47980
48365
  },
47981
- execute: async (args) => {
48366
+ execute: async (args, context) => {
47982
48367
  try {
48368
+ const effectiveUserId = userId ?? context?.userId;
47983
48369
  const imageGen = ImageGeneration.create({ connector });
47984
48370
  const response = await imageGen.generate({
47985
48371
  prompt: args.prompt,
@@ -48010,7 +48396,8 @@ function createImageGenerationTool(connector, outputHandler) {
48010
48396
  format,
48011
48397
  model: modelName,
48012
48398
  vendor: vendor || "unknown",
48013
- index: response.data.length > 1 ? i : void 0
48399
+ index: response.data.length > 1 ? i : void 0,
48400
+ userId: effectiveUserId
48014
48401
  });
48015
48402
  images.push({
48016
48403
  location: result.location,
@@ -48037,9 +48424,9 @@ function createImageGenerationTool(connector, outputHandler) {
48037
48424
 
48038
48425
  // src/tools/multimedia/videoGeneration.ts
48039
48426
  var videoGenInstances = /* @__PURE__ */ new Map();
48040
- function createVideoTools(connector, outputHandler) {
48427
+ function createVideoTools(connector, storage, userId) {
48041
48428
  const vendor = connector.vendor;
48042
- const handler = outputHandler ?? getMediaOutputHandler();
48429
+ const handler = storage ?? getMediaStorage();
48043
48430
  const vendorModels = vendor ? getVideoModelsByVendor(vendor) : [];
48044
48431
  const modelNames = vendorModels.map((m) => m.name);
48045
48432
  const generateProperties = {
@@ -48103,7 +48490,7 @@ function createVideoTools(connector, outputHandler) {
48103
48490
  }
48104
48491
  }
48105
48492
  },
48106
- execute: async (args) => {
48493
+ execute: async (args, _context) => {
48107
48494
  try {
48108
48495
  const videoGen = VideoGeneration.create({ connector });
48109
48496
  const response = await videoGen.generate({
@@ -48152,8 +48539,9 @@ function createVideoTools(connector, outputHandler) {
48152
48539
  }
48153
48540
  }
48154
48541
  },
48155
- execute: async (args) => {
48542
+ execute: async (args, context) => {
48156
48543
  try {
48544
+ const effectiveUserId = userId ?? context?.userId;
48157
48545
  let videoGen = videoGenInstances.get(args.jobId);
48158
48546
  if (!videoGen) {
48159
48547
  videoGen = VideoGeneration.create({ connector });
@@ -48179,7 +48567,8 @@ function createVideoTools(connector, outputHandler) {
48179
48567
  type: "video",
48180
48568
  format,
48181
48569
  model: modelName,
48182
- vendor: vendor || "unknown"
48570
+ vendor: vendor || "unknown",
48571
+ userId: effectiveUserId
48183
48572
  });
48184
48573
  videoGenInstances.delete(args.jobId);
48185
48574
  return {
@@ -48227,9 +48616,9 @@ function createVideoTools(connector, outputHandler) {
48227
48616
  }
48228
48617
 
48229
48618
  // src/tools/multimedia/textToSpeech.ts
48230
- function createTextToSpeechTool(connector, outputHandler) {
48619
+ function createTextToSpeechTool(connector, storage, userId) {
48231
48620
  const vendor = connector.vendor;
48232
- const handler = outputHandler ?? getMediaOutputHandler();
48621
+ const handler = storage ?? getMediaStorage();
48233
48622
  const vendorModels = vendor ? getTTSModelsByVendor(vendor) : [];
48234
48623
  const modelNames = vendorModels.map((m) => m.name);
48235
48624
  const properties = {
@@ -48290,8 +48679,9 @@ function createTextToSpeechTool(connector, outputHandler) {
48290
48679
  }
48291
48680
  }
48292
48681
  },
48293
- execute: async (args) => {
48682
+ execute: async (args, context) => {
48294
48683
  try {
48684
+ const effectiveUserId = userId ?? context?.userId;
48295
48685
  const tts = TextToSpeech.create({
48296
48686
  connector,
48297
48687
  model: args.model,
@@ -48305,7 +48695,8 @@ function createTextToSpeechTool(connector, outputHandler) {
48305
48695
  type: "audio",
48306
48696
  format,
48307
48697
  model: args.model || modelNames[0] || "unknown",
48308
- vendor: vendor || "unknown"
48698
+ vendor: vendor || "unknown",
48699
+ userId: effectiveUserId
48309
48700
  });
48310
48701
  return {
48311
48702
  success: true,
@@ -48328,14 +48719,17 @@ function createTextToSpeechTool(connector, outputHandler) {
48328
48719
  }
48329
48720
  };
48330
48721
  }
48331
- function createSpeechToTextTool(connector) {
48722
+
48723
+ // src/tools/multimedia/speechToText.ts
48724
+ function createSpeechToTextTool(connector, storage, _userId) {
48332
48725
  const vendor = connector.vendor;
48726
+ const handler = storage ?? getMediaStorage();
48333
48727
  const vendorModels = vendor ? getSTTModelsByVendor(vendor) : [];
48334
48728
  const modelNames = vendorModels.map((m) => m.name);
48335
48729
  const properties = {
48336
- audioFilePath: {
48730
+ audioSource: {
48337
48731
  type: "string",
48338
- description: "Path to the audio file to transcribe"
48732
+ description: "Path or location of the audio file to transcribe (file path, storage location, etc.)"
48339
48733
  }
48340
48734
  };
48341
48735
  if (modelNames.length > 0) {
@@ -48363,13 +48757,19 @@ function createSpeechToTextTool(connector) {
48363
48757
  parameters: {
48364
48758
  type: "object",
48365
48759
  properties,
48366
- required: ["audioFilePath"]
48760
+ required: ["audioSource"]
48367
48761
  }
48368
48762
  }
48369
48763
  },
48370
- execute: async (args) => {
48764
+ execute: async (args, _context) => {
48371
48765
  try {
48372
- const audioBuffer = await fs14.readFile(args.audioFilePath);
48766
+ const audioBuffer = await handler.read(args.audioSource);
48767
+ if (!audioBuffer) {
48768
+ return {
48769
+ success: false,
48770
+ error: `Audio not found at: ${args.audioSource}`
48771
+ };
48772
+ }
48373
48773
  const stt = SpeechToText.create({
48374
48774
  connector,
48375
48775
  model: args.model,
@@ -48391,7 +48791,7 @@ function createSpeechToTextTool(connector) {
48391
48791
  };
48392
48792
  }
48393
48793
  },
48394
- describeCall: (args) => args.audioFilePath,
48794
+ describeCall: (args) => args.audioSource,
48395
48795
  permission: {
48396
48796
  scope: "session",
48397
48797
  riskLevel: "low",
@@ -48406,21 +48806,22 @@ var VENDOR_CAPABILITIES = {
48406
48806
  [Vendor.Google]: ["image", "video", "tts"],
48407
48807
  [Vendor.Grok]: ["image", "video"]
48408
48808
  };
48409
- function registerMultimediaTools() {
48809
+ function registerMultimediaTools(storage) {
48410
48810
  for (const [vendor, capabilities] of Object.entries(VENDOR_CAPABILITIES)) {
48411
- ConnectorTools.registerService(vendor, (connector, _userId) => {
48811
+ ConnectorTools.registerService(vendor, (connector, userId) => {
48812
+ const handler = getMediaStorage();
48412
48813
  const tools = [];
48413
48814
  if (capabilities.includes("image")) {
48414
- tools.push(createImageGenerationTool(connector));
48815
+ tools.push(createImageGenerationTool(connector, handler, userId));
48415
48816
  }
48416
48817
  if (capabilities.includes("video")) {
48417
- tools.push(...createVideoTools(connector));
48818
+ tools.push(...createVideoTools(connector, handler, userId));
48418
48819
  }
48419
48820
  if (capabilities.includes("tts")) {
48420
- tools.push(createTextToSpeechTool(connector));
48821
+ tools.push(createTextToSpeechTool(connector, handler, userId));
48421
48822
  }
48422
48823
  if (capabilities.includes("stt")) {
48423
- tools.push(createSpeechToTextTool(connector));
48824
+ tools.push(createSpeechToTextTool(connector, handler));
48424
48825
  }
48425
48826
  return tools;
48426
48827
  });
@@ -48430,6 +48831,851 @@ function registerMultimediaTools() {
48430
48831
  // src/tools/multimedia/index.ts
48431
48832
  registerMultimediaTools();
48432
48833
 
48834
+ // src/tools/github/types.ts
48835
+ function parseRepository(input) {
48836
+ if (!input || input.trim().length === 0) {
48837
+ throw new Error("Repository cannot be empty");
48838
+ }
48839
+ const trimmed = input.trim();
48840
+ try {
48841
+ const url2 = new URL(trimmed);
48842
+ if (url2.hostname === "github.com" || url2.hostname === "www.github.com") {
48843
+ const segments = url2.pathname.split("/").filter(Boolean);
48844
+ if (segments.length >= 2) {
48845
+ return { owner: segments[0], repo: segments[1].replace(/\.git$/, "") };
48846
+ }
48847
+ }
48848
+ } catch {
48849
+ }
48850
+ const parts = trimmed.split("/");
48851
+ if (parts.length === 2 && parts[0].length > 0 && parts[1].length > 0) {
48852
+ return { owner: parts[0], repo: parts[1] };
48853
+ }
48854
+ throw new Error(
48855
+ `Invalid repository format: "${input}". Expected "owner/repo" or "https://github.com/owner/repo"`
48856
+ );
48857
+ }
48858
+ function resolveRepository(repository, connector) {
48859
+ const repoStr = repository ?? connector.getOptions().defaultRepository;
48860
+ if (!repoStr) {
48861
+ return {
48862
+ success: false,
48863
+ error: 'No repository specified. Provide a "repository" parameter (e.g., "owner/repo") or configure defaultRepository on the connector.'
48864
+ };
48865
+ }
48866
+ try {
48867
+ return { success: true, repo: parseRepository(repoStr) };
48868
+ } catch (err) {
48869
+ return { success: false, error: err instanceof Error ? err.message : String(err) };
48870
+ }
48871
+ }
48872
+ var GitHubAPIError = class extends Error {
48873
+ constructor(status, statusText, body) {
48874
+ const msg = typeof body === "object" && body !== null && "message" in body ? body.message : statusText;
48875
+ super(`GitHub API error ${status}: ${msg}`);
48876
+ this.status = status;
48877
+ this.statusText = statusText;
48878
+ this.body = body;
48879
+ this.name = "GitHubAPIError";
48880
+ }
48881
+ };
48882
+ async function githubFetch(connector, endpoint, options) {
48883
+ let url2 = endpoint;
48884
+ if (options?.queryParams && Object.keys(options.queryParams).length > 0) {
48885
+ const params = new URLSearchParams();
48886
+ for (const [key, value] of Object.entries(options.queryParams)) {
48887
+ params.append(key, String(value));
48888
+ }
48889
+ url2 += (url2.includes("?") ? "&" : "?") + params.toString();
48890
+ }
48891
+ const headers = {
48892
+ "Accept": options?.accept ?? "application/vnd.github+json",
48893
+ "X-GitHub-Api-Version": "2022-11-28"
48894
+ };
48895
+ if (options?.body) {
48896
+ headers["Content-Type"] = "application/json";
48897
+ }
48898
+ const response = await connector.fetch(
48899
+ url2,
48900
+ {
48901
+ method: options?.method ?? "GET",
48902
+ headers,
48903
+ body: options?.body ? JSON.stringify(options.body) : void 0
48904
+ },
48905
+ options?.userId
48906
+ );
48907
+ const text = await response.text();
48908
+ let data;
48909
+ try {
48910
+ data = JSON.parse(text);
48911
+ } catch {
48912
+ data = text;
48913
+ }
48914
+ if (!response.ok) {
48915
+ throw new GitHubAPIError(response.status, response.statusText, data);
48916
+ }
48917
+ return data;
48918
+ }
48919
+
48920
+ // src/tools/github/searchFiles.ts
48921
+ function matchGlobPattern2(pattern, filePath) {
48922
+ let regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, ".").replace(/\{\{GLOBSTAR\}\}/g, ".*");
48923
+ regexPattern = "^" + regexPattern + "$";
48924
+ try {
48925
+ const regex = new RegExp(regexPattern);
48926
+ return regex.test(filePath);
48927
+ } catch {
48928
+ return false;
48929
+ }
48930
+ }
48931
+ function createSearchFilesTool(connector, userId) {
48932
+ return {
48933
+ definition: {
48934
+ type: "function",
48935
+ function: {
48936
+ name: "search_files",
48937
+ description: `Search for files by name/path pattern in a GitHub repository.
48938
+
48939
+ USAGE:
48940
+ - Supports glob patterns like "**/*.ts", "src/**/*.tsx"
48941
+ - Returns matching file paths sorted alphabetically
48942
+ - Uses the repository's file tree for fast matching
48943
+
48944
+ PATTERN SYNTAX:
48945
+ - * matches any characters except /
48946
+ - ** matches any characters including /
48947
+ - ? matches a single character
48948
+
48949
+ EXAMPLES:
48950
+ - Find all TypeScript files: { "pattern": "**/*.ts" }
48951
+ - Find files in src: { "pattern": "src/**/*.{ts,tsx}" }
48952
+ - Find package.json: { "pattern": "**/package.json" }
48953
+ - Search specific branch: { "pattern": "**/*.ts", "ref": "develop" }`,
48954
+ parameters: {
48955
+ type: "object",
48956
+ properties: {
48957
+ repository: {
48958
+ type: "string",
48959
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
48960
+ },
48961
+ pattern: {
48962
+ type: "string",
48963
+ description: 'Glob pattern to match files (e.g., "**/*.ts", "src/**/*.tsx")'
48964
+ },
48965
+ ref: {
48966
+ type: "string",
48967
+ description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
48968
+ }
48969
+ },
48970
+ required: ["pattern"]
48971
+ }
48972
+ }
48973
+ },
48974
+ describeCall: (args) => {
48975
+ const parts = [args.pattern];
48976
+ if (args.repository) parts.push(`in ${args.repository}`);
48977
+ if (args.ref) parts.push(`@${args.ref}`);
48978
+ return parts.join(" ");
48979
+ },
48980
+ permission: {
48981
+ scope: "session",
48982
+ riskLevel: "low",
48983
+ approvalMessage: `Search files in a GitHub repository via ${connector.displayName}`
48984
+ },
48985
+ execute: async (args) => {
48986
+ const resolved = resolveRepository(args.repository, connector);
48987
+ if (!resolved.success) {
48988
+ return { success: false, error: resolved.error };
48989
+ }
48990
+ const { owner, repo } = resolved.repo;
48991
+ try {
48992
+ let ref = args.ref;
48993
+ if (!ref) {
48994
+ const repoInfo = await githubFetch(
48995
+ connector,
48996
+ `/repos/${owner}/${repo}`,
48997
+ { userId }
48998
+ );
48999
+ ref = repoInfo.default_branch;
49000
+ }
49001
+ const tree = await githubFetch(
49002
+ connector,
49003
+ `/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`,
49004
+ { userId }
49005
+ );
49006
+ const matching = tree.tree.filter(
49007
+ (entry) => entry.type === "blob" && matchGlobPattern2(args.pattern, entry.path)
49008
+ ).map((entry) => ({
49009
+ path: entry.path,
49010
+ size: entry.size ?? 0,
49011
+ type: entry.type
49012
+ })).sort((a, b) => a.path.localeCompare(b.path));
49013
+ return {
49014
+ success: true,
49015
+ files: matching,
49016
+ count: matching.length,
49017
+ truncated: tree.truncated
49018
+ };
49019
+ } catch (error) {
49020
+ return {
49021
+ success: false,
49022
+ error: `Failed to search files: ${error instanceof Error ? error.message : String(error)}`
49023
+ };
49024
+ }
49025
+ }
49026
+ };
49027
+ }
49028
+
49029
+ // src/tools/github/searchCode.ts
49030
+ function createSearchCodeTool(connector, userId) {
49031
+ return {
49032
+ definition: {
49033
+ type: "function",
49034
+ function: {
49035
+ name: "search_code",
49036
+ description: `Search for code content across a GitHub repository.
49037
+
49038
+ USAGE:
49039
+ - Search by keyword, function name, class name, or any text
49040
+ - Filter by language, path, or file extension
49041
+ - Returns matching files with text fragments showing context
49042
+
49043
+ RATE LIMITS:
49044
+ - GitHub's code search API is limited to 30 requests per minute
49045
+ - Results may be incomplete for very large repositories
49046
+
49047
+ EXAMPLES:
49048
+ - Find function: { "query": "function handleAuth", "language": "typescript" }
49049
+ - Find imports: { "query": "import React", "extension": "tsx" }
49050
+ - Search in path: { "query": "TODO", "path": "src/utils" }
49051
+ - Limit results: { "query": "console.log", "limit": 10 }`,
49052
+ parameters: {
49053
+ type: "object",
49054
+ properties: {
49055
+ repository: {
49056
+ type: "string",
49057
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49058
+ },
49059
+ query: {
49060
+ type: "string",
49061
+ description: "Search query \u2014 keyword, function name, or any text to find in code"
49062
+ },
49063
+ language: {
49064
+ type: "string",
49065
+ description: 'Filter by programming language (e.g., "typescript", "python", "go")'
49066
+ },
49067
+ path: {
49068
+ type: "string",
49069
+ description: 'Filter by file path prefix (e.g., "src/", "lib/utils")'
49070
+ },
49071
+ extension: {
49072
+ type: "string",
49073
+ description: 'Filter by file extension without dot (e.g., "ts", "py", "go")'
49074
+ },
49075
+ limit: {
49076
+ type: "number",
49077
+ description: "Maximum number of results (default: 30, max: 100)"
49078
+ }
49079
+ },
49080
+ required: ["query"]
49081
+ }
49082
+ }
49083
+ },
49084
+ describeCall: (args) => {
49085
+ const parts = [`"${args.query}"`];
49086
+ if (args.language) parts.push(`lang:${args.language}`);
49087
+ if (args.repository) parts.push(`in ${args.repository}`);
49088
+ return parts.join(" ");
49089
+ },
49090
+ permission: {
49091
+ scope: "session",
49092
+ riskLevel: "low",
49093
+ approvalMessage: `Search code in a GitHub repository via ${connector.displayName}`
49094
+ },
49095
+ execute: async (args) => {
49096
+ const resolved = resolveRepository(args.repository, connector);
49097
+ if (!resolved.success) {
49098
+ return { success: false, error: resolved.error };
49099
+ }
49100
+ const { owner, repo } = resolved.repo;
49101
+ try {
49102
+ const qualifiers = [`repo:${owner}/${repo}`];
49103
+ if (args.language) qualifiers.push(`language:${args.language}`);
49104
+ if (args.path) qualifiers.push(`path:${args.path}`);
49105
+ if (args.extension) qualifiers.push(`extension:${args.extension}`);
49106
+ const q = `${args.query} ${qualifiers.join(" ")}`;
49107
+ const perPage = Math.min(args.limit ?? 30, 100);
49108
+ const result = await githubFetch(
49109
+ connector,
49110
+ `/search/code`,
49111
+ {
49112
+ userId,
49113
+ // Request text-match fragments
49114
+ accept: "application/vnd.github.text-match+json",
49115
+ queryParams: { q, per_page: perPage }
49116
+ }
49117
+ );
49118
+ const matches = result.items.map((item) => ({
49119
+ file: item.path,
49120
+ fragment: item.text_matches?.[0]?.fragment
49121
+ }));
49122
+ return {
49123
+ success: true,
49124
+ matches,
49125
+ count: result.total_count,
49126
+ truncated: result.incomplete_results || result.total_count > perPage
49127
+ };
49128
+ } catch (error) {
49129
+ return {
49130
+ success: false,
49131
+ error: `Failed to search code: ${error instanceof Error ? error.message : String(error)}`
49132
+ };
49133
+ }
49134
+ }
49135
+ };
49136
+ }
49137
+
49138
+ // src/tools/github/readFile.ts
49139
+ function createGitHubReadFileTool(connector, userId) {
49140
+ return {
49141
+ definition: {
49142
+ type: "function",
49143
+ function: {
49144
+ name: "read_file",
49145
+ description: `Read file content from a GitHub repository.
49146
+
49147
+ USAGE:
49148
+ - Reads a file and returns content with line numbers
49149
+ - Supports line range selection with offset/limit for large files
49150
+ - By default reads up to 2000 lines from the beginning
49151
+
49152
+ EXAMPLES:
49153
+ - Read entire file: { "path": "src/index.ts" }
49154
+ - Read specific branch: { "path": "README.md", "ref": "develop" }
49155
+ - Read lines 100-200: { "path": "src/app.ts", "offset": 100, "limit": 100 }
49156
+ - Specific repo: { "repository": "owner/repo", "path": "package.json" }
49157
+
49158
+ NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (>5MB) may be truncated.`,
49159
+ parameters: {
49160
+ type: "object",
49161
+ properties: {
49162
+ repository: {
49163
+ type: "string",
49164
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49165
+ },
49166
+ path: {
49167
+ type: "string",
49168
+ description: 'File path within the repository (e.g., "src/index.ts")'
49169
+ },
49170
+ ref: {
49171
+ type: "string",
49172
+ description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
49173
+ },
49174
+ offset: {
49175
+ type: "number",
49176
+ description: "Line number to start reading from (1-indexed). Only provide if the file is too large."
49177
+ },
49178
+ limit: {
49179
+ type: "number",
49180
+ description: "Number of lines to read (default: 2000). Only provide if the file is too large."
49181
+ }
49182
+ },
49183
+ required: ["path"]
49184
+ }
49185
+ }
49186
+ },
49187
+ describeCall: (args) => {
49188
+ const parts = [args.path];
49189
+ if (args.repository) parts.push(`in ${args.repository}`);
49190
+ if (args.ref) parts.push(`@${args.ref}`);
49191
+ if (args.offset && args.limit) parts.push(`[lines ${args.offset}-${args.offset + args.limit}]`);
49192
+ return parts.join(" ");
49193
+ },
49194
+ permission: {
49195
+ scope: "session",
49196
+ riskLevel: "low",
49197
+ approvalMessage: `Read a file from a GitHub repository via ${connector.displayName}`
49198
+ },
49199
+ execute: async (args) => {
49200
+ const resolved = resolveRepository(args.repository, connector);
49201
+ if (!resolved.success) {
49202
+ return { success: false, error: resolved.error };
49203
+ }
49204
+ const { owner, repo } = resolved.repo;
49205
+ try {
49206
+ let fileContent;
49207
+ let fileSha;
49208
+ let fileSize;
49209
+ const refParam = args.ref ? `?ref=${encodeURIComponent(args.ref)}` : "";
49210
+ const contentResp = await githubFetch(
49211
+ connector,
49212
+ `/repos/${owner}/${repo}/contents/${args.path}${refParam}`,
49213
+ { userId }
49214
+ );
49215
+ if (contentResp.type !== "file") {
49216
+ return {
49217
+ success: false,
49218
+ error: `Path is not a file: ${args.path} (type: ${contentResp.type}). Use search_files to explore the repository.`,
49219
+ path: args.path
49220
+ };
49221
+ }
49222
+ fileSha = contentResp.sha;
49223
+ fileSize = contentResp.size;
49224
+ if (contentResp.content && contentResp.encoding === "base64") {
49225
+ fileContent = Buffer.from(contentResp.content, "base64").toString("utf-8");
49226
+ } else if (contentResp.git_url) {
49227
+ const blob = await githubFetch(
49228
+ connector,
49229
+ contentResp.git_url,
49230
+ { userId }
49231
+ );
49232
+ fileContent = Buffer.from(blob.content, "base64").toString("utf-8");
49233
+ fileSize = blob.size;
49234
+ } else {
49235
+ return {
49236
+ success: false,
49237
+ error: `Cannot read file content: ${args.path} (no content or git_url in response)`,
49238
+ path: args.path
49239
+ };
49240
+ }
49241
+ const offset = args.offset ?? 1;
49242
+ const limit = args.limit ?? 2e3;
49243
+ const allLines = fileContent.split("\n");
49244
+ const totalLines = allLines.length;
49245
+ const startIndex = Math.max(0, offset - 1);
49246
+ const endIndex = Math.min(totalLines, startIndex + limit);
49247
+ const selectedLines = allLines.slice(startIndex, endIndex);
49248
+ const lineNumberWidth = String(endIndex).length;
49249
+ const formattedLines = selectedLines.map((line, i) => {
49250
+ const lineNum = startIndex + i + 1;
49251
+ const paddedNum = String(lineNum).padStart(lineNumberWidth, " ");
49252
+ const truncatedLine = line.length > 2e3 ? line.substring(0, 2e3) + "..." : line;
49253
+ return `${paddedNum} ${truncatedLine}`;
49254
+ });
49255
+ const truncated = endIndex < totalLines;
49256
+ const result = formattedLines.join("\n");
49257
+ return {
49258
+ success: true,
49259
+ content: result,
49260
+ path: args.path,
49261
+ size: fileSize,
49262
+ lines: totalLines,
49263
+ truncated,
49264
+ sha: fileSha
49265
+ };
49266
+ } catch (error) {
49267
+ return {
49268
+ success: false,
49269
+ error: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
49270
+ path: args.path
49271
+ };
49272
+ }
49273
+ }
49274
+ };
49275
+ }
49276
+
49277
+ // src/tools/github/getPR.ts
49278
+ function createGetPRTool(connector, userId) {
49279
+ return {
49280
+ definition: {
49281
+ type: "function",
49282
+ function: {
49283
+ name: "get_pr",
49284
+ description: `Get full details of a pull request from a GitHub repository.
49285
+
49286
+ Returns: title, description, state, author, labels, reviewers, merge status, branches, file stats, and more.
49287
+
49288
+ EXAMPLES:
49289
+ - Get PR: { "pull_number": 123 }
49290
+ - Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
49291
+ parameters: {
49292
+ type: "object",
49293
+ properties: {
49294
+ repository: {
49295
+ type: "string",
49296
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49297
+ },
49298
+ pull_number: {
49299
+ type: "number",
49300
+ description: "Pull request number"
49301
+ }
49302
+ },
49303
+ required: ["pull_number"]
49304
+ }
49305
+ }
49306
+ },
49307
+ describeCall: (args) => {
49308
+ const parts = [`#${args.pull_number}`];
49309
+ if (args.repository) parts.push(`in ${args.repository}`);
49310
+ return parts.join(" ");
49311
+ },
49312
+ permission: {
49313
+ scope: "session",
49314
+ riskLevel: "low",
49315
+ approvalMessage: `Get pull request details from GitHub via ${connector.displayName}`
49316
+ },
49317
+ execute: async (args) => {
49318
+ const resolved = resolveRepository(args.repository, connector);
49319
+ if (!resolved.success) {
49320
+ return { success: false, error: resolved.error };
49321
+ }
49322
+ const { owner, repo } = resolved.repo;
49323
+ try {
49324
+ const pr = await githubFetch(
49325
+ connector,
49326
+ `/repos/${owner}/${repo}/pulls/${args.pull_number}`,
49327
+ { userId }
49328
+ );
49329
+ return {
49330
+ success: true,
49331
+ data: {
49332
+ number: pr.number,
49333
+ title: pr.title,
49334
+ body: pr.body,
49335
+ state: pr.state,
49336
+ draft: pr.draft,
49337
+ author: pr.user.login,
49338
+ labels: pr.labels.map((l) => l.name),
49339
+ reviewers: pr.requested_reviewers.map((r) => r.login),
49340
+ mergeable: pr.mergeable,
49341
+ head: pr.head.ref,
49342
+ base: pr.base.ref,
49343
+ url: pr.html_url,
49344
+ created_at: pr.created_at,
49345
+ updated_at: pr.updated_at,
49346
+ additions: pr.additions,
49347
+ deletions: pr.deletions,
49348
+ changed_files: pr.changed_files
49349
+ }
49350
+ };
49351
+ } catch (error) {
49352
+ return {
49353
+ success: false,
49354
+ error: `Failed to get PR: ${error instanceof Error ? error.message : String(error)}`
49355
+ };
49356
+ }
49357
+ }
49358
+ };
49359
+ }
49360
+
49361
+ // src/tools/github/prFiles.ts
49362
+ function createPRFilesTool(connector, userId) {
49363
+ return {
49364
+ definition: {
49365
+ type: "function",
49366
+ function: {
49367
+ name: "pr_files",
49368
+ description: `Get the files changed in a pull request with diffs.
49369
+
49370
+ Returns: filename, status (added/modified/removed/renamed), additions, deletions, and patch (diff) content for each file.
49371
+
49372
+ EXAMPLES:
49373
+ - Get files: { "pull_number": 123 }
49374
+ - Specific repo: { "repository": "owner/repo", "pull_number": 456 }
49375
+
49376
+ NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent for binary files.`,
49377
+ parameters: {
49378
+ type: "object",
49379
+ properties: {
49380
+ repository: {
49381
+ type: "string",
49382
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49383
+ },
49384
+ pull_number: {
49385
+ type: "number",
49386
+ description: "Pull request number"
49387
+ }
49388
+ },
49389
+ required: ["pull_number"]
49390
+ }
49391
+ }
49392
+ },
49393
+ describeCall: (args) => {
49394
+ const parts = [`files for #${args.pull_number}`];
49395
+ if (args.repository) parts.push(`in ${args.repository}`);
49396
+ return parts.join(" ");
49397
+ },
49398
+ permission: {
49399
+ scope: "session",
49400
+ riskLevel: "low",
49401
+ approvalMessage: `Get PR changed files from GitHub via ${connector.displayName}`
49402
+ },
49403
+ execute: async (args) => {
49404
+ const resolved = resolveRepository(args.repository, connector);
49405
+ if (!resolved.success) {
49406
+ return { success: false, error: resolved.error };
49407
+ }
49408
+ const { owner, repo } = resolved.repo;
49409
+ try {
49410
+ const files = await githubFetch(
49411
+ connector,
49412
+ `/repos/${owner}/${repo}/pulls/${args.pull_number}/files`,
49413
+ {
49414
+ userId,
49415
+ queryParams: { per_page: 100 }
49416
+ }
49417
+ );
49418
+ return {
49419
+ success: true,
49420
+ files: files.map((f) => ({
49421
+ filename: f.filename,
49422
+ status: f.status,
49423
+ additions: f.additions,
49424
+ deletions: f.deletions,
49425
+ changes: f.changes,
49426
+ patch: f.patch
49427
+ })),
49428
+ count: files.length
49429
+ };
49430
+ } catch (error) {
49431
+ return {
49432
+ success: false,
49433
+ error: `Failed to get PR files: ${error instanceof Error ? error.message : String(error)}`
49434
+ };
49435
+ }
49436
+ }
49437
+ };
49438
+ }
49439
+
49440
+ // src/tools/github/prComments.ts
49441
+ function createPRCommentsTool(connector, userId) {
49442
+ return {
49443
+ definition: {
49444
+ type: "function",
49445
+ function: {
49446
+ name: "pr_comments",
49447
+ description: `Get all comments and reviews on a pull request.
49448
+
49449
+ Returns a unified list of:
49450
+ - **review_comment**: Line-level comments on specific code (includes file path and line number)
49451
+ - **review**: Full reviews (approve/request changes/comment)
49452
+ - **comment**: General comments on the PR (issue-level)
49453
+
49454
+ All entries are sorted by creation date (oldest first).
49455
+
49456
+ EXAMPLES:
49457
+ - Get comments: { "pull_number": 123 }
49458
+ - Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
49459
+ parameters: {
49460
+ type: "object",
49461
+ properties: {
49462
+ repository: {
49463
+ type: "string",
49464
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49465
+ },
49466
+ pull_number: {
49467
+ type: "number",
49468
+ description: "Pull request number"
49469
+ }
49470
+ },
49471
+ required: ["pull_number"]
49472
+ }
49473
+ }
49474
+ },
49475
+ describeCall: (args) => {
49476
+ const parts = [`comments for #${args.pull_number}`];
49477
+ if (args.repository) parts.push(`in ${args.repository}`);
49478
+ return parts.join(" ");
49479
+ },
49480
+ permission: {
49481
+ scope: "session",
49482
+ riskLevel: "low",
49483
+ approvalMessage: `Get PR comments and reviews from GitHub via ${connector.displayName}`
49484
+ },
49485
+ execute: async (args) => {
49486
+ const resolved = resolveRepository(args.repository, connector);
49487
+ if (!resolved.success) {
49488
+ return { success: false, error: resolved.error };
49489
+ }
49490
+ const { owner, repo } = resolved.repo;
49491
+ try {
49492
+ const basePath = `/repos/${owner}/${repo}`;
49493
+ const queryOpts = { userId, queryParams: { per_page: 100 } };
49494
+ const [reviewComments, reviews, issueComments] = await Promise.all([
49495
+ githubFetch(
49496
+ connector,
49497
+ `${basePath}/pulls/${args.pull_number}/comments`,
49498
+ queryOpts
49499
+ ),
49500
+ githubFetch(
49501
+ connector,
49502
+ `${basePath}/pulls/${args.pull_number}/reviews`,
49503
+ queryOpts
49504
+ ),
49505
+ githubFetch(
49506
+ connector,
49507
+ `${basePath}/issues/${args.pull_number}/comments`,
49508
+ queryOpts
49509
+ )
49510
+ ]);
49511
+ const allComments = [];
49512
+ for (const rc of reviewComments) {
49513
+ allComments.push({
49514
+ id: rc.id,
49515
+ type: "review_comment",
49516
+ author: rc.user.login,
49517
+ body: rc.body,
49518
+ created_at: rc.created_at,
49519
+ path: rc.path,
49520
+ line: rc.line ?? rc.original_line ?? void 0
49521
+ });
49522
+ }
49523
+ for (const r of reviews) {
49524
+ if (!r.body && r.state === "APPROVED") continue;
49525
+ allComments.push({
49526
+ id: r.id,
49527
+ type: "review",
49528
+ author: r.user.login,
49529
+ body: r.body || `[${r.state}]`,
49530
+ created_at: r.submitted_at,
49531
+ state: r.state
49532
+ });
49533
+ }
49534
+ for (const ic of issueComments) {
49535
+ allComments.push({
49536
+ id: ic.id,
49537
+ type: "comment",
49538
+ author: ic.user.login,
49539
+ body: ic.body,
49540
+ created_at: ic.created_at
49541
+ });
49542
+ }
49543
+ allComments.sort(
49544
+ (a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
49545
+ );
49546
+ return {
49547
+ success: true,
49548
+ comments: allComments,
49549
+ count: allComments.length
49550
+ };
49551
+ } catch (error) {
49552
+ return {
49553
+ success: false,
49554
+ error: `Failed to get PR comments: ${error instanceof Error ? error.message : String(error)}`
49555
+ };
49556
+ }
49557
+ }
49558
+ };
49559
+ }
49560
+
49561
+ // src/tools/github/createPR.ts
49562
+ function createCreatePRTool(connector, userId) {
49563
+ return {
49564
+ definition: {
49565
+ type: "function",
49566
+ function: {
49567
+ name: "create_pr",
49568
+ description: `Create a pull request on a GitHub repository.
49569
+
49570
+ USAGE:
49571
+ - Specify source branch (head) and target branch (base)
49572
+ - Optionally create as draft
49573
+
49574
+ EXAMPLES:
49575
+ - Create PR: { "title": "Add feature", "head": "feature-branch", "base": "main" }
49576
+ - Draft PR: { "title": "WIP: Refactor", "head": "refactor", "base": "develop", "draft": true }
49577
+ - With body: { "title": "Fix bug #42", "body": "Fixes the login issue\\n\\n## Changes\\n- Fixed auth flow", "head": "fix/42", "base": "main" }`,
49578
+ parameters: {
49579
+ type: "object",
49580
+ properties: {
49581
+ repository: {
49582
+ type: "string",
49583
+ description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
49584
+ },
49585
+ title: {
49586
+ type: "string",
49587
+ description: "Pull request title"
49588
+ },
49589
+ body: {
49590
+ type: "string",
49591
+ description: "Pull request description/body (Markdown supported)"
49592
+ },
49593
+ head: {
49594
+ type: "string",
49595
+ description: "Source branch name (the branch with your changes)"
49596
+ },
49597
+ base: {
49598
+ type: "string",
49599
+ description: 'Target branch name (the branch you want to merge into, e.g., "main")'
49600
+ },
49601
+ draft: {
49602
+ type: "boolean",
49603
+ description: "Create as a draft pull request (default: false)"
49604
+ }
49605
+ },
49606
+ required: ["title", "head", "base"]
49607
+ }
49608
+ }
49609
+ },
49610
+ describeCall: (args) => {
49611
+ const parts = [args.title];
49612
+ if (args.repository) parts.push(`in ${args.repository}`);
49613
+ return parts.join(" ");
49614
+ },
49615
+ permission: {
49616
+ scope: "session",
49617
+ riskLevel: "medium",
49618
+ approvalMessage: `Create a pull request on GitHub via ${connector.displayName}`
49619
+ },
49620
+ execute: async (args) => {
49621
+ const resolved = resolveRepository(args.repository, connector);
49622
+ if (!resolved.success) {
49623
+ return { success: false, error: resolved.error };
49624
+ }
49625
+ const { owner, repo } = resolved.repo;
49626
+ try {
49627
+ const pr = await githubFetch(
49628
+ connector,
49629
+ `/repos/${owner}/${repo}/pulls`,
49630
+ {
49631
+ method: "POST",
49632
+ userId,
49633
+ body: {
49634
+ title: args.title,
49635
+ body: args.body,
49636
+ head: args.head,
49637
+ base: args.base,
49638
+ draft: args.draft ?? false
49639
+ }
49640
+ }
49641
+ );
49642
+ return {
49643
+ success: true,
49644
+ data: {
49645
+ number: pr.number,
49646
+ url: pr.html_url,
49647
+ state: pr.state,
49648
+ title: pr.title
49649
+ }
49650
+ };
49651
+ } catch (error) {
49652
+ return {
49653
+ success: false,
49654
+ error: `Failed to create PR: ${error instanceof Error ? error.message : String(error)}`
49655
+ };
49656
+ }
49657
+ }
49658
+ };
49659
+ }
49660
+
49661
+ // src/tools/github/register.ts
49662
+ function registerGitHubTools() {
49663
+ ConnectorTools.registerService("github", (connector, userId) => {
49664
+ return [
49665
+ createSearchFilesTool(connector, userId),
49666
+ createSearchCodeTool(connector, userId),
49667
+ createGitHubReadFileTool(connector, userId),
49668
+ createGetPRTool(connector, userId),
49669
+ createPRFilesTool(connector, userId),
49670
+ createPRCommentsTool(connector, userId),
49671
+ createCreatePRTool(connector, userId)
49672
+ ];
49673
+ });
49674
+ }
49675
+
49676
+ // src/tools/github/index.ts
49677
+ registerGitHubTools();
49678
+
48433
49679
  // src/tools/registry.generated.ts
48434
49680
  var toolRegistry = [
48435
49681
  {
@@ -48483,7 +49729,7 @@ var toolRegistry = [
48483
49729
  displayName: "Read File",
48484
49730
  category: "filesystem",
48485
49731
  description: "Read content from a file on the local filesystem.",
48486
- tool: readFile4,
49732
+ tool: readFile5,
48487
49733
  safeByDefault: true
48488
49734
  },
48489
49735
  {
@@ -48492,7 +49738,7 @@ var toolRegistry = [
48492
49738
  displayName: "Write File",
48493
49739
  category: "filesystem",
48494
49740
  description: "Write content to a file on the local filesystem.",
48495
- tool: writeFile4,
49741
+ tool: writeFile5,
48496
49742
  safeByDefault: false
48497
49743
  },
48498
49744
  {
@@ -48721,8 +49967,8 @@ var ToolRegistry = class {
48721
49967
 
48722
49968
  // src/tools/index.ts
48723
49969
  var developerTools = [
48724
- readFile4,
48725
- writeFile4,
49970
+ readFile5,
49971
+ writeFile5,
48726
49972
  editFile,
48727
49973
  glob,
48728
49974
  grep,
@@ -48909,6 +50155,6 @@ REMEMBER: Keep it conversational, ask one question at a time, and only output th
48909
50155
  }
48910
50156
  };
48911
50157
 
48912
- export { AGENT_DEFINITION_FORMAT_VERSION, AIError, APPROVAL_STATE_VERSION, Agent, AgentContextNextGen, ApproximateTokenEstimator, BaseMediaProvider, BasePluginNextGen, BaseProvider, BaseTextProvider, BraveProvider, CONNECTOR_CONFIG_VERSION, CONTEXT_SESSION_FORMAT_VERSION, CheckpointManager, CircuitBreaker, CircuitOpenError, Connector, ConnectorConfigStore, ConnectorTools, ConsoleMetrics, ContentType, ContextOverflowError, DEFAULT_ALLOWLIST, DEFAULT_BACKOFF_CONFIG, DEFAULT_BASE_DELAY_MS, DEFAULT_CHECKPOINT_STRATEGY, DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_CONFIG2 as DEFAULT_CONFIG, DEFAULT_CONNECTOR_TIMEOUT, DEFAULT_CONTEXT_CONFIG, DEFAULT_FEATURES, DEFAULT_FILESYSTEM_CONFIG, DEFAULT_HISTORY_MANAGER_CONFIG, DEFAULT_MAX_DELAY_MS, DEFAULT_MAX_RETRIES, DEFAULT_MEMORY_CONFIG, DEFAULT_PERMISSION_CONFIG, DEFAULT_RATE_LIMITER_CONFIG, DEFAULT_RETRYABLE_STATUSES, DEFAULT_SHELL_CONFIG, DefaultCompactionStrategy, DependencyCycleError, ErrorHandler, ExecutionContext, ExternalDependencyHandler, FileAgentDefinitionStorage, FileConnectorStorage, FileContextStorage, FileMediaOutputHandler, FilePersistentInstructionsStorage, FileStorage, FrameworkLogger, HookManager, IMAGE_MODELS, IMAGE_MODEL_REGISTRY, ImageGeneration, InContextMemoryPluginNextGen, InMemoryAgentStateStorage, InMemoryHistoryStorage, InMemoryMetrics, InMemoryPlanStorage, InMemoryStorage, InvalidConfigError, InvalidToolArgumentsError, LLM_MODELS, LoggingPlugin, MCPClient, MCPConnectionError, MCPError, MCPProtocolError, MCPRegistry, MCPResourceError, MCPTimeoutError, MCPToolError, MEMORY_PRIORITY_VALUES, MODEL_REGISTRY, MemoryConnectorStorage, MemoryEvictionCompactor, MemoryStorage, MessageBuilder, MessageRole, ModelNotSupportedError, NoOpMetrics, OAuthManager, ParallelTasksError, PersistentInstructionsPluginNextGen, PlanningAgent, ProviderAuthError, ProviderConfigAgent, ProviderContextLengthError, ProviderError, ProviderErrorMapper, ProviderNotFoundError, ProviderRateLimitError, RapidAPIProvider, RateLimitError, SERVICE_DEFINITIONS, SERVICE_INFO, SERVICE_URL_PATTERNS, SIMPLE_ICONS_CDN, STT_MODELS, STT_MODEL_REGISTRY, ScopedConnectorRegistry, ScrapeProvider, SearchProvider, SerperProvider, Services, SpeechToText, StrategyRegistry, StreamEventType, StreamHelpers, StreamState, SummarizeCompactor, TERMINAL_TASK_STATUSES, TTS_MODELS, TTS_MODEL_REGISTRY, TaskTimeoutError, TaskValidationError, TavilyProvider, TextToSpeech, TokenBucketRateLimiter, ToolCallState, ToolExecutionError, ToolExecutionPipeline, ToolManager, ToolNotFoundError, ToolPermissionManager, ToolRegistry, ToolTimeoutError, TruncateCompactor, VENDORS, VENDOR_ICON_MAP, VIDEO_MODELS, VIDEO_MODEL_REGISTRY, Vendor, VideoGeneration, WorkingMemory, WorkingMemoryPluginNextGen, addJitter, allVendorTemplates, assertNotDestroyed, authenticatedFetch, backoffSequence, backoffWait, bash, buildAuthConfig, buildEndpointWithQuery, buildQueryString, calculateBackoff, calculateCost, calculateEntrySize, calculateImageCost, calculateSTTCost, calculateTTSCost, calculateVideoCost, canTaskExecute, createAgentStorage, createAuthenticatedFetch, createBashTool, createConnectorFromTemplate, createEditFileTool, createEstimator, createExecuteJavaScriptTool, createFileAgentDefinitionStorage, createFileContextStorage, createGlobTool, createGrepTool, createImageGenerationTool, createImageProvider, createListDirectoryTool, createMessageWithImages, createMetricsCollector, createPlan, createProvider, createReadFileTool, createSpeechToTextTool, createTask, createTextMessage, createTextToSpeechTool, createVideoProvider, createVideoTools, createWriteFileTool, defaultDescribeCall, detectDependencyCycle, detectServiceFromURL, developerTools, editFile, evaluateCondition, extractJSON, extractJSONField, extractNumber, findConnectorByServiceTypes, forPlan, forTasks, generateEncryptionKey, generateSimplePlan, generateWebAPITool, getActiveImageModels, getActiveModels, getActiveSTTModels, getActiveTTSModels, getActiveVideoModels, getAllBuiltInTools, getAllServiceIds, getAllVendorLogos, getAllVendorTemplates, getBackgroundOutput, getConnectorTools, getCredentialsSetupURL, getDocsURL, getImageModelInfo, getImageModelsByVendor, getImageModelsWithFeature, getMediaOutputHandler, getModelInfo, getModelsByVendor, getNextExecutableTasks, getRegisteredScrapeProviders, getSTTModelInfo, getSTTModelsByVendor, getSTTModelsWithFeature, getServiceDefinition, getServiceInfo, getServicesByCategory, getTTSModelInfo, getTTSModelsByVendor, getTTSModelsWithFeature, getTaskDependencies, getToolByName, getToolCallDescription, getToolCategories, getToolRegistry, getToolsByCategory, getToolsRequiringConnector, getVendorAuthTemplate, getVendorColor, getVendorInfo, getVendorLogo, getVendorLogoCdnUrl, getVendorLogoSvg, getVendorTemplate, getVideoModelInfo, getVideoModelsByVendor, getVideoModelsWithAudio, getVideoModelsWithFeature, glob, globalErrorHandler, grep, hasClipboardImage, hasVendorLogo, isBlockedCommand, isErrorEvent, isExcludedExtension, isKnownService, isOutputTextDelta, isResponseComplete, isSimpleScope, isStreamEvent, isTaskAwareScope, isTaskBlocked, isTerminalMemoryStatus, isTerminalStatus, isToolCallArgumentsDelta, isToolCallArgumentsDone, isToolCallStart, isVendor, killBackgroundProcess, listConnectorsByServiceTypes, listDirectory, listVendorIds, listVendors, listVendorsByAuthType, listVendorsByCategory, listVendorsWithLogos, logger, metrics, readClipboardImage, readFile4 as readFile, registerScrapeProvider, resolveConnector, resolveDependencies, retryWithBackoff, scopeEquals, scopeMatches, setMediaOutputHandler, setMetricsCollector, simpleTokenEstimator, toConnectorOptions, toolRegistry, tools_exports as tools, updateTaskStatus, validatePath, writeFile4 as writeFile };
50158
+ export { AGENT_DEFINITION_FORMAT_VERSION, AIError, APPROVAL_STATE_VERSION, Agent, AgentContextNextGen, ApproximateTokenEstimator, BaseMediaProvider, BasePluginNextGen, BaseProvider, BaseTextProvider, BraveProvider, CONNECTOR_CONFIG_VERSION, CONTEXT_SESSION_FORMAT_VERSION, CheckpointManager, CircuitBreaker, CircuitOpenError, Connector, ConnectorConfigStore, ConnectorTools, ConsoleMetrics, ContentType, ContextOverflowError, DEFAULT_ALLOWLIST, DEFAULT_BACKOFF_CONFIG, DEFAULT_BASE_DELAY_MS, DEFAULT_CHECKPOINT_STRATEGY, DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_CONFIG2 as DEFAULT_CONFIG, DEFAULT_CONNECTOR_TIMEOUT, DEFAULT_CONTEXT_CONFIG, DEFAULT_FEATURES, DEFAULT_FILESYSTEM_CONFIG, DEFAULT_HISTORY_MANAGER_CONFIG, DEFAULT_MAX_DELAY_MS, DEFAULT_MAX_RETRIES, DEFAULT_MEMORY_CONFIG, DEFAULT_PERMISSION_CONFIG, DEFAULT_RATE_LIMITER_CONFIG, DEFAULT_RETRYABLE_STATUSES, DEFAULT_SHELL_CONFIG, DefaultCompactionStrategy, DependencyCycleError, ErrorHandler, ExecutionContext, ExternalDependencyHandler, FileAgentDefinitionStorage, FileConnectorStorage, FileContextStorage, FileMediaStorage as FileMediaOutputHandler, FileMediaStorage, FilePersistentInstructionsStorage, FileStorage, FrameworkLogger, HookManager, IMAGE_MODELS, IMAGE_MODEL_REGISTRY, ImageGeneration, InContextMemoryPluginNextGen, InMemoryAgentStateStorage, InMemoryHistoryStorage, InMemoryMetrics, InMemoryPlanStorage, InMemoryStorage, InvalidConfigError, InvalidToolArgumentsError, LLM_MODELS, LoggingPlugin, MCPClient, MCPConnectionError, MCPError, MCPProtocolError, MCPRegistry, MCPResourceError, MCPTimeoutError, MCPToolError, MEMORY_PRIORITY_VALUES, MODEL_REGISTRY, MemoryConnectorStorage, MemoryEvictionCompactor, MemoryStorage, MessageBuilder, MessageRole, ModelNotSupportedError, NoOpMetrics, OAuthManager, ParallelTasksError, PersistentInstructionsPluginNextGen, PlanningAgent, ProviderAuthError, ProviderConfigAgent, ProviderContextLengthError, ProviderError, ProviderErrorMapper, ProviderNotFoundError, ProviderRateLimitError, RapidAPIProvider, RateLimitError, SERVICE_DEFINITIONS, SERVICE_INFO, SERVICE_URL_PATTERNS, SIMPLE_ICONS_CDN, STT_MODELS, STT_MODEL_REGISTRY, ScopedConnectorRegistry, ScrapeProvider, SearchProvider, SerperProvider, Services, SpeechToText, StrategyRegistry, StreamEventType, StreamHelpers, StreamState, SummarizeCompactor, TERMINAL_TASK_STATUSES, TTS_MODELS, TTS_MODEL_REGISTRY, TaskTimeoutError, TaskValidationError, TavilyProvider, TextToSpeech, TokenBucketRateLimiter, ToolCallState, ToolExecutionError, ToolExecutionPipeline, ToolManager, ToolNotFoundError, ToolPermissionManager, ToolRegistry, ToolTimeoutError, TruncateCompactor, VENDORS, VENDOR_ICON_MAP, VIDEO_MODELS, VIDEO_MODEL_REGISTRY, Vendor, VideoGeneration, WorkingMemory, WorkingMemoryPluginNextGen, addJitter, allVendorTemplates, assertNotDestroyed, authenticatedFetch, backoffSequence, backoffWait, bash, buildAuthConfig, buildEndpointWithQuery, buildQueryString, calculateBackoff, calculateCost, calculateEntrySize, calculateImageCost, calculateSTTCost, calculateTTSCost, calculateVideoCost, canTaskExecute, createAgentStorage, createAuthenticatedFetch, createBashTool, createConnectorFromTemplate, createCreatePRTool, createEditFileTool, createEstimator, createExecuteJavaScriptTool, createFileAgentDefinitionStorage, createFileContextStorage, createFileMediaStorage, createGetPRTool, createGitHubReadFileTool, createGlobTool, createGrepTool, createImageGenerationTool, createImageProvider, createListDirectoryTool, createMessageWithImages, createMetricsCollector, createPRCommentsTool, createPRFilesTool, createPlan, createProvider, createReadFileTool, createSearchCodeTool, createSearchFilesTool, createSpeechToTextTool, createTask, createTextMessage, createTextToSpeechTool, createVideoProvider, createVideoTools, createWriteFileTool, defaultDescribeCall, detectDependencyCycle, detectServiceFromURL, developerTools, editFile, evaluateCondition, extractJSON, extractJSONField, extractNumber, findConnectorByServiceTypes, forPlan, forTasks, generateEncryptionKey, generateSimplePlan, generateWebAPITool, getActiveImageModels, getActiveModels, getActiveSTTModels, getActiveTTSModels, getActiveVideoModels, getAllBuiltInTools, getAllServiceIds, getAllVendorLogos, getAllVendorTemplates, getBackgroundOutput, getConnectorTools, getCredentialsSetupURL, getDocsURL, getImageModelInfo, getImageModelsByVendor, getImageModelsWithFeature, getMediaOutputHandler, getMediaStorage, getModelInfo, getModelsByVendor, getNextExecutableTasks, getRegisteredScrapeProviders, getSTTModelInfo, getSTTModelsByVendor, getSTTModelsWithFeature, getServiceDefinition, getServiceInfo, getServicesByCategory, getTTSModelInfo, getTTSModelsByVendor, getTTSModelsWithFeature, getTaskDependencies, getToolByName, getToolCallDescription, getToolCategories, getToolRegistry, getToolsByCategory, getToolsRequiringConnector, getVendorAuthTemplate, getVendorColor, getVendorDefaultBaseURL, getVendorInfo, getVendorLogo, getVendorLogoCdnUrl, getVendorLogoSvg, getVendorTemplate, getVideoModelInfo, getVideoModelsByVendor, getVideoModelsWithAudio, getVideoModelsWithFeature, glob, globalErrorHandler, grep, hasClipboardImage, hasVendorLogo, isBlockedCommand, isErrorEvent, isExcludedExtension, isKnownService, isOutputTextDelta, isResponseComplete, isSimpleScope, isStreamEvent, isTaskAwareScope, isTaskBlocked, isTerminalMemoryStatus, isTerminalStatus, isToolCallArgumentsDelta, isToolCallArgumentsDone, isToolCallStart, isVendor, killBackgroundProcess, listConnectorsByServiceTypes, listDirectory, listVendorIds, listVendors, listVendorsByAuthType, listVendorsByCategory, listVendorsWithLogos, logger, metrics, parseRepository, readClipboardImage, readFile5 as readFile, registerScrapeProvider, resolveConnector, resolveDependencies, resolveRepository, retryWithBackoff, scopeEquals, scopeMatches, setMediaOutputHandler, setMediaStorage, setMetricsCollector, simpleTokenEstimator, toConnectorOptions, toolRegistry, tools_exports as tools, updateTaskStatus, validatePath, writeFile5 as writeFile };
48913
50159
  //# sourceMappingURL=index.js.map
48914
50160
  //# sourceMappingURL=index.js.map