@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/README.md +76 -43
- package/dist/{ImageModel-DtN780fU.d.cts → ImageModel-DSY7SNsq.d.cts} +11 -31
- package/dist/{ImageModel-BkAX5Rr5.d.ts → ImageModel-qNJHPh4q.d.ts} +11 -31
- package/dist/Vendor-DYh_bzwo.d.cts +31 -0
- package/dist/Vendor-DYh_bzwo.d.ts +31 -0
- package/dist/capabilities/agents/index.d.cts +1 -1
- package/dist/capabilities/agents/index.d.ts +1 -1
- package/dist/capabilities/images/index.d.cts +2 -1
- package/dist/capabilities/images/index.d.ts +2 -1
- package/dist/{index-BmOYeqU7.d.ts → index-CEp1H4fV.d.ts} +2 -0
- package/dist/{index-DCzFlLoN.d.cts → index-NOV01LWF.d.cts} +2 -0
- package/dist/index.cjs +1706 -446
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +671 -376
- package/dist/index.d.ts +671 -376
- package/dist/index.js +1590 -344
- package/dist/index.js.map +1 -1
- package/dist/shared/index.cjs +1780 -0
- package/dist/shared/index.cjs.map +1 -0
- package/dist/shared/index.d.cts +266 -0
- package/dist/shared/index.d.ts +266 -0
- package/dist/shared/index.js +1760 -0
- package/dist/shared/index.js.map +1 -0
- package/package.json +7 -2
package/dist/index.cjs
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
var crypto2 = require('crypto');
|
|
4
4
|
var jose = require('jose');
|
|
5
|
-
var
|
|
5
|
+
var fs16 = require('fs');
|
|
6
6
|
var eventemitter3 = require('eventemitter3');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
7
|
+
var path2 = require('path');
|
|
8
|
+
var os2 = require('os');
|
|
9
|
+
var OpenAI3 = require('openai');
|
|
10
10
|
var Anthropic = require('@anthropic-ai/sdk');
|
|
11
11
|
var genai = require('@google/genai');
|
|
12
12
|
require('zod/v3');
|
|
@@ -14,7 +14,7 @@ var z4mini = require('zod/v4-mini');
|
|
|
14
14
|
var z = require('zod/v4');
|
|
15
15
|
var process2 = require('process');
|
|
16
16
|
var stream = require('stream');
|
|
17
|
-
var
|
|
17
|
+
var fs15 = require('fs/promises');
|
|
18
18
|
var simpleIcons = require('simple-icons');
|
|
19
19
|
var child_process = require('child_process');
|
|
20
20
|
var util = require('util');
|
|
@@ -44,15 +44,15 @@ function _interopNamespace(e) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
|
|
47
|
-
var
|
|
48
|
-
var
|
|
49
|
-
var
|
|
50
|
-
var
|
|
47
|
+
var fs16__namespace = /*#__PURE__*/_interopNamespace(fs16);
|
|
48
|
+
var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
|
|
49
|
+
var os2__namespace = /*#__PURE__*/_interopNamespace(os2);
|
|
50
|
+
var OpenAI3__default = /*#__PURE__*/_interopDefault(OpenAI3);
|
|
51
51
|
var Anthropic__default = /*#__PURE__*/_interopDefault(Anthropic);
|
|
52
52
|
var z4mini__namespace = /*#__PURE__*/_interopNamespace(z4mini);
|
|
53
53
|
var z__namespace = /*#__PURE__*/_interopNamespace(z);
|
|
54
54
|
var process2__default = /*#__PURE__*/_interopDefault(process2);
|
|
55
|
-
var
|
|
55
|
+
var fs15__namespace = /*#__PURE__*/_interopNamespace(fs15);
|
|
56
56
|
var simpleIcons__namespace = /*#__PURE__*/_interopNamespace(simpleIcons);
|
|
57
57
|
var TurndownService__default = /*#__PURE__*/_interopDefault(TurndownService);
|
|
58
58
|
var vm__namespace = /*#__PURE__*/_interopNamespace(vm);
|
|
@@ -631,7 +631,7 @@ var init_JWTBearer = __esm({
|
|
|
631
631
|
this.privateKey = config.privateKey;
|
|
632
632
|
} else if (config.privateKeyPath) {
|
|
633
633
|
try {
|
|
634
|
-
this.privateKey =
|
|
634
|
+
this.privateKey = fs16__namespace.readFileSync(config.privateKeyPath, "utf8");
|
|
635
635
|
} catch (error) {
|
|
636
636
|
throw new Error(`Failed to read private key from ${config.privateKeyPath}: ${error.message}`);
|
|
637
637
|
}
|
|
@@ -1281,11 +1281,11 @@ var init_Logger = __esm({
|
|
|
1281
1281
|
*/
|
|
1282
1282
|
initFileStream(filePath) {
|
|
1283
1283
|
try {
|
|
1284
|
-
const dir =
|
|
1285
|
-
if (!
|
|
1286
|
-
|
|
1284
|
+
const dir = path2__namespace.dirname(filePath);
|
|
1285
|
+
if (!fs16__namespace.existsSync(dir)) {
|
|
1286
|
+
fs16__namespace.mkdirSync(dir, { recursive: true });
|
|
1287
1287
|
}
|
|
1288
|
-
this.fileStream =
|
|
1288
|
+
this.fileStream = fs16__namespace.createWriteStream(filePath, {
|
|
1289
1289
|
flags: "a",
|
|
1290
1290
|
// append mode
|
|
1291
1291
|
encoding: "utf8"
|
|
@@ -14555,12 +14555,12 @@ var require_dist = __commonJS({
|
|
|
14555
14555
|
throw new Error(`Unknown format "${name}"`);
|
|
14556
14556
|
return f;
|
|
14557
14557
|
};
|
|
14558
|
-
function addFormats(ajv, list,
|
|
14558
|
+
function addFormats(ajv, list, fs17, exportName) {
|
|
14559
14559
|
var _a;
|
|
14560
14560
|
var _b;
|
|
14561
14561
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
14562
14562
|
for (const f of list)
|
|
14563
|
-
ajv.addFormat(f,
|
|
14563
|
+
ajv.addFormat(f, fs17[f]);
|
|
14564
14564
|
}
|
|
14565
14565
|
module.exports = exports$1 = formatsPlugin;
|
|
14566
14566
|
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
@@ -14573,7 +14573,7 @@ var require_windows = __commonJS({
|
|
|
14573
14573
|
"node_modules/isexe/windows.js"(exports$1, module) {
|
|
14574
14574
|
module.exports = isexe;
|
|
14575
14575
|
isexe.sync = sync;
|
|
14576
|
-
var
|
|
14576
|
+
var fs17 = __require("fs");
|
|
14577
14577
|
function checkPathExt(path6, options) {
|
|
14578
14578
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
14579
14579
|
if (!pathext) {
|
|
@@ -14591,19 +14591,19 @@ var require_windows = __commonJS({
|
|
|
14591
14591
|
}
|
|
14592
14592
|
return false;
|
|
14593
14593
|
}
|
|
14594
|
-
function checkStat(
|
|
14595
|
-
if (!
|
|
14594
|
+
function checkStat(stat6, path6, options) {
|
|
14595
|
+
if (!stat6.isSymbolicLink() && !stat6.isFile()) {
|
|
14596
14596
|
return false;
|
|
14597
14597
|
}
|
|
14598
14598
|
return checkPathExt(path6, options);
|
|
14599
14599
|
}
|
|
14600
14600
|
function isexe(path6, options, cb) {
|
|
14601
|
-
|
|
14602
|
-
cb(er, er ? false : checkStat(
|
|
14601
|
+
fs17.stat(path6, function(er, stat6) {
|
|
14602
|
+
cb(er, er ? false : checkStat(stat6, path6, options));
|
|
14603
14603
|
});
|
|
14604
14604
|
}
|
|
14605
14605
|
function sync(path6, options) {
|
|
14606
|
-
return checkStat(
|
|
14606
|
+
return checkStat(fs17.statSync(path6), path6, options);
|
|
14607
14607
|
}
|
|
14608
14608
|
}
|
|
14609
14609
|
});
|
|
@@ -14613,22 +14613,22 @@ var require_mode = __commonJS({
|
|
|
14613
14613
|
"node_modules/isexe/mode.js"(exports$1, module) {
|
|
14614
14614
|
module.exports = isexe;
|
|
14615
14615
|
isexe.sync = sync;
|
|
14616
|
-
var
|
|
14616
|
+
var fs17 = __require("fs");
|
|
14617
14617
|
function isexe(path6, options, cb) {
|
|
14618
|
-
|
|
14619
|
-
cb(er, er ? false : checkStat(
|
|
14618
|
+
fs17.stat(path6, function(er, stat6) {
|
|
14619
|
+
cb(er, er ? false : checkStat(stat6, options));
|
|
14620
14620
|
});
|
|
14621
14621
|
}
|
|
14622
14622
|
function sync(path6, options) {
|
|
14623
|
-
return checkStat(
|
|
14623
|
+
return checkStat(fs17.statSync(path6), options);
|
|
14624
14624
|
}
|
|
14625
|
-
function checkStat(
|
|
14626
|
-
return
|
|
14625
|
+
function checkStat(stat6, options) {
|
|
14626
|
+
return stat6.isFile() && checkMode(stat6, options);
|
|
14627
14627
|
}
|
|
14628
|
-
function checkMode(
|
|
14629
|
-
var mod =
|
|
14630
|
-
var uid =
|
|
14631
|
-
var gid =
|
|
14628
|
+
function checkMode(stat6, options) {
|
|
14629
|
+
var mod = stat6.mode;
|
|
14630
|
+
var uid = stat6.uid;
|
|
14631
|
+
var gid = stat6.gid;
|
|
14632
14632
|
var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
|
|
14633
14633
|
var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
|
|
14634
14634
|
var u = parseInt("100", 8);
|
|
@@ -14902,16 +14902,16 @@ var require_shebang_command = __commonJS({
|
|
|
14902
14902
|
// node_modules/cross-spawn/lib/util/readShebang.js
|
|
14903
14903
|
var require_readShebang = __commonJS({
|
|
14904
14904
|
"node_modules/cross-spawn/lib/util/readShebang.js"(exports$1, module) {
|
|
14905
|
-
var
|
|
14905
|
+
var fs17 = __require("fs");
|
|
14906
14906
|
var shebangCommand = require_shebang_command();
|
|
14907
14907
|
function readShebang(command) {
|
|
14908
14908
|
const size = 150;
|
|
14909
14909
|
const buffer = Buffer.alloc(size);
|
|
14910
14910
|
let fd;
|
|
14911
14911
|
try {
|
|
14912
|
-
fd =
|
|
14913
|
-
|
|
14914
|
-
|
|
14912
|
+
fd = fs17.openSync(command, "r");
|
|
14913
|
+
fs17.readSync(fd, buffer, 0, size, 0);
|
|
14914
|
+
fs17.closeSync(fd);
|
|
14915
14915
|
} catch (e) {
|
|
14916
14916
|
}
|
|
14917
14917
|
return shebangCommand(buffer.toString());
|
|
@@ -15089,8 +15089,8 @@ var DEFAULT_ALLOWLIST = [
|
|
|
15089
15089
|
"context_list",
|
|
15090
15090
|
// Persistent instructions tools
|
|
15091
15091
|
"instructions_set",
|
|
15092
|
-
"
|
|
15093
|
-
"
|
|
15092
|
+
"instructions_remove",
|
|
15093
|
+
"instructions_list",
|
|
15094
15094
|
"instructions_clear",
|
|
15095
15095
|
// Meta-tools (internal coordination)
|
|
15096
15096
|
"_start_planning",
|
|
@@ -16020,13 +16020,26 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16020
16020
|
pipeline;
|
|
16021
16021
|
/** Optional tool context for execution (set by agent before runs) */
|
|
16022
16022
|
_toolContext;
|
|
16023
|
-
|
|
16023
|
+
/** Hard timeout for tool execution (0 = disabled) */
|
|
16024
|
+
_toolExecutionTimeout;
|
|
16025
|
+
constructor(config) {
|
|
16024
16026
|
super();
|
|
16027
|
+
this._toolExecutionTimeout = config?.toolExecutionTimeout ?? 0;
|
|
16025
16028
|
this.namespaceIndex.set("default", /* @__PURE__ */ new Set());
|
|
16026
16029
|
this.toolLogger = exports.logger.child({ component: "ToolManager" });
|
|
16027
16030
|
this.pipeline = new ToolExecutionPipeline();
|
|
16028
16031
|
this.pipeline.use(new ResultNormalizerPlugin());
|
|
16029
16032
|
}
|
|
16033
|
+
/**
|
|
16034
|
+
* Get or set the hard tool execution timeout in milliseconds.
|
|
16035
|
+
* 0 = disabled (relies on tool's own timeout).
|
|
16036
|
+
*/
|
|
16037
|
+
get toolExecutionTimeout() {
|
|
16038
|
+
return this._toolExecutionTimeout;
|
|
16039
|
+
}
|
|
16040
|
+
set toolExecutionTimeout(value) {
|
|
16041
|
+
this._toolExecutionTimeout = Math.max(0, value);
|
|
16042
|
+
}
|
|
16030
16043
|
/**
|
|
16031
16044
|
* Access the execution pipeline for plugin management.
|
|
16032
16045
|
*
|
|
@@ -16524,7 +16537,7 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16524
16537
|
const startTime = Date.now();
|
|
16525
16538
|
exports.metrics.increment("tool.executed", 1, { tool: toolName });
|
|
16526
16539
|
try {
|
|
16527
|
-
const
|
|
16540
|
+
const executionPromise = breaker.execute(async () => {
|
|
16528
16541
|
const toolWithContext = {
|
|
16529
16542
|
...registration.tool,
|
|
16530
16543
|
execute: async (pipelineArgs) => {
|
|
@@ -16533,6 +16546,7 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16533
16546
|
};
|
|
16534
16547
|
return await this.pipeline.execute(toolWithContext, args);
|
|
16535
16548
|
});
|
|
16549
|
+
const result = this._toolExecutionTimeout > 0 ? await this.withHardTimeout(executionPromise, toolName, this._toolExecutionTimeout) : await executionPromise;
|
|
16536
16550
|
const duration = Date.now() - startTime;
|
|
16537
16551
|
this.recordExecution(toolName, duration, true);
|
|
16538
16552
|
const resultSummary = this.summarizeResult(result);
|
|
@@ -16595,6 +16609,29 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16595
16609
|
return this.list();
|
|
16596
16610
|
}
|
|
16597
16611
|
// ==========================================================================
|
|
16612
|
+
// Hard Timeout
|
|
16613
|
+
// ==========================================================================
|
|
16614
|
+
/**
|
|
16615
|
+
* Wrap a promise with a hard timeout safety net.
|
|
16616
|
+
* If the promise doesn't resolve within the timeout, throws ToolExecutionError.
|
|
16617
|
+
*/
|
|
16618
|
+
async withHardTimeout(promise, toolName, timeoutMs) {
|
|
16619
|
+
let timeoutId;
|
|
16620
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
16621
|
+
timeoutId = setTimeout(() => {
|
|
16622
|
+
reject(new ToolExecutionError(
|
|
16623
|
+
toolName,
|
|
16624
|
+
`Tool execution hard timeout after ${timeoutMs}ms (safety net - tool's own timeout may have failed)`
|
|
16625
|
+
));
|
|
16626
|
+
}, timeoutMs);
|
|
16627
|
+
});
|
|
16628
|
+
try {
|
|
16629
|
+
return await Promise.race([promise, timeoutPromise]);
|
|
16630
|
+
} finally {
|
|
16631
|
+
clearTimeout(timeoutId);
|
|
16632
|
+
}
|
|
16633
|
+
}
|
|
16634
|
+
// ==========================================================================
|
|
16598
16635
|
// Circuit Breaker Management
|
|
16599
16636
|
// ==========================================================================
|
|
16600
16637
|
/**
|
|
@@ -19653,10 +19690,10 @@ function getDefaultBaseDirectory() {
|
|
|
19653
19690
|
if (platform2 === "win32") {
|
|
19654
19691
|
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
19655
19692
|
if (appData) {
|
|
19656
|
-
return
|
|
19693
|
+
return path2.join(appData, "oneringai", "agents");
|
|
19657
19694
|
}
|
|
19658
19695
|
}
|
|
19659
|
-
return
|
|
19696
|
+
return path2.join(os2.homedir(), ".oneringai", "agents");
|
|
19660
19697
|
}
|
|
19661
19698
|
function sanitizeAgentId(agentId) {
|
|
19662
19699
|
return agentId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
|
|
@@ -19664,22 +19701,45 @@ function sanitizeAgentId(agentId) {
|
|
|
19664
19701
|
var FilePersistentInstructionsStorage = class {
|
|
19665
19702
|
directory;
|
|
19666
19703
|
filePath;
|
|
19704
|
+
legacyFilePath;
|
|
19667
19705
|
agentId;
|
|
19668
19706
|
constructor(config) {
|
|
19669
19707
|
this.agentId = config.agentId;
|
|
19670
19708
|
const sanitizedId = sanitizeAgentId(config.agentId);
|
|
19671
19709
|
const baseDir = config.baseDirectory ?? getDefaultBaseDirectory();
|
|
19672
|
-
const filename = config.filename ?? "custom_instructions.
|
|
19673
|
-
this.directory =
|
|
19674
|
-
this.filePath =
|
|
19710
|
+
const filename = config.filename ?? "custom_instructions.json";
|
|
19711
|
+
this.directory = path2.join(baseDir, sanitizedId);
|
|
19712
|
+
this.filePath = path2.join(this.directory, filename);
|
|
19713
|
+
this.legacyFilePath = path2.join(this.directory, "custom_instructions.md");
|
|
19675
19714
|
}
|
|
19676
19715
|
/**
|
|
19677
|
-
* Load
|
|
19716
|
+
* Load instruction entries from file.
|
|
19717
|
+
* Falls back to legacy .md file migration if JSON not found.
|
|
19678
19718
|
*/
|
|
19679
19719
|
async load() {
|
|
19680
19720
|
try {
|
|
19681
|
-
const
|
|
19682
|
-
|
|
19721
|
+
const raw = await fs16.promises.readFile(this.filePath, "utf-8");
|
|
19722
|
+
const data = JSON.parse(raw);
|
|
19723
|
+
if (data.version === 2 && Array.isArray(data.entries)) {
|
|
19724
|
+
return data.entries.length > 0 ? data.entries : null;
|
|
19725
|
+
}
|
|
19726
|
+
return null;
|
|
19727
|
+
} catch (error) {
|
|
19728
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
|
|
19729
|
+
throw error;
|
|
19730
|
+
}
|
|
19731
|
+
}
|
|
19732
|
+
try {
|
|
19733
|
+
const content = await fs16.promises.readFile(this.legacyFilePath, "utf-8");
|
|
19734
|
+
const trimmed = content.trim();
|
|
19735
|
+
if (!trimmed) return null;
|
|
19736
|
+
const now = Date.now();
|
|
19737
|
+
return [{
|
|
19738
|
+
id: "legacy_instructions",
|
|
19739
|
+
content: trimmed,
|
|
19740
|
+
createdAt: now,
|
|
19741
|
+
updatedAt: now
|
|
19742
|
+
}];
|
|
19683
19743
|
} catch (error) {
|
|
19684
19744
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
19685
19745
|
return null;
|
|
@@ -19688,44 +19748,56 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19688
19748
|
}
|
|
19689
19749
|
}
|
|
19690
19750
|
/**
|
|
19691
|
-
* Save
|
|
19692
|
-
* Creates directory if it doesn't exist
|
|
19751
|
+
* Save instruction entries to file as JSON.
|
|
19752
|
+
* Creates directory if it doesn't exist.
|
|
19753
|
+
* Cleans up legacy .md file if present.
|
|
19693
19754
|
*/
|
|
19694
|
-
async save(
|
|
19755
|
+
async save(entries) {
|
|
19695
19756
|
await this.ensureDirectory();
|
|
19757
|
+
const data = {
|
|
19758
|
+
version: 2,
|
|
19759
|
+
entries
|
|
19760
|
+
};
|
|
19696
19761
|
const tempPath = `${this.filePath}.tmp`;
|
|
19697
19762
|
try {
|
|
19698
|
-
await
|
|
19699
|
-
await
|
|
19763
|
+
await fs16.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
|
|
19764
|
+
await fs16.promises.rename(tempPath, this.filePath);
|
|
19700
19765
|
} catch (error) {
|
|
19701
19766
|
try {
|
|
19702
|
-
await
|
|
19767
|
+
await fs16.promises.unlink(tempPath);
|
|
19703
19768
|
} catch {
|
|
19704
19769
|
}
|
|
19705
19770
|
throw error;
|
|
19706
19771
|
}
|
|
19772
|
+
await this.removeLegacyFile();
|
|
19707
19773
|
}
|
|
19708
19774
|
/**
|
|
19709
|
-
* Delete instructions file
|
|
19775
|
+
* Delete instructions file (and legacy .md if exists)
|
|
19710
19776
|
*/
|
|
19711
19777
|
async delete() {
|
|
19712
19778
|
try {
|
|
19713
|
-
await
|
|
19779
|
+
await fs16.promises.unlink(this.filePath);
|
|
19714
19780
|
} catch (error) {
|
|
19715
19781
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
19716
19782
|
throw error;
|
|
19717
19783
|
}
|
|
19718
19784
|
}
|
|
19785
|
+
await this.removeLegacyFile();
|
|
19719
19786
|
}
|
|
19720
19787
|
/**
|
|
19721
|
-
* Check if instructions file exists
|
|
19788
|
+
* Check if instructions file exists (JSON or legacy .md)
|
|
19722
19789
|
*/
|
|
19723
19790
|
async exists() {
|
|
19724
19791
|
try {
|
|
19725
|
-
await
|
|
19792
|
+
await fs16.promises.access(this.filePath);
|
|
19726
19793
|
return true;
|
|
19727
19794
|
} catch {
|
|
19728
|
-
|
|
19795
|
+
try {
|
|
19796
|
+
await fs16.promises.access(this.legacyFilePath);
|
|
19797
|
+
return true;
|
|
19798
|
+
} catch {
|
|
19799
|
+
return false;
|
|
19800
|
+
}
|
|
19729
19801
|
}
|
|
19730
19802
|
}
|
|
19731
19803
|
/**
|
|
@@ -19745,65 +19817,86 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19745
19817
|
*/
|
|
19746
19818
|
async ensureDirectory() {
|
|
19747
19819
|
try {
|
|
19748
|
-
await
|
|
19820
|
+
await fs16.promises.mkdir(this.directory, { recursive: true });
|
|
19749
19821
|
} catch (error) {
|
|
19750
19822
|
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
19751
19823
|
throw error;
|
|
19752
19824
|
}
|
|
19753
19825
|
}
|
|
19754
19826
|
}
|
|
19827
|
+
/**
|
|
19828
|
+
* Remove legacy .md file if it exists
|
|
19829
|
+
*/
|
|
19830
|
+
async removeLegacyFile() {
|
|
19831
|
+
try {
|
|
19832
|
+
await fs16.promises.unlink(this.legacyFilePath);
|
|
19833
|
+
} catch (error) {
|
|
19834
|
+
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
19835
|
+
console.warn(`Failed to remove legacy instructions file: ${this.legacyFilePath}`);
|
|
19836
|
+
}
|
|
19837
|
+
}
|
|
19838
|
+
}
|
|
19755
19839
|
};
|
|
19756
19840
|
|
|
19757
19841
|
// src/core/context-nextgen/plugins/PersistentInstructionsPluginNextGen.ts
|
|
19758
|
-
var
|
|
19842
|
+
var DEFAULT_MAX_TOTAL_LENGTH = 5e4;
|
|
19843
|
+
var DEFAULT_MAX_ENTRIES = 50;
|
|
19844
|
+
var KEY_MAX_LENGTH = 100;
|
|
19845
|
+
var KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
19759
19846
|
var PERSISTENT_INSTRUCTIONS_INSTRUCTIONS = `Persistent Instructions are stored on disk and survive across sessions.
|
|
19847
|
+
Each instruction is a keyed entry that can be independently managed.
|
|
19760
19848
|
|
|
19761
19849
|
**To modify:**
|
|
19762
|
-
- \`instructions_set(content)\`:
|
|
19763
|
-
- \`
|
|
19764
|
-
- \`
|
|
19850
|
+
- \`instructions_set(key, content)\`: Add or update a single instruction by key
|
|
19851
|
+
- \`instructions_remove(key)\`: Remove a single instruction by key
|
|
19852
|
+
- \`instructions_list()\`: List all instructions with keys and content
|
|
19853
|
+
- \`instructions_clear(confirm: true)\`: Remove all instructions (destructive!)
|
|
19765
19854
|
|
|
19766
19855
|
**Use for:** Agent personality, user preferences, learned rules, guidelines.`;
|
|
19767
19856
|
var instructionsSetDefinition = {
|
|
19768
19857
|
type: "function",
|
|
19769
19858
|
function: {
|
|
19770
19859
|
name: "instructions_set",
|
|
19771
|
-
description: `
|
|
19772
|
-
|
|
19860
|
+
description: `Add or update a single persistent instruction by key. Persists across sessions.
|
|
19861
|
+
If the key exists, it will be updated. If not, a new entry is created.`,
|
|
19773
19862
|
parameters: {
|
|
19774
19863
|
type: "object",
|
|
19775
19864
|
properties: {
|
|
19865
|
+
key: {
|
|
19866
|
+
type: "string",
|
|
19867
|
+
description: "Unique key for the instruction (alphanumeric, dash, underscore; max 100 chars)"
|
|
19868
|
+
},
|
|
19776
19869
|
content: {
|
|
19777
19870
|
type: "string",
|
|
19778
|
-
description: "
|
|
19871
|
+
description: "Instruction content (markdown supported)"
|
|
19779
19872
|
}
|
|
19780
19873
|
},
|
|
19781
|
-
required: ["content"]
|
|
19874
|
+
required: ["key", "content"]
|
|
19782
19875
|
}
|
|
19783
19876
|
}
|
|
19784
19877
|
};
|
|
19785
|
-
var
|
|
19878
|
+
var instructionsRemoveDefinition = {
|
|
19786
19879
|
type: "function",
|
|
19787
19880
|
function: {
|
|
19788
|
-
name: "
|
|
19789
|
-
description: "
|
|
19881
|
+
name: "instructions_remove",
|
|
19882
|
+
description: "Remove a single persistent instruction by key.",
|
|
19790
19883
|
parameters: {
|
|
19791
19884
|
type: "object",
|
|
19792
19885
|
properties: {
|
|
19793
|
-
|
|
19886
|
+
key: {
|
|
19794
19887
|
type: "string",
|
|
19795
|
-
description: "
|
|
19888
|
+
description: "Key of the instruction to remove"
|
|
19796
19889
|
}
|
|
19797
19890
|
},
|
|
19798
|
-
required: ["
|
|
19891
|
+
required: ["key"]
|
|
19799
19892
|
}
|
|
19800
19893
|
}
|
|
19801
19894
|
};
|
|
19802
|
-
var
|
|
19895
|
+
var instructionsListDefinition = {
|
|
19803
19896
|
type: "function",
|
|
19804
19897
|
function: {
|
|
19805
|
-
name: "
|
|
19806
|
-
description: "
|
|
19898
|
+
name: "instructions_list",
|
|
19899
|
+
description: "List all persistent instructions with their keys and content.",
|
|
19807
19900
|
parameters: {
|
|
19808
19901
|
type: "object",
|
|
19809
19902
|
properties: {},
|
|
@@ -19815,7 +19908,7 @@ var instructionsClearDefinition = {
|
|
|
19815
19908
|
type: "function",
|
|
19816
19909
|
function: {
|
|
19817
19910
|
name: "instructions_clear",
|
|
19818
|
-
description: "Clear all
|
|
19911
|
+
description: "Clear all persistent instructions (DESTRUCTIVE). Requires confirmation.",
|
|
19819
19912
|
parameters: {
|
|
19820
19913
|
type: "object",
|
|
19821
19914
|
properties: {
|
|
@@ -19828,13 +19921,22 @@ var instructionsClearDefinition = {
|
|
|
19828
19921
|
}
|
|
19829
19922
|
}
|
|
19830
19923
|
};
|
|
19924
|
+
function validateKey(key) {
|
|
19925
|
+
if (typeof key !== "string") return "Key must be a string";
|
|
19926
|
+
const trimmed = key.trim();
|
|
19927
|
+
if (trimmed.length === 0) return "Key cannot be empty";
|
|
19928
|
+
if (trimmed.length > KEY_MAX_LENGTH) return `Key exceeds maximum length (${KEY_MAX_LENGTH} chars)`;
|
|
19929
|
+
if (!KEY_PATTERN.test(trimmed)) return "Key must contain only alphanumeric characters, dashes, and underscores";
|
|
19930
|
+
return null;
|
|
19931
|
+
}
|
|
19831
19932
|
var PersistentInstructionsPluginNextGen = class {
|
|
19832
19933
|
name = "persistent_instructions";
|
|
19833
|
-
|
|
19934
|
+
_entries = /* @__PURE__ */ new Map();
|
|
19834
19935
|
_initialized = false;
|
|
19835
19936
|
_destroyed = false;
|
|
19836
19937
|
storage;
|
|
19837
|
-
|
|
19938
|
+
maxTotalLength;
|
|
19939
|
+
maxEntries;
|
|
19838
19940
|
agentId;
|
|
19839
19941
|
estimator = simpleTokenEstimator;
|
|
19840
19942
|
_tokenCache = null;
|
|
@@ -19844,7 +19946,8 @@ var PersistentInstructionsPluginNextGen = class {
|
|
|
19844
19946
|
throw new Error("PersistentInstructionsPluginNextGen requires agentId");
|
|
19845
19947
|
}
|
|
19846
19948
|
this.agentId = config.agentId;
|
|
19847
|
-
this.
|
|
19949
|
+
this.maxTotalLength = config.maxTotalLength ?? DEFAULT_MAX_TOTAL_LENGTH;
|
|
19950
|
+
this.maxEntries = config.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
19848
19951
|
this.storage = config.storage ?? new FilePersistentInstructionsStorage({
|
|
19849
19952
|
agentId: config.agentId
|
|
19850
19953
|
});
|
|
@@ -19857,14 +19960,16 @@ var PersistentInstructionsPluginNextGen = class {
|
|
|
19857
19960
|
}
|
|
19858
19961
|
async getContent() {
|
|
19859
19962
|
await this.ensureInitialized();
|
|
19860
|
-
if (
|
|
19963
|
+
if (this._entries.size === 0) {
|
|
19964
|
+
this._tokenCache = 0;
|
|
19861
19965
|
return null;
|
|
19862
19966
|
}
|
|
19863
|
-
|
|
19864
|
-
|
|
19967
|
+
const rendered = this.renderContent();
|
|
19968
|
+
this._tokenCache = this.estimator.estimateTokens(rendered);
|
|
19969
|
+
return rendered;
|
|
19865
19970
|
}
|
|
19866
19971
|
getContents() {
|
|
19867
|
-
return this.
|
|
19972
|
+
return new Map(this._entries);
|
|
19868
19973
|
}
|
|
19869
19974
|
getTokenSize() {
|
|
19870
19975
|
return this._tokenCache ?? 0;
|
|
@@ -19884,32 +19989,54 @@ var PersistentInstructionsPluginNextGen = class {
|
|
|
19884
19989
|
getTools() {
|
|
19885
19990
|
return [
|
|
19886
19991
|
this.createInstructionsSetTool(),
|
|
19887
|
-
this.
|
|
19888
|
-
this.
|
|
19992
|
+
this.createInstructionsRemoveTool(),
|
|
19993
|
+
this.createInstructionsListTool(),
|
|
19889
19994
|
this.createInstructionsClearTool()
|
|
19890
19995
|
];
|
|
19891
19996
|
}
|
|
19892
19997
|
destroy() {
|
|
19893
19998
|
if (this._destroyed) return;
|
|
19894
|
-
this.
|
|
19999
|
+
this._entries.clear();
|
|
19895
20000
|
this._destroyed = true;
|
|
19896
20001
|
this._tokenCache = null;
|
|
19897
20002
|
}
|
|
19898
20003
|
getState() {
|
|
19899
20004
|
return {
|
|
19900
|
-
|
|
19901
|
-
agentId: this.agentId
|
|
20005
|
+
entries: Array.from(this._entries.values()),
|
|
20006
|
+
agentId: this.agentId,
|
|
20007
|
+
version: 2
|
|
19902
20008
|
};
|
|
19903
20009
|
}
|
|
19904
20010
|
restoreState(state) {
|
|
20011
|
+
if (!state || typeof state !== "object") return;
|
|
19905
20012
|
const s = state;
|
|
19906
|
-
if (
|
|
19907
|
-
|
|
19908
|
-
|
|
19909
|
-
|
|
20013
|
+
if ("version" in s && s.version === 2 && Array.isArray(s.entries)) {
|
|
20014
|
+
this._entries.clear();
|
|
20015
|
+
for (const entry of s.entries) {
|
|
20016
|
+
this._entries.set(entry.id, entry);
|
|
20017
|
+
}
|
|
20018
|
+
this._initialized = true;
|
|
20019
|
+
this._tokenCache = null;
|
|
20020
|
+
return;
|
|
20021
|
+
}
|
|
20022
|
+
if ("content" in s) {
|
|
20023
|
+
this._entries.clear();
|
|
20024
|
+
const content = s.content;
|
|
20025
|
+
if (content) {
|
|
20026
|
+
const now = Date.now();
|
|
20027
|
+
this._entries.set("legacy_instructions", {
|
|
20028
|
+
id: "legacy_instructions",
|
|
20029
|
+
content,
|
|
20030
|
+
createdAt: now,
|
|
20031
|
+
updatedAt: now
|
|
20032
|
+
});
|
|
20033
|
+
}
|
|
20034
|
+
this._initialized = true;
|
|
20035
|
+
this._tokenCache = null;
|
|
20036
|
+
}
|
|
19910
20037
|
}
|
|
19911
20038
|
// ============================================================================
|
|
19912
|
-
//
|
|
20039
|
+
// Public API
|
|
19913
20040
|
// ============================================================================
|
|
19914
20041
|
/**
|
|
19915
20042
|
* Initialize by loading from storage (called lazily)
|
|
@@ -19917,66 +20044,99 @@ var PersistentInstructionsPluginNextGen = class {
|
|
|
19917
20044
|
async initialize() {
|
|
19918
20045
|
if (this._initialized || this._destroyed) return;
|
|
19919
20046
|
try {
|
|
19920
|
-
|
|
20047
|
+
const entries = await this.storage.load();
|
|
20048
|
+
this._entries.clear();
|
|
20049
|
+
if (entries) {
|
|
20050
|
+
for (const entry of entries) {
|
|
20051
|
+
this._entries.set(entry.id, entry);
|
|
20052
|
+
}
|
|
20053
|
+
}
|
|
19921
20054
|
this._initialized = true;
|
|
19922
20055
|
} catch (error) {
|
|
19923
20056
|
console.warn(`Failed to load persistent instructions for agent '${this.agentId}':`, error);
|
|
19924
|
-
this.
|
|
20057
|
+
this._entries.clear();
|
|
19925
20058
|
this._initialized = true;
|
|
19926
20059
|
}
|
|
19927
20060
|
this._tokenCache = null;
|
|
19928
20061
|
}
|
|
19929
20062
|
/**
|
|
19930
|
-
*
|
|
20063
|
+
* Add or update an instruction entry by key
|
|
19931
20064
|
*/
|
|
19932
|
-
async set(content) {
|
|
20065
|
+
async set(key, content) {
|
|
19933
20066
|
this.assertNotDestroyed();
|
|
19934
|
-
|
|
20067
|
+
await this.ensureInitialized();
|
|
20068
|
+
const keyError = validateKey(key);
|
|
20069
|
+
if (keyError) return false;
|
|
20070
|
+
const trimmedContent = content.trim();
|
|
20071
|
+
if (trimmedContent.length === 0) return false;
|
|
20072
|
+
if (!this._entries.has(key) && this._entries.size >= this.maxEntries) {
|
|
19935
20073
|
return false;
|
|
19936
20074
|
}
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
|
|
19941
|
-
|
|
20075
|
+
const currentTotal = this.calculateTotalContentLength();
|
|
20076
|
+
const existingLength = this._entries.get(key)?.content.length ?? 0;
|
|
20077
|
+
const newTotal = currentTotal - existingLength + trimmedContent.length;
|
|
20078
|
+
if (newTotal > this.maxTotalLength) {
|
|
20079
|
+
return false;
|
|
19942
20080
|
}
|
|
20081
|
+
const now = Date.now();
|
|
20082
|
+
const existing = this._entries.get(key);
|
|
20083
|
+
this._entries.set(key, {
|
|
20084
|
+
id: key,
|
|
20085
|
+
content: trimmedContent,
|
|
20086
|
+
createdAt: existing?.createdAt ?? now,
|
|
20087
|
+
updatedAt: now
|
|
20088
|
+
});
|
|
20089
|
+
await this.persistToStorage();
|
|
19943
20090
|
this._tokenCache = null;
|
|
19944
20091
|
return true;
|
|
19945
20092
|
}
|
|
19946
20093
|
/**
|
|
19947
|
-
*
|
|
20094
|
+
* Remove an instruction entry by key
|
|
19948
20095
|
*/
|
|
19949
|
-
async
|
|
20096
|
+
async remove(key) {
|
|
19950
20097
|
this.assertNotDestroyed();
|
|
19951
20098
|
await this.ensureInitialized();
|
|
19952
|
-
|
|
19953
|
-
|
|
19954
|
-
|
|
19955
|
-
|
|
19956
|
-
|
|
19957
|
-
|
|
19958
|
-
if (newContent.length > this.maxLength) {
|
|
19959
|
-
return false;
|
|
20099
|
+
if (!this._entries.has(key)) return false;
|
|
20100
|
+
this._entries.delete(key);
|
|
20101
|
+
if (this._entries.size === 0) {
|
|
20102
|
+
await this.storage.delete();
|
|
20103
|
+
} else {
|
|
20104
|
+
await this.persistToStorage();
|
|
19960
20105
|
}
|
|
19961
|
-
this._content = newContent;
|
|
19962
|
-
await this.storage.save(this._content);
|
|
19963
20106
|
this._tokenCache = null;
|
|
19964
20107
|
return true;
|
|
19965
20108
|
}
|
|
19966
20109
|
/**
|
|
19967
|
-
* Get
|
|
20110
|
+
* Get one entry by key, or all entries if no key provided
|
|
19968
20111
|
*/
|
|
19969
|
-
async get() {
|
|
20112
|
+
async get(key) {
|
|
19970
20113
|
this.assertNotDestroyed();
|
|
19971
20114
|
await this.ensureInitialized();
|
|
19972
|
-
|
|
20115
|
+
if (key !== void 0) {
|
|
20116
|
+
return this._entries.get(key) ?? null;
|
|
20117
|
+
}
|
|
20118
|
+
if (this._entries.size === 0) return null;
|
|
20119
|
+
return this.getSortedEntries();
|
|
19973
20120
|
}
|
|
19974
20121
|
/**
|
|
19975
|
-
*
|
|
20122
|
+
* List metadata for all entries
|
|
20123
|
+
*/
|
|
20124
|
+
async list() {
|
|
20125
|
+
this.assertNotDestroyed();
|
|
20126
|
+
await this.ensureInitialized();
|
|
20127
|
+
return this.getSortedEntries().map((entry) => ({
|
|
20128
|
+
key: entry.id,
|
|
20129
|
+
contentLength: entry.content.length,
|
|
20130
|
+
createdAt: entry.createdAt,
|
|
20131
|
+
updatedAt: entry.updatedAt
|
|
20132
|
+
}));
|
|
20133
|
+
}
|
|
20134
|
+
/**
|
|
20135
|
+
* Clear all instruction entries
|
|
19976
20136
|
*/
|
|
19977
20137
|
async clear() {
|
|
19978
20138
|
this.assertNotDestroyed();
|
|
19979
|
-
this.
|
|
20139
|
+
this._entries.clear();
|
|
19980
20140
|
await this.storage.delete();
|
|
19981
20141
|
this._tokenCache = null;
|
|
19982
20142
|
}
|
|
@@ -19999,6 +20159,35 @@ ${trimmedSection}` : trimmedSection;
|
|
|
19999
20159
|
throw new Error("PersistentInstructionsPluginNextGen is destroyed");
|
|
20000
20160
|
}
|
|
20001
20161
|
}
|
|
20162
|
+
/**
|
|
20163
|
+
* Persist current entries to storage
|
|
20164
|
+
*/
|
|
20165
|
+
async persistToStorage() {
|
|
20166
|
+
await this.storage.save(Array.from(this._entries.values()));
|
|
20167
|
+
}
|
|
20168
|
+
/**
|
|
20169
|
+
* Calculate total content length across all entries
|
|
20170
|
+
*/
|
|
20171
|
+
calculateTotalContentLength() {
|
|
20172
|
+
let total = 0;
|
|
20173
|
+
for (const entry of this._entries.values()) {
|
|
20174
|
+
total += entry.content.length;
|
|
20175
|
+
}
|
|
20176
|
+
return total;
|
|
20177
|
+
}
|
|
20178
|
+
/**
|
|
20179
|
+
* Get entries sorted by createdAt (oldest first)
|
|
20180
|
+
*/
|
|
20181
|
+
getSortedEntries() {
|
|
20182
|
+
return Array.from(this._entries.values()).sort((a, b) => a.createdAt - b.createdAt);
|
|
20183
|
+
}
|
|
20184
|
+
/**
|
|
20185
|
+
* Render all entries as markdown for context injection
|
|
20186
|
+
*/
|
|
20187
|
+
renderContent() {
|
|
20188
|
+
return this.getSortedEntries().map((entry) => `### ${entry.id}
|
|
20189
|
+
${entry.content}`).join("\n\n");
|
|
20190
|
+
}
|
|
20002
20191
|
// ============================================================================
|
|
20003
20192
|
// Tool Factories
|
|
20004
20193
|
// ============================================================================
|
|
@@ -20006,60 +20195,84 @@ ${trimmedSection}` : trimmedSection;
|
|
|
20006
20195
|
return {
|
|
20007
20196
|
definition: instructionsSetDefinition,
|
|
20008
20197
|
execute: async (args) => {
|
|
20198
|
+
const key = args.key;
|
|
20009
20199
|
const content = args.content;
|
|
20200
|
+
const keyError = validateKey(key);
|
|
20201
|
+
if (keyError) {
|
|
20202
|
+
return { error: keyError };
|
|
20203
|
+
}
|
|
20010
20204
|
if (!content || content.trim().length === 0) {
|
|
20011
|
-
return { error: "Content cannot be empty. Use
|
|
20205
|
+
return { error: "Content cannot be empty. Use instructions_remove to delete an entry." };
|
|
20012
20206
|
}
|
|
20013
|
-
const
|
|
20207
|
+
const isUpdate = this._entries.has(key.trim());
|
|
20208
|
+
const success = await this.set(key.trim(), content);
|
|
20014
20209
|
if (!success) {
|
|
20015
|
-
|
|
20210
|
+
if (!isUpdate && this._entries.size >= this.maxEntries) {
|
|
20211
|
+
return { error: `Maximum number of entries reached (${this.maxEntries})` };
|
|
20212
|
+
}
|
|
20213
|
+
return { error: `Content would exceed maximum total length (${this.maxTotalLength} chars)` };
|
|
20016
20214
|
}
|
|
20017
20215
|
return {
|
|
20018
20216
|
success: true,
|
|
20019
|
-
message:
|
|
20020
|
-
|
|
20217
|
+
message: isUpdate ? `Instruction '${key.trim()}' updated` : `Instruction '${key.trim()}' added`,
|
|
20218
|
+
key: key.trim(),
|
|
20219
|
+
contentLength: content.trim().length
|
|
20021
20220
|
};
|
|
20022
20221
|
},
|
|
20023
20222
|
permission: { scope: "always", riskLevel: "low" },
|
|
20024
|
-
describeCall: () =>
|
|
20223
|
+
describeCall: (args) => `set instruction '${args.key}'`
|
|
20025
20224
|
};
|
|
20026
20225
|
}
|
|
20027
|
-
|
|
20226
|
+
createInstructionsRemoveTool() {
|
|
20028
20227
|
return {
|
|
20029
|
-
definition:
|
|
20228
|
+
definition: instructionsRemoveDefinition,
|
|
20030
20229
|
execute: async (args) => {
|
|
20031
|
-
const
|
|
20032
|
-
if (!
|
|
20033
|
-
return { error: "
|
|
20230
|
+
const key = args.key;
|
|
20231
|
+
if (!key || typeof key !== "string" || key.trim().length === 0) {
|
|
20232
|
+
return { error: "Key is required" };
|
|
20034
20233
|
}
|
|
20035
|
-
const success = await this.
|
|
20234
|
+
const success = await this.remove(key.trim());
|
|
20036
20235
|
if (!success) {
|
|
20037
|
-
return { error: `
|
|
20236
|
+
return { error: `Instruction '${key.trim()}' not found` };
|
|
20038
20237
|
}
|
|
20039
20238
|
return {
|
|
20040
20239
|
success: true,
|
|
20041
|
-
message:
|
|
20042
|
-
|
|
20240
|
+
message: `Instruction '${key.trim()}' removed`,
|
|
20241
|
+
key: key.trim()
|
|
20043
20242
|
};
|
|
20044
20243
|
},
|
|
20045
20244
|
permission: { scope: "always", riskLevel: "low" },
|
|
20046
|
-
describeCall: () =>
|
|
20245
|
+
describeCall: (args) => `remove instruction '${args.key}'`
|
|
20047
20246
|
};
|
|
20048
20247
|
}
|
|
20049
|
-
|
|
20248
|
+
createInstructionsListTool() {
|
|
20050
20249
|
return {
|
|
20051
|
-
definition:
|
|
20250
|
+
definition: instructionsListDefinition,
|
|
20052
20251
|
execute: async () => {
|
|
20053
|
-
const
|
|
20252
|
+
const entries = await this.list();
|
|
20253
|
+
const all = await this.get();
|
|
20254
|
+
if (entries.length === 0) {
|
|
20255
|
+
return {
|
|
20256
|
+
count: 0,
|
|
20257
|
+
entries: [],
|
|
20258
|
+
message: "(no custom instructions set)"
|
|
20259
|
+
};
|
|
20260
|
+
}
|
|
20261
|
+
const allEntries = all;
|
|
20054
20262
|
return {
|
|
20055
|
-
|
|
20056
|
-
|
|
20057
|
-
|
|
20263
|
+
count: entries.length,
|
|
20264
|
+
entries: allEntries.map((e) => ({
|
|
20265
|
+
key: e.id,
|
|
20266
|
+
content: e.content,
|
|
20267
|
+
contentLength: e.content.length,
|
|
20268
|
+
createdAt: e.createdAt,
|
|
20269
|
+
updatedAt: e.updatedAt
|
|
20270
|
+
})),
|
|
20058
20271
|
agentId: this.agentId
|
|
20059
20272
|
};
|
|
20060
20273
|
},
|
|
20061
20274
|
permission: { scope: "always", riskLevel: "low" },
|
|
20062
|
-
describeCall: () => "
|
|
20275
|
+
describeCall: () => "list instructions"
|
|
20063
20276
|
};
|
|
20064
20277
|
}
|
|
20065
20278
|
createInstructionsClearTool() {
|
|
@@ -20072,7 +20285,7 @@ ${trimmedSection}` : trimmedSection;
|
|
|
20072
20285
|
await this.clear();
|
|
20073
20286
|
return {
|
|
20074
20287
|
success: true,
|
|
20075
|
-
message: "
|
|
20288
|
+
message: "All custom instructions cleared"
|
|
20076
20289
|
};
|
|
20077
20290
|
},
|
|
20078
20291
|
permission: { scope: "once", riskLevel: "medium" },
|
|
@@ -20797,7 +21010,9 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
|
|
|
20797
21010
|
this._agentId = this._config.agentId;
|
|
20798
21011
|
this._storage = config.storage;
|
|
20799
21012
|
this._compactionStrategy = config.compactionStrategy ?? StrategyRegistry.create(this._config.strategy);
|
|
20800
|
-
this._tools = new ToolManager(
|
|
21013
|
+
this._tools = new ToolManager(
|
|
21014
|
+
config.toolExecutionTimeout ? { toolExecutionTimeout: config.toolExecutionTimeout } : void 0
|
|
21015
|
+
);
|
|
20801
21016
|
if (config.tools) {
|
|
20802
21017
|
for (const tool of config.tools) {
|
|
20803
21018
|
this._tools.register(tool);
|
|
@@ -22533,7 +22748,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
|
|
|
22533
22748
|
streamConverter;
|
|
22534
22749
|
constructor(config) {
|
|
22535
22750
|
super(config);
|
|
22536
|
-
this.client = new
|
|
22751
|
+
this.client = new OpenAI3__default.default({
|
|
22537
22752
|
apiKey: this.getApiKey(),
|
|
22538
22753
|
baseURL: this.getBaseURL(),
|
|
22539
22754
|
organization: config.organization,
|
|
@@ -24263,7 +24478,9 @@ var GoogleTextProvider = class extends BaseTextProvider {
|
|
|
24263
24478
|
constructor(config) {
|
|
24264
24479
|
super(config);
|
|
24265
24480
|
this.client = new genai.GoogleGenAI({
|
|
24266
|
-
apiKey: this.getApiKey()
|
|
24481
|
+
apiKey: this.getApiKey(),
|
|
24482
|
+
// Pass custom baseURL for proxy support (e.g. when routing through EW proxy)
|
|
24483
|
+
...config.baseURL ? { httpOptions: { baseUrl: config.baseURL } } : {}
|
|
24267
24484
|
});
|
|
24268
24485
|
this.converter = new GoogleConverter();
|
|
24269
24486
|
this.streamConverter = new GoogleStreamConverter();
|
|
@@ -24560,6 +24777,30 @@ var GenericOpenAIProvider = class extends OpenAITextProvider {
|
|
|
24560
24777
|
};
|
|
24561
24778
|
|
|
24562
24779
|
// src/core/createProvider.ts
|
|
24780
|
+
var VENDOR_DEFAULT_URLS = (() => {
|
|
24781
|
+
const map = /* @__PURE__ */ new Map();
|
|
24782
|
+
try {
|
|
24783
|
+
map.set(Vendor.OpenAI, new OpenAI3__default.default({ apiKey: "_" }).baseURL);
|
|
24784
|
+
} catch {
|
|
24785
|
+
}
|
|
24786
|
+
try {
|
|
24787
|
+
map.set(Vendor.Anthropic, new Anthropic__default.default({ apiKey: "_" }).baseURL);
|
|
24788
|
+
} catch {
|
|
24789
|
+
}
|
|
24790
|
+
map.set(Vendor.Google, "https://generativelanguage.googleapis.com");
|
|
24791
|
+
map.set(Vendor.GoogleVertex, "https://us-central1-aiplatform.googleapis.com");
|
|
24792
|
+
map.set(Vendor.Groq, "https://api.groq.com/openai/v1");
|
|
24793
|
+
map.set(Vendor.Together, "https://api.together.xyz/v1");
|
|
24794
|
+
map.set(Vendor.Perplexity, "https://api.perplexity.ai");
|
|
24795
|
+
map.set(Vendor.Grok, "https://api.x.ai/v1");
|
|
24796
|
+
map.set(Vendor.DeepSeek, "https://api.deepseek.com/v1");
|
|
24797
|
+
map.set(Vendor.Mistral, "https://api.mistral.ai/v1");
|
|
24798
|
+
map.set(Vendor.Ollama, "http://localhost:11434/v1");
|
|
24799
|
+
return map;
|
|
24800
|
+
})();
|
|
24801
|
+
function getVendorDefaultBaseURL(vendor) {
|
|
24802
|
+
return VENDOR_DEFAULT_URLS.get(vendor);
|
|
24803
|
+
}
|
|
24563
24804
|
function createProvider(connector) {
|
|
24564
24805
|
const injectedProvider = connector.getOptions().provider;
|
|
24565
24806
|
if (injectedProvider && typeof injectedProvider.generate === "function") {
|
|
@@ -24594,39 +24835,15 @@ function createProvider(connector) {
|
|
|
24594
24835
|
});
|
|
24595
24836
|
// OpenAI-compatible providers (use connector.name for unique identification)
|
|
24596
24837
|
case Vendor.Groq:
|
|
24597
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24598
|
-
...config,
|
|
24599
|
-
baseURL: config.baseURL || "https://api.groq.com/openai/v1"
|
|
24600
|
-
});
|
|
24601
24838
|
case Vendor.Together:
|
|
24602
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24603
|
-
...config,
|
|
24604
|
-
baseURL: config.baseURL || "https://api.together.xyz/v1"
|
|
24605
|
-
});
|
|
24606
24839
|
case Vendor.Perplexity:
|
|
24607
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24608
|
-
...config,
|
|
24609
|
-
baseURL: config.baseURL || "https://api.perplexity.ai"
|
|
24610
|
-
});
|
|
24611
24840
|
case Vendor.Grok:
|
|
24612
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24613
|
-
...config,
|
|
24614
|
-
baseURL: config.baseURL || "https://api.x.ai/v1"
|
|
24615
|
-
});
|
|
24616
24841
|
case Vendor.DeepSeek:
|
|
24617
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24618
|
-
...config,
|
|
24619
|
-
baseURL: config.baseURL || "https://api.deepseek.com/v1"
|
|
24620
|
-
});
|
|
24621
24842
|
case Vendor.Mistral:
|
|
24622
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24623
|
-
...config,
|
|
24624
|
-
baseURL: config.baseURL || "https://api.mistral.ai/v1"
|
|
24625
|
-
});
|
|
24626
24843
|
case Vendor.Ollama:
|
|
24627
24844
|
return new GenericOpenAIProvider(connector.name, {
|
|
24628
24845
|
...config,
|
|
24629
|
-
baseURL: config.baseURL ||
|
|
24846
|
+
baseURL: config.baseURL || getVendorDefaultBaseURL(vendor)
|
|
24630
24847
|
});
|
|
24631
24848
|
case Vendor.Custom:
|
|
24632
24849
|
if (!config.baseURL) {
|
|
@@ -24738,7 +24955,10 @@ var BaseAgent = class extends eventemitter3.EventEmitter {
|
|
|
24738
24955
|
agentId: config.name,
|
|
24739
24956
|
// Include storage and sessionId if session config is provided
|
|
24740
24957
|
storage: config.session?.storage,
|
|
24958
|
+
// Thread tool execution timeout to ToolManager
|
|
24959
|
+
toolExecutionTimeout: config.toolExecutionTimeout,
|
|
24741
24960
|
// Subclasses can add systemPrompt via their config
|
|
24961
|
+
// Note: context-level toolExecutionTimeout overrides agent-level if both set
|
|
24742
24962
|
...typeof config.context === "object" && config.context !== null ? config.context : {}
|
|
24743
24963
|
};
|
|
24744
24964
|
return AgentContextNextGen.create(contextConfig);
|
|
@@ -27178,18 +27398,18 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27178
27398
|
(class {
|
|
27179
27399
|
static DEFAULT_PATHS = [
|
|
27180
27400
|
"./oneringai.config.json",
|
|
27181
|
-
|
|
27401
|
+
path2.join(os2.homedir(), ".oneringai", "config.json")
|
|
27182
27402
|
];
|
|
27183
27403
|
/**
|
|
27184
27404
|
* Load configuration from file
|
|
27185
27405
|
*/
|
|
27186
27406
|
static async load(path6) {
|
|
27187
|
-
const configPath = path6 ?
|
|
27407
|
+
const configPath = path6 ? path2.resolve(path6) : await this.findConfig();
|
|
27188
27408
|
if (!configPath) {
|
|
27189
27409
|
throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
|
|
27190
27410
|
}
|
|
27191
27411
|
try {
|
|
27192
|
-
const content = await
|
|
27412
|
+
const content = await fs16.promises.readFile(configPath, "utf-8");
|
|
27193
27413
|
let config = JSON.parse(content);
|
|
27194
27414
|
config = this.interpolateEnvVars(config);
|
|
27195
27415
|
this.validate(config);
|
|
@@ -27205,13 +27425,13 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27205
27425
|
* Load configuration synchronously
|
|
27206
27426
|
*/
|
|
27207
27427
|
static loadSync(path6) {
|
|
27208
|
-
const configPath = path6 ?
|
|
27428
|
+
const configPath = path6 ? path2.resolve(path6) : this.findConfigSync();
|
|
27209
27429
|
if (!configPath) {
|
|
27210
27430
|
throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
|
|
27211
27431
|
}
|
|
27212
27432
|
try {
|
|
27213
|
-
const
|
|
27214
|
-
const content =
|
|
27433
|
+
const fs17 = __require("fs");
|
|
27434
|
+
const content = fs17.readFileSync(configPath, "utf-8");
|
|
27215
27435
|
let config = JSON.parse(content);
|
|
27216
27436
|
config = this.interpolateEnvVars(config);
|
|
27217
27437
|
this.validate(config);
|
|
@@ -27229,8 +27449,8 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27229
27449
|
static async findConfig() {
|
|
27230
27450
|
for (const path6 of this.DEFAULT_PATHS) {
|
|
27231
27451
|
try {
|
|
27232
|
-
await
|
|
27233
|
-
return
|
|
27452
|
+
await fs16.promises.access(path2.resolve(path6));
|
|
27453
|
+
return path2.resolve(path6);
|
|
27234
27454
|
} catch {
|
|
27235
27455
|
}
|
|
27236
27456
|
}
|
|
@@ -27240,11 +27460,11 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27240
27460
|
* Find configuration file synchronously
|
|
27241
27461
|
*/
|
|
27242
27462
|
static findConfigSync() {
|
|
27243
|
-
const
|
|
27463
|
+
const fs17 = __require("fs");
|
|
27244
27464
|
for (const path6 of this.DEFAULT_PATHS) {
|
|
27245
27465
|
try {
|
|
27246
|
-
|
|
27247
|
-
return
|
|
27466
|
+
fs17.accessSync(path2.resolve(path6));
|
|
27467
|
+
return path2.resolve(path6);
|
|
27248
27468
|
} catch {
|
|
27249
27469
|
}
|
|
27250
27470
|
}
|
|
@@ -32801,8 +33021,8 @@ var MCPRegistry = class {
|
|
|
32801
33021
|
*/
|
|
32802
33022
|
static async loadFromConfigFile(path6) {
|
|
32803
33023
|
try {
|
|
32804
|
-
const configPath =
|
|
32805
|
-
const content = await
|
|
33024
|
+
const configPath = path2.resolve(path6);
|
|
33025
|
+
const content = await fs16.promises.readFile(configPath, "utf-8");
|
|
32806
33026
|
const config = JSON.parse(content);
|
|
32807
33027
|
if (!config.mcp) {
|
|
32808
33028
|
throw new MCPError("Configuration file does not contain MCP section");
|
|
@@ -33190,7 +33410,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
|
|
|
33190
33410
|
client;
|
|
33191
33411
|
constructor(config) {
|
|
33192
33412
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
33193
|
-
this.client = new
|
|
33413
|
+
this.client = new OpenAI3__default.default({
|
|
33194
33414
|
apiKey: config.auth.apiKey,
|
|
33195
33415
|
baseURL: config.baseURL,
|
|
33196
33416
|
organization: config.organization,
|
|
@@ -33273,7 +33493,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
|
|
|
33273
33493
|
* Handle OpenAI API errors
|
|
33274
33494
|
*/
|
|
33275
33495
|
handleError(error) {
|
|
33276
|
-
if (error instanceof
|
|
33496
|
+
if (error instanceof OpenAI3__default.default.APIError) {
|
|
33277
33497
|
const status = error.status;
|
|
33278
33498
|
const message = error.message || "Unknown OpenAI API error";
|
|
33279
33499
|
if (status === 401) {
|
|
@@ -33305,7 +33525,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
|
|
|
33305
33525
|
client;
|
|
33306
33526
|
constructor(config) {
|
|
33307
33527
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
33308
|
-
this.client = new
|
|
33528
|
+
this.client = new OpenAI3__default.default({
|
|
33309
33529
|
apiKey: config.auth.apiKey,
|
|
33310
33530
|
baseURL: config.baseURL,
|
|
33311
33531
|
organization: config.organization,
|
|
@@ -33407,7 +33627,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
|
|
|
33407
33627
|
if (Buffer.isBuffer(audio)) {
|
|
33408
33628
|
return new File([new Uint8Array(audio)], "audio.wav", { type: "audio/wav" });
|
|
33409
33629
|
} else if (typeof audio === "string") {
|
|
33410
|
-
return
|
|
33630
|
+
return fs16__namespace.createReadStream(audio);
|
|
33411
33631
|
} else {
|
|
33412
33632
|
throw new Error("Invalid audio input: must be Buffer or file path");
|
|
33413
33633
|
}
|
|
@@ -33466,7 +33686,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
|
|
|
33466
33686
|
* Handle OpenAI API errors
|
|
33467
33687
|
*/
|
|
33468
33688
|
handleError(error) {
|
|
33469
|
-
if (error instanceof
|
|
33689
|
+
if (error instanceof OpenAI3__default.default.APIError) {
|
|
33470
33690
|
const status = error.status;
|
|
33471
33691
|
const message = error.message || "Unknown OpenAI API error";
|
|
33472
33692
|
if (status === 401) {
|
|
@@ -33960,7 +34180,7 @@ var TextToSpeech = class _TextToSpeech {
|
|
|
33960
34180
|
*/
|
|
33961
34181
|
async toFile(text, filePath, options) {
|
|
33962
34182
|
const response = await this.synthesize(text, options);
|
|
33963
|
-
await
|
|
34183
|
+
await fs15__namespace.writeFile(filePath, response.audio);
|
|
33964
34184
|
}
|
|
33965
34185
|
// ======================== Introspection Methods ========================
|
|
33966
34186
|
/**
|
|
@@ -34308,7 +34528,7 @@ var SpeechToText = class _SpeechToText {
|
|
|
34308
34528
|
* @param options - Optional transcription parameters
|
|
34309
34529
|
*/
|
|
34310
34530
|
async transcribeFile(filePath, options) {
|
|
34311
|
-
const audio = await
|
|
34531
|
+
const audio = await fs15__namespace.readFile(filePath);
|
|
34312
34532
|
return this.transcribe(audio, options);
|
|
34313
34533
|
}
|
|
34314
34534
|
/**
|
|
@@ -34472,7 +34692,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
|
|
|
34472
34692
|
client;
|
|
34473
34693
|
constructor(config) {
|
|
34474
34694
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
34475
|
-
this.client = new
|
|
34695
|
+
this.client = new OpenAI3__default.default({
|
|
34476
34696
|
apiKey: config.auth.apiKey,
|
|
34477
34697
|
baseURL: config.baseURL,
|
|
34478
34698
|
organization: config.organization,
|
|
@@ -34634,7 +34854,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
|
|
|
34634
34854
|
if (Buffer.isBuffer(image)) {
|
|
34635
34855
|
return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
|
|
34636
34856
|
}
|
|
34637
|
-
return
|
|
34857
|
+
return fs16__namespace.createReadStream(image);
|
|
34638
34858
|
}
|
|
34639
34859
|
/**
|
|
34640
34860
|
* Handle OpenAI API errors
|
|
@@ -34781,8 +35001,8 @@ var GoogleImageProvider = class extends BaseMediaProvider {
|
|
|
34781
35001
|
if (Buffer.isBuffer(image)) {
|
|
34782
35002
|
imageBytes = image.toString("base64");
|
|
34783
35003
|
} else {
|
|
34784
|
-
const
|
|
34785
|
-
const buffer =
|
|
35004
|
+
const fs17 = await import('fs');
|
|
35005
|
+
const buffer = fs17.readFileSync(image);
|
|
34786
35006
|
imageBytes = buffer.toString("base64");
|
|
34787
35007
|
}
|
|
34788
35008
|
return {
|
|
@@ -34832,7 +35052,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
|
|
|
34832
35052
|
client;
|
|
34833
35053
|
constructor(config) {
|
|
34834
35054
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
34835
|
-
this.client = new
|
|
35055
|
+
this.client = new OpenAI3__default.default({
|
|
34836
35056
|
apiKey: config.auth.apiKey,
|
|
34837
35057
|
baseURL: config.baseURL || GROK_API_BASE_URL,
|
|
34838
35058
|
timeout: config.timeout,
|
|
@@ -34943,7 +35163,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
|
|
|
34943
35163
|
if (Buffer.isBuffer(image)) {
|
|
34944
35164
|
return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
|
|
34945
35165
|
}
|
|
34946
|
-
return
|
|
35166
|
+
return fs16__namespace.createReadStream(image);
|
|
34947
35167
|
}
|
|
34948
35168
|
/**
|
|
34949
35169
|
* Handle API errors
|
|
@@ -36145,7 +36365,7 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
|
|
|
36145
36365
|
client;
|
|
36146
36366
|
constructor(config) {
|
|
36147
36367
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
36148
|
-
this.client = new
|
|
36368
|
+
this.client = new OpenAI3__default.default({
|
|
36149
36369
|
apiKey: config.auth.apiKey,
|
|
36150
36370
|
baseURL: config.baseURL,
|
|
36151
36371
|
organization: config.organization,
|
|
@@ -36393,8 +36613,8 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
|
|
|
36393
36613
|
return new File([new Uint8Array(image)], "input.png", { type: "image/png" });
|
|
36394
36614
|
}
|
|
36395
36615
|
if (!image.startsWith("http")) {
|
|
36396
|
-
const
|
|
36397
|
-
const data =
|
|
36616
|
+
const fs17 = await import('fs');
|
|
36617
|
+
const data = fs17.readFileSync(image);
|
|
36398
36618
|
return new File([new Uint8Array(data)], "input.png", { type: "image/png" });
|
|
36399
36619
|
}
|
|
36400
36620
|
const response = await fetch(image);
|
|
@@ -36572,7 +36792,7 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
|
|
|
36572
36792
|
if (video.videoBytes) {
|
|
36573
36793
|
buffer = Buffer.from(video.videoBytes, "base64");
|
|
36574
36794
|
} else if (video.uri) {
|
|
36575
|
-
const
|
|
36795
|
+
const fs17 = await import('fs/promises');
|
|
36576
36796
|
const os3 = await import('os');
|
|
36577
36797
|
const path6 = await import('path');
|
|
36578
36798
|
const tempDir = os3.tmpdir();
|
|
@@ -36583,11 +36803,11 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
|
|
|
36583
36803
|
// Pass as GeneratedVideo
|
|
36584
36804
|
downloadPath: tempFile
|
|
36585
36805
|
});
|
|
36586
|
-
buffer = await
|
|
36587
|
-
await
|
|
36806
|
+
buffer = await fs17.readFile(tempFile);
|
|
36807
|
+
await fs17.unlink(tempFile).catch(() => {
|
|
36588
36808
|
});
|
|
36589
36809
|
} catch (downloadError) {
|
|
36590
|
-
await
|
|
36810
|
+
await fs17.unlink(tempFile).catch(() => {
|
|
36591
36811
|
});
|
|
36592
36812
|
throw new ProviderError(
|
|
36593
36813
|
"google",
|
|
@@ -36709,8 +36929,8 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
|
|
|
36709
36929
|
if (image.startsWith("http://") || image.startsWith("https://")) {
|
|
36710
36930
|
return { imageUri: image };
|
|
36711
36931
|
}
|
|
36712
|
-
const
|
|
36713
|
-
const data = await
|
|
36932
|
+
const fs17 = await import('fs/promises');
|
|
36933
|
+
const data = await fs17.readFile(image);
|
|
36714
36934
|
return {
|
|
36715
36935
|
imageBytes: data.toString("base64")
|
|
36716
36936
|
};
|
|
@@ -37017,8 +37237,8 @@ var GrokImagineProvider = class extends BaseMediaProvider {
|
|
|
37017
37237
|
if (image.startsWith("http") || image.startsWith("data:")) {
|
|
37018
37238
|
return image;
|
|
37019
37239
|
}
|
|
37020
|
-
const
|
|
37021
|
-
const data =
|
|
37240
|
+
const fs17 = await import('fs');
|
|
37241
|
+
const data = fs17.readFileSync(image);
|
|
37022
37242
|
const base64 = data.toString("base64");
|
|
37023
37243
|
const ext = image.split(".").pop()?.toLowerCase() || "png";
|
|
37024
37244
|
const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext}`;
|
|
@@ -40223,10 +40443,10 @@ function getDefaultBaseDirectory2() {
|
|
|
40223
40443
|
if (platform2 === "win32") {
|
|
40224
40444
|
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
40225
40445
|
if (appData) {
|
|
40226
|
-
return
|
|
40446
|
+
return path2.join(appData, "oneringai", "agents");
|
|
40227
40447
|
}
|
|
40228
40448
|
}
|
|
40229
|
-
return
|
|
40449
|
+
return path2.join(os2.homedir(), ".oneringai", "agents");
|
|
40230
40450
|
}
|
|
40231
40451
|
function sanitizeId(id) {
|
|
40232
40452
|
return id.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
|
|
@@ -40243,8 +40463,8 @@ var FileContextStorage = class {
|
|
|
40243
40463
|
const sanitizedAgentId = sanitizeId(config.agentId);
|
|
40244
40464
|
const baseDir = config.baseDirectory ?? getDefaultBaseDirectory2();
|
|
40245
40465
|
this.prettyPrint = config.prettyPrint ?? true;
|
|
40246
|
-
this.sessionsDirectory =
|
|
40247
|
-
this.indexPath =
|
|
40466
|
+
this.sessionsDirectory = path2.join(baseDir, sanitizedAgentId, "sessions");
|
|
40467
|
+
this.indexPath = path2.join(this.sessionsDirectory, "_index.json");
|
|
40248
40468
|
}
|
|
40249
40469
|
/**
|
|
40250
40470
|
* Save context state to a session file
|
|
@@ -40270,11 +40490,11 @@ var FileContextStorage = class {
|
|
|
40270
40490
|
const data = this.prettyPrint ? JSON.stringify(storedSession, null, 2) : JSON.stringify(storedSession);
|
|
40271
40491
|
const tempPath = `${filePath}.tmp`;
|
|
40272
40492
|
try {
|
|
40273
|
-
await
|
|
40274
|
-
await
|
|
40493
|
+
await fs16.promises.writeFile(tempPath, data, "utf-8");
|
|
40494
|
+
await fs16.promises.rename(tempPath, filePath);
|
|
40275
40495
|
} catch (error) {
|
|
40276
40496
|
try {
|
|
40277
|
-
await
|
|
40497
|
+
await fs16.promises.unlink(tempPath);
|
|
40278
40498
|
} catch {
|
|
40279
40499
|
}
|
|
40280
40500
|
throw error;
|
|
@@ -40295,7 +40515,7 @@ var FileContextStorage = class {
|
|
|
40295
40515
|
const sanitizedSessionId = sanitizeId(sessionId);
|
|
40296
40516
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40297
40517
|
try {
|
|
40298
|
-
await
|
|
40518
|
+
await fs16.promises.unlink(filePath);
|
|
40299
40519
|
} catch (error) {
|
|
40300
40520
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
40301
40521
|
throw error;
|
|
@@ -40310,7 +40530,7 @@ var FileContextStorage = class {
|
|
|
40310
40530
|
const sanitizedSessionId = sanitizeId(sessionId);
|
|
40311
40531
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40312
40532
|
try {
|
|
40313
|
-
await
|
|
40533
|
+
await fs16.promises.access(filePath);
|
|
40314
40534
|
return true;
|
|
40315
40535
|
} catch {
|
|
40316
40536
|
return false;
|
|
@@ -40375,7 +40595,7 @@ var FileContextStorage = class {
|
|
|
40375
40595
|
const sanitizedSessionId = sanitizeId(sessionId);
|
|
40376
40596
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40377
40597
|
const data = this.prettyPrint ? JSON.stringify(stored, null, 2) : JSON.stringify(stored);
|
|
40378
|
-
await
|
|
40598
|
+
await fs16.promises.writeFile(filePath, data, "utf-8");
|
|
40379
40599
|
await this.updateIndex(stored);
|
|
40380
40600
|
}
|
|
40381
40601
|
/**
|
|
@@ -40396,13 +40616,13 @@ var FileContextStorage = class {
|
|
|
40396
40616
|
*/
|
|
40397
40617
|
async rebuildIndex() {
|
|
40398
40618
|
await this.ensureDirectory();
|
|
40399
|
-
const files = await
|
|
40619
|
+
const files = await fs16.promises.readdir(this.sessionsDirectory);
|
|
40400
40620
|
const sessionFiles = files.filter((f) => f.endsWith(".json") && !f.startsWith("_"));
|
|
40401
40621
|
const entries = [];
|
|
40402
40622
|
for (const file of sessionFiles) {
|
|
40403
40623
|
try {
|
|
40404
|
-
const filePath =
|
|
40405
|
-
const data = await
|
|
40624
|
+
const filePath = path2.join(this.sessionsDirectory, file);
|
|
40625
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40406
40626
|
const stored = JSON.parse(data);
|
|
40407
40627
|
entries.push(this.storedToIndexEntry(stored));
|
|
40408
40628
|
} catch {
|
|
@@ -40420,11 +40640,11 @@ var FileContextStorage = class {
|
|
|
40420
40640
|
// Private Helpers
|
|
40421
40641
|
// ==========================================================================
|
|
40422
40642
|
getFilePath(sanitizedSessionId) {
|
|
40423
|
-
return
|
|
40643
|
+
return path2.join(this.sessionsDirectory, `${sanitizedSessionId}.json`);
|
|
40424
40644
|
}
|
|
40425
40645
|
async ensureDirectory() {
|
|
40426
40646
|
try {
|
|
40427
|
-
await
|
|
40647
|
+
await fs16.promises.mkdir(this.sessionsDirectory, { recursive: true });
|
|
40428
40648
|
} catch (error) {
|
|
40429
40649
|
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
40430
40650
|
throw error;
|
|
@@ -40434,7 +40654,7 @@ var FileContextStorage = class {
|
|
|
40434
40654
|
async loadRaw(sanitizedSessionId) {
|
|
40435
40655
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40436
40656
|
try {
|
|
40437
|
-
const data = await
|
|
40657
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40438
40658
|
return JSON.parse(data);
|
|
40439
40659
|
} catch (error) {
|
|
40440
40660
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -40452,7 +40672,7 @@ var FileContextStorage = class {
|
|
|
40452
40672
|
return this.index;
|
|
40453
40673
|
}
|
|
40454
40674
|
try {
|
|
40455
|
-
const data = await
|
|
40675
|
+
const data = await fs16.promises.readFile(this.indexPath, "utf-8");
|
|
40456
40676
|
this.index = JSON.parse(data);
|
|
40457
40677
|
return this.index;
|
|
40458
40678
|
} catch (error) {
|
|
@@ -40473,7 +40693,7 @@ var FileContextStorage = class {
|
|
|
40473
40693
|
await this.ensureDirectory();
|
|
40474
40694
|
this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
40475
40695
|
const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
|
|
40476
|
-
await
|
|
40696
|
+
await fs16.promises.writeFile(this.indexPath, data, "utf-8");
|
|
40477
40697
|
}
|
|
40478
40698
|
async updateIndex(stored) {
|
|
40479
40699
|
const index = await this.loadIndex();
|
|
@@ -40511,10 +40731,10 @@ function getDefaultBaseDirectory3() {
|
|
|
40511
40731
|
if (platform2 === "win32") {
|
|
40512
40732
|
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
40513
40733
|
if (appData) {
|
|
40514
|
-
return
|
|
40734
|
+
return path2.join(appData, "oneringai", "agents");
|
|
40515
40735
|
}
|
|
40516
40736
|
}
|
|
40517
|
-
return
|
|
40737
|
+
return path2.join(os2.homedir(), ".oneringai", "agents");
|
|
40518
40738
|
}
|
|
40519
40739
|
function sanitizeAgentId2(agentId) {
|
|
40520
40740
|
return agentId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
|
|
@@ -40527,15 +40747,15 @@ var FileAgentDefinitionStorage = class {
|
|
|
40527
40747
|
constructor(config = {}) {
|
|
40528
40748
|
this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory3();
|
|
40529
40749
|
this.prettyPrint = config.prettyPrint ?? true;
|
|
40530
|
-
this.indexPath =
|
|
40750
|
+
this.indexPath = path2.join(this.baseDirectory, "_agents_index.json");
|
|
40531
40751
|
}
|
|
40532
40752
|
/**
|
|
40533
40753
|
* Save an agent definition
|
|
40534
40754
|
*/
|
|
40535
40755
|
async save(definition) {
|
|
40536
40756
|
const sanitizedId = sanitizeAgentId2(definition.agentId);
|
|
40537
|
-
const agentDir =
|
|
40538
|
-
const filePath =
|
|
40757
|
+
const agentDir = path2.join(this.baseDirectory, sanitizedId);
|
|
40758
|
+
const filePath = path2.join(agentDir, "definition.json");
|
|
40539
40759
|
await this.ensureDirectory(agentDir);
|
|
40540
40760
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
40541
40761
|
if (!definition.createdAt) {
|
|
@@ -40547,11 +40767,11 @@ var FileAgentDefinitionStorage = class {
|
|
|
40547
40767
|
const data = this.prettyPrint ? JSON.stringify(definition, null, 2) : JSON.stringify(definition);
|
|
40548
40768
|
const tempPath = `${filePath}.tmp`;
|
|
40549
40769
|
try {
|
|
40550
|
-
await
|
|
40551
|
-
await
|
|
40770
|
+
await fs16.promises.writeFile(tempPath, data, "utf-8");
|
|
40771
|
+
await fs16.promises.rename(tempPath, filePath);
|
|
40552
40772
|
} catch (error) {
|
|
40553
40773
|
try {
|
|
40554
|
-
await
|
|
40774
|
+
await fs16.promises.unlink(tempPath);
|
|
40555
40775
|
} catch {
|
|
40556
40776
|
}
|
|
40557
40777
|
throw error;
|
|
@@ -40570,10 +40790,10 @@ var FileAgentDefinitionStorage = class {
|
|
|
40570
40790
|
*/
|
|
40571
40791
|
async delete(agentId) {
|
|
40572
40792
|
const sanitizedId = sanitizeAgentId2(agentId);
|
|
40573
|
-
const agentDir =
|
|
40574
|
-
const filePath =
|
|
40793
|
+
const agentDir = path2.join(this.baseDirectory, sanitizedId);
|
|
40794
|
+
const filePath = path2.join(agentDir, "definition.json");
|
|
40575
40795
|
try {
|
|
40576
|
-
await
|
|
40796
|
+
await fs16.promises.unlink(filePath);
|
|
40577
40797
|
} catch (error) {
|
|
40578
40798
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
40579
40799
|
throw error;
|
|
@@ -40586,9 +40806,9 @@ var FileAgentDefinitionStorage = class {
|
|
|
40586
40806
|
*/
|
|
40587
40807
|
async exists(agentId) {
|
|
40588
40808
|
const sanitizedId = sanitizeAgentId2(agentId);
|
|
40589
|
-
const filePath =
|
|
40809
|
+
const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
|
|
40590
40810
|
try {
|
|
40591
|
-
await
|
|
40811
|
+
await fs16.promises.access(filePath);
|
|
40592
40812
|
return true;
|
|
40593
40813
|
} catch {
|
|
40594
40814
|
return false;
|
|
@@ -40650,13 +40870,13 @@ var FileAgentDefinitionStorage = class {
|
|
|
40650
40870
|
*/
|
|
40651
40871
|
async rebuildIndex() {
|
|
40652
40872
|
await this.ensureDirectory(this.baseDirectory);
|
|
40653
|
-
const entries = await
|
|
40873
|
+
const entries = await fs16.promises.readdir(this.baseDirectory, { withFileTypes: true });
|
|
40654
40874
|
const agentDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith("_"));
|
|
40655
40875
|
const indexEntries = [];
|
|
40656
40876
|
for (const dir of agentDirs) {
|
|
40657
40877
|
try {
|
|
40658
|
-
const filePath =
|
|
40659
|
-
const data = await
|
|
40878
|
+
const filePath = path2.join(this.baseDirectory, dir.name, "definition.json");
|
|
40879
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40660
40880
|
const definition = JSON.parse(data);
|
|
40661
40881
|
indexEntries.push(this.definitionToIndexEntry(definition));
|
|
40662
40882
|
} catch {
|
|
@@ -40674,7 +40894,7 @@ var FileAgentDefinitionStorage = class {
|
|
|
40674
40894
|
// ==========================================================================
|
|
40675
40895
|
async ensureDirectory(dir) {
|
|
40676
40896
|
try {
|
|
40677
|
-
await
|
|
40897
|
+
await fs16.promises.mkdir(dir, { recursive: true });
|
|
40678
40898
|
} catch (error) {
|
|
40679
40899
|
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
40680
40900
|
throw error;
|
|
@@ -40682,9 +40902,9 @@ var FileAgentDefinitionStorage = class {
|
|
|
40682
40902
|
}
|
|
40683
40903
|
}
|
|
40684
40904
|
async loadRaw(sanitizedId) {
|
|
40685
|
-
const filePath =
|
|
40905
|
+
const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
|
|
40686
40906
|
try {
|
|
40687
|
-
const data = await
|
|
40907
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40688
40908
|
return JSON.parse(data);
|
|
40689
40909
|
} catch (error) {
|
|
40690
40910
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -40702,7 +40922,7 @@ var FileAgentDefinitionStorage = class {
|
|
|
40702
40922
|
return this.index;
|
|
40703
40923
|
}
|
|
40704
40924
|
try {
|
|
40705
|
-
const data = await
|
|
40925
|
+
const data = await fs16.promises.readFile(this.indexPath, "utf-8");
|
|
40706
40926
|
this.index = JSON.parse(data);
|
|
40707
40927
|
return this.index;
|
|
40708
40928
|
} catch (error) {
|
|
@@ -40722,7 +40942,7 @@ var FileAgentDefinitionStorage = class {
|
|
|
40722
40942
|
await this.ensureDirectory(this.baseDirectory);
|
|
40723
40943
|
this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
40724
40944
|
const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
|
|
40725
|
-
await
|
|
40945
|
+
await fs16.promises.writeFile(this.indexPath, data, "utf-8");
|
|
40726
40946
|
}
|
|
40727
40947
|
async updateIndex(definition) {
|
|
40728
40948
|
const index = await this.loadIndex();
|
|
@@ -40755,6 +40975,126 @@ var FileAgentDefinitionStorage = class {
|
|
|
40755
40975
|
function createFileAgentDefinitionStorage(config) {
|
|
40756
40976
|
return new FileAgentDefinitionStorage(config);
|
|
40757
40977
|
}
|
|
40978
|
+
var MIME_TYPES = {
|
|
40979
|
+
png: "image/png",
|
|
40980
|
+
jpeg: "image/jpeg",
|
|
40981
|
+
jpg: "image/jpeg",
|
|
40982
|
+
webp: "image/webp",
|
|
40983
|
+
gif: "image/gif",
|
|
40984
|
+
mp4: "video/mp4",
|
|
40985
|
+
webm: "video/webm",
|
|
40986
|
+
mp3: "audio/mpeg",
|
|
40987
|
+
wav: "audio/wav",
|
|
40988
|
+
opus: "audio/opus",
|
|
40989
|
+
ogg: "audio/ogg",
|
|
40990
|
+
aac: "audio/aac",
|
|
40991
|
+
flac: "audio/flac",
|
|
40992
|
+
pcm: "audio/pcm"
|
|
40993
|
+
};
|
|
40994
|
+
var MEDIA_TYPE_PREFIXES = ["image", "video", "audio"];
|
|
40995
|
+
var FileMediaStorage = class {
|
|
40996
|
+
outputDir;
|
|
40997
|
+
initialized = false;
|
|
40998
|
+
constructor(config) {
|
|
40999
|
+
this.outputDir = config?.outputDir ?? path2__namespace.join(os2__namespace.tmpdir(), "oneringai-media");
|
|
41000
|
+
}
|
|
41001
|
+
async save(data, metadata) {
|
|
41002
|
+
const dir = metadata.userId ? path2__namespace.join(this.outputDir, metadata.userId) : this.outputDir;
|
|
41003
|
+
await fs15__namespace.mkdir(dir, { recursive: true });
|
|
41004
|
+
const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
|
|
41005
|
+
const filePath = path2__namespace.join(dir, filename);
|
|
41006
|
+
await fs15__namespace.writeFile(filePath, data);
|
|
41007
|
+
const format = metadata.format.toLowerCase();
|
|
41008
|
+
const mimeType = MIME_TYPES[format] ?? "application/octet-stream";
|
|
41009
|
+
return {
|
|
41010
|
+
location: filePath,
|
|
41011
|
+
mimeType,
|
|
41012
|
+
size: data.length
|
|
41013
|
+
};
|
|
41014
|
+
}
|
|
41015
|
+
async read(location) {
|
|
41016
|
+
try {
|
|
41017
|
+
return await fs15__namespace.readFile(location);
|
|
41018
|
+
} catch (err) {
|
|
41019
|
+
if (err.code === "ENOENT") {
|
|
41020
|
+
return null;
|
|
41021
|
+
}
|
|
41022
|
+
throw err;
|
|
41023
|
+
}
|
|
41024
|
+
}
|
|
41025
|
+
async delete(location) {
|
|
41026
|
+
try {
|
|
41027
|
+
await fs15__namespace.unlink(location);
|
|
41028
|
+
} catch (err) {
|
|
41029
|
+
if (err.code === "ENOENT") {
|
|
41030
|
+
return;
|
|
41031
|
+
}
|
|
41032
|
+
throw err;
|
|
41033
|
+
}
|
|
41034
|
+
}
|
|
41035
|
+
async exists(location) {
|
|
41036
|
+
try {
|
|
41037
|
+
await fs15__namespace.access(location);
|
|
41038
|
+
return true;
|
|
41039
|
+
} catch {
|
|
41040
|
+
return false;
|
|
41041
|
+
}
|
|
41042
|
+
}
|
|
41043
|
+
async list(options) {
|
|
41044
|
+
await this.ensureDir();
|
|
41045
|
+
let entries = [];
|
|
41046
|
+
const files = await fs15__namespace.readdir(this.outputDir);
|
|
41047
|
+
for (const file of files) {
|
|
41048
|
+
const filePath = path2__namespace.join(this.outputDir, file);
|
|
41049
|
+
try {
|
|
41050
|
+
const stat6 = await fs15__namespace.stat(filePath);
|
|
41051
|
+
if (!stat6.isFile()) continue;
|
|
41052
|
+
const ext = path2__namespace.extname(file).slice(1).toLowerCase();
|
|
41053
|
+
const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
41054
|
+
let type;
|
|
41055
|
+
for (const prefix of MEDIA_TYPE_PREFIXES) {
|
|
41056
|
+
if (file.startsWith(`${prefix}_`)) {
|
|
41057
|
+
type = prefix;
|
|
41058
|
+
break;
|
|
41059
|
+
}
|
|
41060
|
+
}
|
|
41061
|
+
entries.push({
|
|
41062
|
+
location: filePath,
|
|
41063
|
+
mimeType,
|
|
41064
|
+
size: stat6.size,
|
|
41065
|
+
type,
|
|
41066
|
+
createdAt: stat6.birthtime
|
|
41067
|
+
});
|
|
41068
|
+
} catch {
|
|
41069
|
+
}
|
|
41070
|
+
}
|
|
41071
|
+
if (options?.type) {
|
|
41072
|
+
entries = entries.filter((e) => e.type === options.type);
|
|
41073
|
+
}
|
|
41074
|
+
entries.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
41075
|
+
const offset = options?.offset ?? 0;
|
|
41076
|
+
const limit = options?.limit ?? entries.length;
|
|
41077
|
+
return entries.slice(offset, offset + limit);
|
|
41078
|
+
}
|
|
41079
|
+
getPath() {
|
|
41080
|
+
return this.outputDir;
|
|
41081
|
+
}
|
|
41082
|
+
generateFilename(metadata) {
|
|
41083
|
+
const timestamp = Date.now();
|
|
41084
|
+
const random2 = crypto2__namespace.randomBytes(4).toString("hex");
|
|
41085
|
+
const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
|
|
41086
|
+
return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
|
|
41087
|
+
}
|
|
41088
|
+
async ensureDir() {
|
|
41089
|
+
if (!this.initialized) {
|
|
41090
|
+
await fs15__namespace.mkdir(this.outputDir, { recursive: true });
|
|
41091
|
+
this.initialized = true;
|
|
41092
|
+
}
|
|
41093
|
+
}
|
|
41094
|
+
};
|
|
41095
|
+
function createFileMediaStorage(config) {
|
|
41096
|
+
return new FileMediaStorage(config);
|
|
41097
|
+
}
|
|
40758
41098
|
|
|
40759
41099
|
// src/capabilities/agents/StreamHelpers.ts
|
|
40760
41100
|
var StreamHelpers = class {
|
|
@@ -41677,7 +42017,7 @@ var ConnectorTools = class {
|
|
|
41677
42017
|
static createGenericAPITool(connector, options) {
|
|
41678
42018
|
const toolName = options?.toolName ?? `${connector.name}_api`;
|
|
41679
42019
|
const userId = options?.userId;
|
|
41680
|
-
const description = options?.description ?? `Make an authenticated API call to ${connector.displayName}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}
|
|
42020
|
+
const description = options?.description ?? `Make an authenticated API call to ${connector.displayName}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}.` : " Provide full URL in endpoint.") + ' IMPORTANT: For POST/PUT/PATCH requests, pass data in the "body" parameter as a JSON object, NOT as query string parameters in the endpoint URL. The body is sent as application/json.';
|
|
41681
42021
|
return {
|
|
41682
42022
|
definition: {
|
|
41683
42023
|
type: "function",
|
|
@@ -41694,15 +42034,15 @@ var ConnectorTools = class {
|
|
|
41694
42034
|
},
|
|
41695
42035
|
endpoint: {
|
|
41696
42036
|
type: "string",
|
|
41697
|
-
description:
|
|
42037
|
+
description: 'API endpoint path (relative to base URL) or full URL. Do NOT put request data as query parameters here for POST/PUT/PATCH \u2014 use the "body" parameter instead.'
|
|
41698
42038
|
},
|
|
41699
42039
|
body: {
|
|
41700
42040
|
type: "object",
|
|
41701
|
-
description:
|
|
42041
|
+
description: 'JSON request body for POST/PUT/PATCH requests. ALWAYS use this for sending data (e.g., {"channel": "C123", "text": "hello"}) instead of query string parameters.'
|
|
41702
42042
|
},
|
|
41703
42043
|
queryParams: {
|
|
41704
42044
|
type: "object",
|
|
41705
|
-
description:
|
|
42045
|
+
description: 'URL query parameters (for filtering/pagination on GET requests). Do NOT use for POST/PUT/PATCH data \u2014 use "body" instead.'
|
|
41706
42046
|
},
|
|
41707
42047
|
headers: {
|
|
41708
42048
|
type: "object",
|
|
@@ -41767,7 +42107,10 @@ var ConnectorTools = class {
|
|
|
41767
42107
|
};
|
|
41768
42108
|
}
|
|
41769
42109
|
},
|
|
41770
|
-
describeCall: (args) =>
|
|
42110
|
+
describeCall: (args) => {
|
|
42111
|
+
const bodyInfo = args.body ? ` body=${JSON.stringify(args.body).slice(0, 100)}` : "";
|
|
42112
|
+
return `${args.method} ${args.endpoint}${bodyInfo}`;
|
|
42113
|
+
},
|
|
41771
42114
|
permission: options?.permission ?? {
|
|
41772
42115
|
scope: "session",
|
|
41773
42116
|
riskLevel: "medium",
|
|
@@ -41802,8 +42145,8 @@ var FileStorage = class {
|
|
|
41802
42145
|
}
|
|
41803
42146
|
async ensureDirectory() {
|
|
41804
42147
|
try {
|
|
41805
|
-
await
|
|
41806
|
-
await
|
|
42148
|
+
await fs15__namespace.mkdir(this.directory, { recursive: true });
|
|
42149
|
+
await fs15__namespace.chmod(this.directory, 448);
|
|
41807
42150
|
} catch (error) {
|
|
41808
42151
|
}
|
|
41809
42152
|
}
|
|
@@ -41812,20 +42155,20 @@ var FileStorage = class {
|
|
|
41812
42155
|
*/
|
|
41813
42156
|
getFilePath(key) {
|
|
41814
42157
|
const hash = crypto2__namespace.createHash("sha256").update(key).digest("hex");
|
|
41815
|
-
return
|
|
42158
|
+
return path2__namespace.join(this.directory, `${hash}.token`);
|
|
41816
42159
|
}
|
|
41817
42160
|
async storeToken(key, token) {
|
|
41818
42161
|
await this.ensureDirectory();
|
|
41819
42162
|
const filePath = this.getFilePath(key);
|
|
41820
42163
|
const plaintext = JSON.stringify(token);
|
|
41821
42164
|
const encrypted = encrypt(plaintext, this.encryptionKey);
|
|
41822
|
-
await
|
|
41823
|
-
await
|
|
42165
|
+
await fs15__namespace.writeFile(filePath, encrypted, "utf8");
|
|
42166
|
+
await fs15__namespace.chmod(filePath, 384);
|
|
41824
42167
|
}
|
|
41825
42168
|
async getToken(key) {
|
|
41826
42169
|
const filePath = this.getFilePath(key);
|
|
41827
42170
|
try {
|
|
41828
|
-
const encrypted = await
|
|
42171
|
+
const encrypted = await fs15__namespace.readFile(filePath, "utf8");
|
|
41829
42172
|
const decrypted = decrypt(encrypted, this.encryptionKey);
|
|
41830
42173
|
return JSON.parse(decrypted);
|
|
41831
42174
|
} catch (error) {
|
|
@@ -41834,7 +42177,7 @@ var FileStorage = class {
|
|
|
41834
42177
|
}
|
|
41835
42178
|
console.error("Failed to read/decrypt token file:", error);
|
|
41836
42179
|
try {
|
|
41837
|
-
await
|
|
42180
|
+
await fs15__namespace.unlink(filePath);
|
|
41838
42181
|
} catch {
|
|
41839
42182
|
}
|
|
41840
42183
|
return null;
|
|
@@ -41843,7 +42186,7 @@ var FileStorage = class {
|
|
|
41843
42186
|
async deleteToken(key) {
|
|
41844
42187
|
const filePath = this.getFilePath(key);
|
|
41845
42188
|
try {
|
|
41846
|
-
await
|
|
42189
|
+
await fs15__namespace.unlink(filePath);
|
|
41847
42190
|
} catch (error) {
|
|
41848
42191
|
if (error.code !== "ENOENT") {
|
|
41849
42192
|
throw error;
|
|
@@ -41853,7 +42196,7 @@ var FileStorage = class {
|
|
|
41853
42196
|
async hasToken(key) {
|
|
41854
42197
|
const filePath = this.getFilePath(key);
|
|
41855
42198
|
try {
|
|
41856
|
-
await
|
|
42199
|
+
await fs15__namespace.access(filePath);
|
|
41857
42200
|
return true;
|
|
41858
42201
|
} catch {
|
|
41859
42202
|
return false;
|
|
@@ -41864,7 +42207,7 @@ var FileStorage = class {
|
|
|
41864
42207
|
*/
|
|
41865
42208
|
async listTokens() {
|
|
41866
42209
|
try {
|
|
41867
|
-
const files = await
|
|
42210
|
+
const files = await fs15__namespace.readdir(this.directory);
|
|
41868
42211
|
return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
|
|
41869
42212
|
} catch {
|
|
41870
42213
|
return [];
|
|
@@ -41875,10 +42218,10 @@ var FileStorage = class {
|
|
|
41875
42218
|
*/
|
|
41876
42219
|
async clearAll() {
|
|
41877
42220
|
try {
|
|
41878
|
-
const files = await
|
|
42221
|
+
const files = await fs15__namespace.readdir(this.directory);
|
|
41879
42222
|
const tokenFiles = files.filter((f) => f.endsWith(".token"));
|
|
41880
42223
|
await Promise.all(
|
|
41881
|
-
tokenFiles.map((f) =>
|
|
42224
|
+
tokenFiles.map((f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
|
|
41882
42225
|
}))
|
|
41883
42226
|
);
|
|
41884
42227
|
} catch {
|
|
@@ -42146,22 +42489,26 @@ var ConnectorConfigStore = class {
|
|
|
42146
42489
|
* Encrypt secrets in ConnectorAuth based on auth type
|
|
42147
42490
|
*/
|
|
42148
42491
|
encryptAuthSecrets(auth2) {
|
|
42492
|
+
const encryptedExtra = this.encryptExtra(auth2.extra);
|
|
42149
42493
|
switch (auth2.type) {
|
|
42150
42494
|
case "api_key":
|
|
42151
42495
|
return {
|
|
42152
42496
|
...auth2,
|
|
42153
|
-
apiKey: this.encryptValue(auth2.apiKey)
|
|
42497
|
+
apiKey: this.encryptValue(auth2.apiKey),
|
|
42498
|
+
...encryptedExtra ? { extra: encryptedExtra } : {}
|
|
42154
42499
|
};
|
|
42155
42500
|
case "oauth":
|
|
42156
42501
|
return {
|
|
42157
42502
|
...auth2,
|
|
42158
42503
|
clientSecret: auth2.clientSecret ? this.encryptValue(auth2.clientSecret) : void 0,
|
|
42159
|
-
privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0
|
|
42504
|
+
privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0,
|
|
42505
|
+
...encryptedExtra ? { extra: encryptedExtra } : {}
|
|
42160
42506
|
};
|
|
42161
42507
|
case "jwt":
|
|
42162
42508
|
return {
|
|
42163
42509
|
...auth2,
|
|
42164
|
-
privateKey: this.encryptValue(auth2.privateKey)
|
|
42510
|
+
privateKey: this.encryptValue(auth2.privateKey),
|
|
42511
|
+
...encryptedExtra ? { extra: encryptedExtra } : {}
|
|
42165
42512
|
};
|
|
42166
42513
|
default:
|
|
42167
42514
|
return auth2;
|
|
@@ -42171,27 +42518,53 @@ var ConnectorConfigStore = class {
|
|
|
42171
42518
|
* Decrypt secrets in ConnectorAuth based on auth type
|
|
42172
42519
|
*/
|
|
42173
42520
|
decryptAuthSecrets(auth2) {
|
|
42521
|
+
const decryptedExtra = this.decryptExtra(auth2.extra);
|
|
42174
42522
|
switch (auth2.type) {
|
|
42175
42523
|
case "api_key":
|
|
42176
42524
|
return {
|
|
42177
42525
|
...auth2,
|
|
42178
|
-
apiKey: this.decryptValue(auth2.apiKey)
|
|
42526
|
+
apiKey: this.decryptValue(auth2.apiKey),
|
|
42527
|
+
...decryptedExtra ? { extra: decryptedExtra } : {}
|
|
42179
42528
|
};
|
|
42180
42529
|
case "oauth":
|
|
42181
42530
|
return {
|
|
42182
42531
|
...auth2,
|
|
42183
42532
|
clientSecret: auth2.clientSecret ? this.decryptValue(auth2.clientSecret) : void 0,
|
|
42184
|
-
privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0
|
|
42533
|
+
privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0,
|
|
42534
|
+
...decryptedExtra ? { extra: decryptedExtra } : {}
|
|
42185
42535
|
};
|
|
42186
42536
|
case "jwt":
|
|
42187
42537
|
return {
|
|
42188
42538
|
...auth2,
|
|
42189
|
-
privateKey: this.decryptValue(auth2.privateKey)
|
|
42539
|
+
privateKey: this.decryptValue(auth2.privateKey),
|
|
42540
|
+
...decryptedExtra ? { extra: decryptedExtra } : {}
|
|
42190
42541
|
};
|
|
42191
42542
|
default:
|
|
42192
42543
|
return auth2;
|
|
42193
42544
|
}
|
|
42194
42545
|
}
|
|
42546
|
+
/**
|
|
42547
|
+
* Encrypt all values in an extra Record (vendor-specific credentials)
|
|
42548
|
+
*/
|
|
42549
|
+
encryptExtra(extra) {
|
|
42550
|
+
if (!extra || Object.keys(extra).length === 0) return void 0;
|
|
42551
|
+
const result = {};
|
|
42552
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
42553
|
+
result[key] = this.encryptValue(value);
|
|
42554
|
+
}
|
|
42555
|
+
return result;
|
|
42556
|
+
}
|
|
42557
|
+
/**
|
|
42558
|
+
* Decrypt all values in an extra Record (vendor-specific credentials)
|
|
42559
|
+
*/
|
|
42560
|
+
decryptExtra(extra) {
|
|
42561
|
+
if (!extra || Object.keys(extra).length === 0) return void 0;
|
|
42562
|
+
const result = {};
|
|
42563
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
42564
|
+
result[key] = this.decryptValue(value);
|
|
42565
|
+
}
|
|
42566
|
+
return result;
|
|
42567
|
+
}
|
|
42195
42568
|
/**
|
|
42196
42569
|
* Encrypt a single value if not already encrypted
|
|
42197
42570
|
*/
|
|
@@ -42269,20 +42642,20 @@ var FileConnectorStorage = class {
|
|
|
42269
42642
|
throw new Error("FileConnectorStorage requires a directory path");
|
|
42270
42643
|
}
|
|
42271
42644
|
this.directory = config.directory;
|
|
42272
|
-
this.indexPath =
|
|
42645
|
+
this.indexPath = path2__namespace.join(this.directory, "_index.json");
|
|
42273
42646
|
}
|
|
42274
42647
|
async save(name, stored) {
|
|
42275
42648
|
await this.ensureDirectory();
|
|
42276
42649
|
const filePath = this.getFilePath(name);
|
|
42277
42650
|
const json = JSON.stringify(stored, null, 2);
|
|
42278
|
-
await
|
|
42279
|
-
await
|
|
42651
|
+
await fs15__namespace.writeFile(filePath, json, "utf8");
|
|
42652
|
+
await fs15__namespace.chmod(filePath, 384);
|
|
42280
42653
|
await this.updateIndex(name, "add");
|
|
42281
42654
|
}
|
|
42282
42655
|
async get(name) {
|
|
42283
42656
|
const filePath = this.getFilePath(name);
|
|
42284
42657
|
try {
|
|
42285
|
-
const json = await
|
|
42658
|
+
const json = await fs15__namespace.readFile(filePath, "utf8");
|
|
42286
42659
|
return JSON.parse(json);
|
|
42287
42660
|
} catch (error) {
|
|
42288
42661
|
const err = error;
|
|
@@ -42295,7 +42668,7 @@ var FileConnectorStorage = class {
|
|
|
42295
42668
|
async delete(name) {
|
|
42296
42669
|
const filePath = this.getFilePath(name);
|
|
42297
42670
|
try {
|
|
42298
|
-
await
|
|
42671
|
+
await fs15__namespace.unlink(filePath);
|
|
42299
42672
|
await this.updateIndex(name, "remove");
|
|
42300
42673
|
return true;
|
|
42301
42674
|
} catch (error) {
|
|
@@ -42309,7 +42682,7 @@ var FileConnectorStorage = class {
|
|
|
42309
42682
|
async has(name) {
|
|
42310
42683
|
const filePath = this.getFilePath(name);
|
|
42311
42684
|
try {
|
|
42312
|
-
await
|
|
42685
|
+
await fs15__namespace.access(filePath);
|
|
42313
42686
|
return true;
|
|
42314
42687
|
} catch {
|
|
42315
42688
|
return false;
|
|
@@ -42335,13 +42708,13 @@ var FileConnectorStorage = class {
|
|
|
42335
42708
|
*/
|
|
42336
42709
|
async clear() {
|
|
42337
42710
|
try {
|
|
42338
|
-
const files = await
|
|
42711
|
+
const files = await fs15__namespace.readdir(this.directory);
|
|
42339
42712
|
const connectorFiles = files.filter(
|
|
42340
42713
|
(f) => f.endsWith(".connector.json") || f === "_index.json"
|
|
42341
42714
|
);
|
|
42342
42715
|
await Promise.all(
|
|
42343
42716
|
connectorFiles.map(
|
|
42344
|
-
(f) =>
|
|
42717
|
+
(f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
|
|
42345
42718
|
})
|
|
42346
42719
|
)
|
|
42347
42720
|
);
|
|
@@ -42354,7 +42727,7 @@ var FileConnectorStorage = class {
|
|
|
42354
42727
|
*/
|
|
42355
42728
|
getFilePath(name) {
|
|
42356
42729
|
const hash = this.hashName(name);
|
|
42357
|
-
return
|
|
42730
|
+
return path2__namespace.join(this.directory, `${hash}.connector.json`);
|
|
42358
42731
|
}
|
|
42359
42732
|
/**
|
|
42360
42733
|
* Hash connector name to prevent enumeration
|
|
@@ -42368,8 +42741,8 @@ var FileConnectorStorage = class {
|
|
|
42368
42741
|
async ensureDirectory() {
|
|
42369
42742
|
if (this.initialized) return;
|
|
42370
42743
|
try {
|
|
42371
|
-
await
|
|
42372
|
-
await
|
|
42744
|
+
await fs15__namespace.mkdir(this.directory, { recursive: true });
|
|
42745
|
+
await fs15__namespace.chmod(this.directory, 448);
|
|
42373
42746
|
this.initialized = true;
|
|
42374
42747
|
} catch {
|
|
42375
42748
|
this.initialized = true;
|
|
@@ -42380,7 +42753,7 @@ var FileConnectorStorage = class {
|
|
|
42380
42753
|
*/
|
|
42381
42754
|
async loadIndex() {
|
|
42382
42755
|
try {
|
|
42383
|
-
const json = await
|
|
42756
|
+
const json = await fs15__namespace.readFile(this.indexPath, "utf8");
|
|
42384
42757
|
return JSON.parse(json);
|
|
42385
42758
|
} catch {
|
|
42386
42759
|
return { connectors: {} };
|
|
@@ -42398,8 +42771,8 @@ var FileConnectorStorage = class {
|
|
|
42398
42771
|
delete index.connectors[hash];
|
|
42399
42772
|
}
|
|
42400
42773
|
const json = JSON.stringify(index, null, 2);
|
|
42401
|
-
await
|
|
42402
|
-
await
|
|
42774
|
+
await fs15__namespace.writeFile(this.indexPath, json, "utf8");
|
|
42775
|
+
await fs15__namespace.chmod(this.indexPath, 384);
|
|
42403
42776
|
}
|
|
42404
42777
|
};
|
|
42405
42778
|
|
|
@@ -42444,11 +42817,19 @@ function buildAuthConfig(authTemplate, credentials) {
|
|
|
42444
42817
|
if (!credentials.apiKey) {
|
|
42445
42818
|
throw new Error("API key is required for api_key auth");
|
|
42446
42819
|
}
|
|
42820
|
+
const standardApiKeyFields = /* @__PURE__ */ new Set(["apiKey", "headerName", "headerPrefix"]);
|
|
42821
|
+
const extra = {};
|
|
42822
|
+
for (const field of authTemplate.optionalFields ?? []) {
|
|
42823
|
+
if (!standardApiKeyFields.has(field) && credentials[field]) {
|
|
42824
|
+
extra[field] = credentials[field];
|
|
42825
|
+
}
|
|
42826
|
+
}
|
|
42447
42827
|
return {
|
|
42448
42828
|
type: "api_key",
|
|
42449
42829
|
apiKey: credentials.apiKey,
|
|
42450
42830
|
headerName: defaults.headerName ?? "Authorization",
|
|
42451
|
-
headerPrefix: defaults.headerPrefix ?? "Bearer"
|
|
42831
|
+
headerPrefix: defaults.headerPrefix ?? "Bearer",
|
|
42832
|
+
...Object.keys(extra).length > 0 ? { extra } : {}
|
|
42452
42833
|
};
|
|
42453
42834
|
}
|
|
42454
42835
|
if (!authTemplate.flow) {
|
|
@@ -42718,8 +43099,9 @@ var slackTemplate = {
|
|
|
42718
43099
|
id: "bot-token",
|
|
42719
43100
|
name: "Bot Token",
|
|
42720
43101
|
type: "api_key",
|
|
42721
|
-
description: "Internal workspace bot - get from OAuth & Permissions page of your Slack app",
|
|
43102
|
+
description: "Internal workspace bot - get from OAuth & Permissions page of your Slack app. For Socket Mode bots, also provide appToken and signingSecret in extra fields.",
|
|
42722
43103
|
requiredFields: ["apiKey"],
|
|
43104
|
+
optionalFields: ["appToken", "signingSecret"],
|
|
42723
43105
|
defaults: {
|
|
42724
43106
|
type: "api_key",
|
|
42725
43107
|
headerName: "Authorization",
|
|
@@ -44557,14 +44939,14 @@ function createMessageWithImages(text, imageUrls, role = "user" /* USER */) {
|
|
|
44557
44939
|
var execAsync = util.promisify(child_process.exec);
|
|
44558
44940
|
function cleanupTempFile(filePath) {
|
|
44559
44941
|
try {
|
|
44560
|
-
if (
|
|
44561
|
-
|
|
44942
|
+
if (fs16__namespace.existsSync(filePath)) {
|
|
44943
|
+
fs16__namespace.unlinkSync(filePath);
|
|
44562
44944
|
}
|
|
44563
44945
|
} catch {
|
|
44564
44946
|
}
|
|
44565
44947
|
}
|
|
44566
44948
|
async function readClipboardImage() {
|
|
44567
|
-
const platform2 =
|
|
44949
|
+
const platform2 = os2__namespace.platform();
|
|
44568
44950
|
try {
|
|
44569
44951
|
switch (platform2) {
|
|
44570
44952
|
case "darwin":
|
|
@@ -44587,7 +44969,7 @@ async function readClipboardImage() {
|
|
|
44587
44969
|
}
|
|
44588
44970
|
}
|
|
44589
44971
|
async function readClipboardImageMac() {
|
|
44590
|
-
const tempFile =
|
|
44972
|
+
const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
|
|
44591
44973
|
try {
|
|
44592
44974
|
try {
|
|
44593
44975
|
await execAsync(`pngpaste "${tempFile}"`);
|
|
@@ -44609,7 +44991,7 @@ async function readClipboardImageMac() {
|
|
|
44609
44991
|
end try
|
|
44610
44992
|
`;
|
|
44611
44993
|
const { stdout } = await execAsync(`osascript -e '${script}'`);
|
|
44612
|
-
if (stdout.includes("success") ||
|
|
44994
|
+
if (stdout.includes("success") || fs16__namespace.existsSync(tempFile)) {
|
|
44613
44995
|
return await convertFileToDataUri(tempFile);
|
|
44614
44996
|
}
|
|
44615
44997
|
return {
|
|
@@ -44622,18 +45004,18 @@ async function readClipboardImageMac() {
|
|
|
44622
45004
|
}
|
|
44623
45005
|
}
|
|
44624
45006
|
async function readClipboardImageLinux() {
|
|
44625
|
-
const tempFile =
|
|
45007
|
+
const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
|
|
44626
45008
|
try {
|
|
44627
45009
|
try {
|
|
44628
45010
|
await execAsync(`xclip -selection clipboard -t image/png -o > "${tempFile}"`);
|
|
44629
|
-
if (
|
|
45011
|
+
if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
|
|
44630
45012
|
return await convertFileToDataUri(tempFile);
|
|
44631
45013
|
}
|
|
44632
45014
|
} catch {
|
|
44633
45015
|
}
|
|
44634
45016
|
try {
|
|
44635
45017
|
await execAsync(`wl-paste -t image/png > "${tempFile}"`);
|
|
44636
|
-
if (
|
|
45018
|
+
if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
|
|
44637
45019
|
return await convertFileToDataUri(tempFile);
|
|
44638
45020
|
}
|
|
44639
45021
|
} catch {
|
|
@@ -44647,7 +45029,7 @@ async function readClipboardImageLinux() {
|
|
|
44647
45029
|
}
|
|
44648
45030
|
}
|
|
44649
45031
|
async function readClipboardImageWindows() {
|
|
44650
|
-
const tempFile =
|
|
45032
|
+
const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
|
|
44651
45033
|
try {
|
|
44652
45034
|
const psScript = `
|
|
44653
45035
|
Add-Type -AssemblyName System.Windows.Forms;
|
|
@@ -44660,7 +45042,7 @@ async function readClipboardImageWindows() {
|
|
|
44660
45042
|
}
|
|
44661
45043
|
`;
|
|
44662
45044
|
await execAsync(`powershell -Command "${psScript}"`);
|
|
44663
|
-
if (
|
|
45045
|
+
if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
|
|
44664
45046
|
return await convertFileToDataUri(tempFile);
|
|
44665
45047
|
}
|
|
44666
45048
|
return {
|
|
@@ -44673,7 +45055,7 @@ async function readClipboardImageWindows() {
|
|
|
44673
45055
|
}
|
|
44674
45056
|
async function convertFileToDataUri(filePath) {
|
|
44675
45057
|
try {
|
|
44676
|
-
const imageBuffer =
|
|
45058
|
+
const imageBuffer = fs16__namespace.readFileSync(filePath);
|
|
44677
45059
|
const base64Image = imageBuffer.toString("base64");
|
|
44678
45060
|
const magic = imageBuffer.slice(0, 4).toString("hex");
|
|
44679
45061
|
let mimeType = "image/png";
|
|
@@ -44700,7 +45082,7 @@ async function convertFileToDataUri(filePath) {
|
|
|
44700
45082
|
}
|
|
44701
45083
|
}
|
|
44702
45084
|
async function hasClipboardImage() {
|
|
44703
|
-
const platform2 =
|
|
45085
|
+
const platform2 = os2__namespace.platform();
|
|
44704
45086
|
try {
|
|
44705
45087
|
switch (platform2) {
|
|
44706
45088
|
case "darwin":
|
|
@@ -44918,17 +45300,24 @@ __export(tools_exports, {
|
|
|
44918
45300
|
ConnectorTools: () => ConnectorTools,
|
|
44919
45301
|
DEFAULT_FILESYSTEM_CONFIG: () => DEFAULT_FILESYSTEM_CONFIG,
|
|
44920
45302
|
DEFAULT_SHELL_CONFIG: () => DEFAULT_SHELL_CONFIG,
|
|
44921
|
-
FileMediaOutputHandler: () =>
|
|
45303
|
+
FileMediaOutputHandler: () => FileMediaStorage,
|
|
44922
45304
|
ToolRegistry: () => ToolRegistry,
|
|
44923
45305
|
bash: () => bash,
|
|
44924
45306
|
createBashTool: () => createBashTool,
|
|
45307
|
+
createCreatePRTool: () => createCreatePRTool,
|
|
44925
45308
|
createEditFileTool: () => createEditFileTool,
|
|
44926
45309
|
createExecuteJavaScriptTool: () => createExecuteJavaScriptTool,
|
|
45310
|
+
createGetPRTool: () => createGetPRTool,
|
|
45311
|
+
createGitHubReadFileTool: () => createGitHubReadFileTool,
|
|
44927
45312
|
createGlobTool: () => createGlobTool,
|
|
44928
45313
|
createGrepTool: () => createGrepTool,
|
|
44929
45314
|
createImageGenerationTool: () => createImageGenerationTool,
|
|
44930
45315
|
createListDirectoryTool: () => createListDirectoryTool,
|
|
45316
|
+
createPRCommentsTool: () => createPRCommentsTool,
|
|
45317
|
+
createPRFilesTool: () => createPRFilesTool,
|
|
44931
45318
|
createReadFileTool: () => createReadFileTool,
|
|
45319
|
+
createSearchCodeTool: () => createSearchCodeTool,
|
|
45320
|
+
createSearchFilesTool: () => createSearchFilesTool,
|
|
44932
45321
|
createSpeechToTextTool: () => createSpeechToTextTool,
|
|
44933
45322
|
createTextToSpeechTool: () => createTextToSpeechTool,
|
|
44934
45323
|
createVideoTools: () => createVideoTools,
|
|
@@ -44940,6 +45329,7 @@ __export(tools_exports, {
|
|
|
44940
45329
|
getAllBuiltInTools: () => getAllBuiltInTools,
|
|
44941
45330
|
getBackgroundOutput: () => getBackgroundOutput,
|
|
44942
45331
|
getMediaOutputHandler: () => getMediaOutputHandler,
|
|
45332
|
+
getMediaStorage: () => getMediaStorage,
|
|
44943
45333
|
getToolByName: () => getToolByName,
|
|
44944
45334
|
getToolCategories: () => getToolCategories,
|
|
44945
45335
|
getToolRegistry: () => getToolRegistry,
|
|
@@ -44952,15 +45342,18 @@ __export(tools_exports, {
|
|
|
44952
45342
|
jsonManipulator: () => jsonManipulator,
|
|
44953
45343
|
killBackgroundProcess: () => killBackgroundProcess,
|
|
44954
45344
|
listDirectory: () => listDirectory,
|
|
44955
|
-
|
|
45345
|
+
parseRepository: () => parseRepository,
|
|
45346
|
+
readFile: () => readFile5,
|
|
45347
|
+
resolveRepository: () => resolveRepository,
|
|
44956
45348
|
setMediaOutputHandler: () => setMediaOutputHandler,
|
|
45349
|
+
setMediaStorage: () => setMediaStorage,
|
|
44957
45350
|
toolRegistry: () => toolRegistry,
|
|
44958
45351
|
validatePath: () => validatePath,
|
|
44959
45352
|
webFetch: () => webFetch,
|
|
44960
45353
|
webFetchJS: () => webFetchJS,
|
|
44961
45354
|
webScrape: () => webScrape,
|
|
44962
45355
|
webSearch: () => webSearch,
|
|
44963
|
-
writeFile: () =>
|
|
45356
|
+
writeFile: () => writeFile5
|
|
44964
45357
|
});
|
|
44965
45358
|
var DEFAULT_FILESYSTEM_CONFIG = {
|
|
44966
45359
|
workingDirectory: process.cwd(),
|
|
@@ -45019,15 +45412,15 @@ function validatePath(inputPath, config = {}) {
|
|
|
45019
45412
|
const blockedDirs = config.blockedDirectories || DEFAULT_FILESYSTEM_CONFIG.blockedDirectories;
|
|
45020
45413
|
let expandedPath = inputPath;
|
|
45021
45414
|
if (inputPath.startsWith("~/")) {
|
|
45022
|
-
expandedPath =
|
|
45415
|
+
expandedPath = path2.resolve(os2.homedir(), inputPath.slice(2));
|
|
45023
45416
|
} else if (inputPath === "~") {
|
|
45024
|
-
expandedPath =
|
|
45417
|
+
expandedPath = os2.homedir();
|
|
45025
45418
|
}
|
|
45026
45419
|
let resolvedPath;
|
|
45027
|
-
if (
|
|
45028
|
-
resolvedPath =
|
|
45420
|
+
if (path2.isAbsolute(expandedPath)) {
|
|
45421
|
+
resolvedPath = path2.normalize(expandedPath);
|
|
45029
45422
|
} else {
|
|
45030
|
-
resolvedPath =
|
|
45423
|
+
resolvedPath = path2.resolve(workingDir, expandedPath);
|
|
45031
45424
|
}
|
|
45032
45425
|
const pathSegments = resolvedPath.split("/").filter(Boolean);
|
|
45033
45426
|
for (const blocked of blockedDirs) {
|
|
@@ -45040,7 +45433,7 @@ function validatePath(inputPath, config = {}) {
|
|
|
45040
45433
|
};
|
|
45041
45434
|
}
|
|
45042
45435
|
} else {
|
|
45043
|
-
const blockedPath =
|
|
45436
|
+
const blockedPath = path2.isAbsolute(blocked) ? blocked : path2.resolve(workingDir, blocked);
|
|
45044
45437
|
if (resolvedPath.startsWith(blockedPath + "/") || resolvedPath === blockedPath) {
|
|
45045
45438
|
return {
|
|
45046
45439
|
valid: false,
|
|
@@ -45053,7 +45446,7 @@ function validatePath(inputPath, config = {}) {
|
|
|
45053
45446
|
if (allowedDirs.length > 0) {
|
|
45054
45447
|
let isAllowed = false;
|
|
45055
45448
|
for (const allowed of allowedDirs) {
|
|
45056
|
-
const allowedPath =
|
|
45449
|
+
const allowedPath = path2.isAbsolute(allowed) ? allowed : path2.resolve(workingDir, allowed);
|
|
45057
45450
|
if (resolvedPath.startsWith(allowedPath + "/") || resolvedPath === allowedPath) {
|
|
45058
45451
|
isAllowed = true;
|
|
45059
45452
|
break;
|
|
@@ -45071,9 +45464,9 @@ function validatePath(inputPath, config = {}) {
|
|
|
45071
45464
|
}
|
|
45072
45465
|
function expandTilde(inputPath) {
|
|
45073
45466
|
if (inputPath.startsWith("~/")) {
|
|
45074
|
-
return
|
|
45467
|
+
return path2.resolve(os2.homedir(), inputPath.slice(2));
|
|
45075
45468
|
} else if (inputPath === "~") {
|
|
45076
|
-
return
|
|
45469
|
+
return os2.homedir();
|
|
45077
45470
|
}
|
|
45078
45471
|
return inputPath;
|
|
45079
45472
|
}
|
|
@@ -45148,7 +45541,7 @@ EXAMPLES:
|
|
|
45148
45541
|
};
|
|
45149
45542
|
}
|
|
45150
45543
|
const resolvedPath = validation.resolvedPath;
|
|
45151
|
-
if (!
|
|
45544
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
45152
45545
|
return {
|
|
45153
45546
|
success: false,
|
|
45154
45547
|
error: `File not found: ${file_path}`,
|
|
@@ -45156,7 +45549,7 @@ EXAMPLES:
|
|
|
45156
45549
|
};
|
|
45157
45550
|
}
|
|
45158
45551
|
try {
|
|
45159
|
-
const stats = await
|
|
45552
|
+
const stats = await fs15.stat(resolvedPath);
|
|
45160
45553
|
if (!stats.isFile()) {
|
|
45161
45554
|
return {
|
|
45162
45555
|
success: false,
|
|
@@ -45172,7 +45565,7 @@ EXAMPLES:
|
|
|
45172
45565
|
size: stats.size
|
|
45173
45566
|
};
|
|
45174
45567
|
}
|
|
45175
|
-
const content = await
|
|
45568
|
+
const content = await fs15.readFile(resolvedPath, "utf-8");
|
|
45176
45569
|
const allLines = content.split("\n");
|
|
45177
45570
|
const totalLines = allLines.length;
|
|
45178
45571
|
const startIndex = Math.max(0, offset - 1);
|
|
@@ -45213,7 +45606,7 @@ EXAMPLES:
|
|
|
45213
45606
|
}
|
|
45214
45607
|
};
|
|
45215
45608
|
}
|
|
45216
|
-
var
|
|
45609
|
+
var readFile5 = createReadFileTool();
|
|
45217
45610
|
function createWriteFileTool(config = {}) {
|
|
45218
45611
|
const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
|
|
45219
45612
|
return {
|
|
@@ -45277,13 +45670,13 @@ EXAMPLES:
|
|
|
45277
45670
|
};
|
|
45278
45671
|
}
|
|
45279
45672
|
const resolvedPath = validation.resolvedPath;
|
|
45280
|
-
const fileExists =
|
|
45673
|
+
const fileExists = fs16.existsSync(resolvedPath);
|
|
45281
45674
|
try {
|
|
45282
|
-
const parentDir =
|
|
45283
|
-
if (!
|
|
45284
|
-
await
|
|
45675
|
+
const parentDir = path2.dirname(resolvedPath);
|
|
45676
|
+
if (!fs16.existsSync(parentDir)) {
|
|
45677
|
+
await fs15.mkdir(parentDir, { recursive: true });
|
|
45285
45678
|
}
|
|
45286
|
-
await
|
|
45679
|
+
await fs15.writeFile(resolvedPath, content, "utf-8");
|
|
45287
45680
|
return {
|
|
45288
45681
|
success: true,
|
|
45289
45682
|
path: file_path,
|
|
@@ -45300,7 +45693,7 @@ EXAMPLES:
|
|
|
45300
45693
|
}
|
|
45301
45694
|
};
|
|
45302
45695
|
}
|
|
45303
|
-
var
|
|
45696
|
+
var writeFile5 = createWriteFileTool();
|
|
45304
45697
|
function createEditFileTool(config = {}) {
|
|
45305
45698
|
const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
|
|
45306
45699
|
return {
|
|
@@ -45386,7 +45779,7 @@ EXAMPLES:
|
|
|
45386
45779
|
};
|
|
45387
45780
|
}
|
|
45388
45781
|
const resolvedPath = validation.resolvedPath;
|
|
45389
|
-
if (!
|
|
45782
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
45390
45783
|
return {
|
|
45391
45784
|
success: false,
|
|
45392
45785
|
error: `File not found: ${file_path}`,
|
|
@@ -45394,7 +45787,7 @@ EXAMPLES:
|
|
|
45394
45787
|
};
|
|
45395
45788
|
}
|
|
45396
45789
|
try {
|
|
45397
|
-
const content = await
|
|
45790
|
+
const content = await fs15.readFile(resolvedPath, "utf-8");
|
|
45398
45791
|
let occurrences = 0;
|
|
45399
45792
|
let searchIndex = 0;
|
|
45400
45793
|
while (true) {
|
|
@@ -45433,7 +45826,7 @@ EXAMPLES:
|
|
|
45433
45826
|
} else {
|
|
45434
45827
|
newContent = content.replace(old_string, new_string);
|
|
45435
45828
|
}
|
|
45436
|
-
await
|
|
45829
|
+
await fs15.writeFile(resolvedPath, newContent, "utf-8");
|
|
45437
45830
|
const diffPreview = generateDiffPreview(old_string, new_string);
|
|
45438
45831
|
return {
|
|
45439
45832
|
success: true,
|
|
@@ -45489,11 +45882,11 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
|
|
|
45489
45882
|
return results;
|
|
45490
45883
|
}
|
|
45491
45884
|
try {
|
|
45492
|
-
const entries = await
|
|
45885
|
+
const entries = await fs15.readdir(dir, { withFileTypes: true });
|
|
45493
45886
|
for (const entry of entries) {
|
|
45494
45887
|
if (results.length >= config.maxResults) break;
|
|
45495
|
-
const fullPath =
|
|
45496
|
-
const relativePath =
|
|
45888
|
+
const fullPath = path2.join(dir, entry.name);
|
|
45889
|
+
const relativePath = path2.relative(baseDir, fullPath);
|
|
45497
45890
|
if (entry.isDirectory()) {
|
|
45498
45891
|
const isBlocked = config.blockedDirectories.some(
|
|
45499
45892
|
(blocked) => entry.name === blocked || relativePath.includes(`/${blocked}/`) || relativePath.startsWith(`${blocked}/`)
|
|
@@ -45503,7 +45896,7 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
|
|
|
45503
45896
|
} else if (entry.isFile()) {
|
|
45504
45897
|
if (matchGlobPattern(pattern, relativePath)) {
|
|
45505
45898
|
try {
|
|
45506
|
-
const stats = await
|
|
45899
|
+
const stats = await fs15.stat(fullPath);
|
|
45507
45900
|
results.push({
|
|
45508
45901
|
path: relativePath,
|
|
45509
45902
|
mtime: stats.mtimeMs
|
|
@@ -45585,7 +45978,7 @@ WHEN TO USE:
|
|
|
45585
45978
|
};
|
|
45586
45979
|
}
|
|
45587
45980
|
const resolvedDir = validation.resolvedPath;
|
|
45588
|
-
if (!
|
|
45981
|
+
if (!fs16.existsSync(resolvedDir)) {
|
|
45589
45982
|
return {
|
|
45590
45983
|
success: false,
|
|
45591
45984
|
error: `Directory not found: ${searchDir}`
|
|
@@ -45640,9 +46033,9 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
|
|
|
45640
46033
|
return files;
|
|
45641
46034
|
}
|
|
45642
46035
|
try {
|
|
45643
|
-
const entries = await
|
|
46036
|
+
const entries = await fs15.readdir(dir, { withFileTypes: true });
|
|
45644
46037
|
for (const entry of entries) {
|
|
45645
|
-
const fullPath =
|
|
46038
|
+
const fullPath = path2.join(dir, entry.name);
|
|
45646
46039
|
if (entry.isDirectory()) {
|
|
45647
46040
|
const isBlocked = config.blockedDirectories.some(
|
|
45648
46041
|
(blocked) => entry.name === blocked
|
|
@@ -45654,7 +46047,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
|
|
|
45654
46047
|
if (fileType) {
|
|
45655
46048
|
const extensions = FILE_TYPE_MAP[fileType.toLowerCase()];
|
|
45656
46049
|
if (extensions) {
|
|
45657
|
-
const ext =
|
|
46050
|
+
const ext = path2.extname(entry.name).toLowerCase();
|
|
45658
46051
|
if (!extensions.includes(ext)) continue;
|
|
45659
46052
|
}
|
|
45660
46053
|
}
|
|
@@ -45673,7 +46066,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
|
|
|
45673
46066
|
async function searchFile(filePath, regex, contextBefore, contextAfter) {
|
|
45674
46067
|
const matches = [];
|
|
45675
46068
|
try {
|
|
45676
|
-
const content = await
|
|
46069
|
+
const content = await fs15.readFile(filePath, "utf-8");
|
|
45677
46070
|
const lines = content.split("\n");
|
|
45678
46071
|
for (let i = 0; i < lines.length; i++) {
|
|
45679
46072
|
const line = lines[i] ?? "";
|
|
@@ -45814,7 +46207,7 @@ WHEN TO USE:
|
|
|
45814
46207
|
};
|
|
45815
46208
|
}
|
|
45816
46209
|
const resolvedPath = validation.resolvedPath;
|
|
45817
|
-
if (!
|
|
46210
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
45818
46211
|
return {
|
|
45819
46212
|
success: false,
|
|
45820
46213
|
error: `Path not found: ${searchPath}`
|
|
@@ -45830,7 +46223,7 @@ WHEN TO USE:
|
|
|
45830
46223
|
};
|
|
45831
46224
|
}
|
|
45832
46225
|
try {
|
|
45833
|
-
const stats = await
|
|
46226
|
+
const stats = await fs15.stat(resolvedPath);
|
|
45834
46227
|
let filesToSearch;
|
|
45835
46228
|
if (stats.isFile()) {
|
|
45836
46229
|
filesToSearch = [resolvedPath];
|
|
@@ -45856,7 +46249,7 @@ WHEN TO USE:
|
|
|
45856
46249
|
);
|
|
45857
46250
|
if (matches.length > 0) {
|
|
45858
46251
|
filesMatched++;
|
|
45859
|
-
const relativePath =
|
|
46252
|
+
const relativePath = path2.relative(resolvedPath, file) || file;
|
|
45860
46253
|
for (const match of matches) {
|
|
45861
46254
|
match.file = relativePath;
|
|
45862
46255
|
}
|
|
@@ -45918,11 +46311,11 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
|
|
|
45918
46311
|
return entries;
|
|
45919
46312
|
}
|
|
45920
46313
|
try {
|
|
45921
|
-
const dirEntries = await
|
|
46314
|
+
const dirEntries = await fs15.readdir(dir, { withFileTypes: true });
|
|
45922
46315
|
for (const entry of dirEntries) {
|
|
45923
46316
|
if (entries.length >= config.maxResults) break;
|
|
45924
|
-
const fullPath =
|
|
45925
|
-
const relativePath =
|
|
46317
|
+
const fullPath = path2.join(dir, entry.name);
|
|
46318
|
+
const relativePath = path2.relative(baseDir, fullPath);
|
|
45926
46319
|
if (entry.isDirectory() && config.blockedDirectories.includes(entry.name)) {
|
|
45927
46320
|
continue;
|
|
45928
46321
|
}
|
|
@@ -45936,7 +46329,7 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
|
|
|
45936
46329
|
}
|
|
45937
46330
|
if (filter === "directories" && !isDir) continue;
|
|
45938
46331
|
try {
|
|
45939
|
-
const stats = await
|
|
46332
|
+
const stats = await fs15.stat(fullPath);
|
|
45940
46333
|
const dirEntry = {
|
|
45941
46334
|
name: entry.name,
|
|
45942
46335
|
path: relativePath,
|
|
@@ -46032,14 +46425,14 @@ EXAMPLES:
|
|
|
46032
46425
|
};
|
|
46033
46426
|
}
|
|
46034
46427
|
const resolvedPath = validation.resolvedPath;
|
|
46035
|
-
if (!
|
|
46428
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
46036
46429
|
return {
|
|
46037
46430
|
success: false,
|
|
46038
46431
|
error: `Directory not found: ${path6}`
|
|
46039
46432
|
};
|
|
46040
46433
|
}
|
|
46041
46434
|
try {
|
|
46042
|
-
const stats = await
|
|
46435
|
+
const stats = await fs15.stat(resolvedPath);
|
|
46043
46436
|
if (!stats.isDirectory()) {
|
|
46044
46437
|
return {
|
|
46045
46438
|
success: false,
|
|
@@ -46227,7 +46620,8 @@ EXAMPLES:
|
|
|
46227
46620
|
shell: mergedConfig.shell,
|
|
46228
46621
|
cwd: mergedConfig.workingDirectory,
|
|
46229
46622
|
env,
|
|
46230
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
46623
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
46624
|
+
detached: true
|
|
46231
46625
|
});
|
|
46232
46626
|
if (run_in_background && mergedConfig.allowBackground) {
|
|
46233
46627
|
const bgId = generateBackgroundId();
|
|
@@ -46254,14 +46648,27 @@ EXAMPLES:
|
|
|
46254
46648
|
let stdout = "";
|
|
46255
46649
|
let stderr = "";
|
|
46256
46650
|
let killed = false;
|
|
46651
|
+
const killProcessGroup = (signal) => {
|
|
46652
|
+
try {
|
|
46653
|
+
if (childProcess.pid) {
|
|
46654
|
+
process.kill(-childProcess.pid, signal);
|
|
46655
|
+
}
|
|
46656
|
+
} catch {
|
|
46657
|
+
try {
|
|
46658
|
+
childProcess.kill(signal);
|
|
46659
|
+
} catch {
|
|
46660
|
+
}
|
|
46661
|
+
}
|
|
46662
|
+
};
|
|
46663
|
+
const GRACEFUL_KILL_WAIT_MS = 3e3;
|
|
46257
46664
|
const timeoutId = setTimeout(() => {
|
|
46258
46665
|
killed = true;
|
|
46259
|
-
|
|
46666
|
+
killProcessGroup("SIGTERM");
|
|
46260
46667
|
setTimeout(() => {
|
|
46261
46668
|
if (!childProcess.killed) {
|
|
46262
|
-
|
|
46669
|
+
killProcessGroup("SIGKILL");
|
|
46263
46670
|
}
|
|
46264
|
-
},
|
|
46671
|
+
}, GRACEFUL_KILL_WAIT_MS);
|
|
46265
46672
|
}, effectiveTimeout);
|
|
46266
46673
|
childProcess.stdout.on("data", (data) => {
|
|
46267
46674
|
stdout += data.toString();
|
|
@@ -46275,8 +46682,28 @@ EXAMPLES:
|
|
|
46275
46682
|
stderr = stderr.slice(-mergedConfig.maxOutputSize);
|
|
46276
46683
|
}
|
|
46277
46684
|
});
|
|
46278
|
-
|
|
46685
|
+
let resolved = false;
|
|
46686
|
+
const safeResolve = (result) => {
|
|
46687
|
+
if (resolved) return;
|
|
46688
|
+
resolved = true;
|
|
46279
46689
|
clearTimeout(timeoutId);
|
|
46690
|
+
clearTimeout(hardTimeoutId);
|
|
46691
|
+
resolve4(result);
|
|
46692
|
+
};
|
|
46693
|
+
const HARD_TIMEOUT_GRACE_MS = 5e3;
|
|
46694
|
+
const hardTimeoutId = setTimeout(() => {
|
|
46695
|
+
if (!resolved) {
|
|
46696
|
+
killProcessGroup("SIGKILL");
|
|
46697
|
+
safeResolve({
|
|
46698
|
+
success: false,
|
|
46699
|
+
stdout,
|
|
46700
|
+
stderr,
|
|
46701
|
+
duration: Date.now() - startTime,
|
|
46702
|
+
error: `Command timed out after ${effectiveTimeout}ms (hard timeout: process group did not exit)`
|
|
46703
|
+
});
|
|
46704
|
+
}
|
|
46705
|
+
}, effectiveTimeout + GRACEFUL_KILL_WAIT_MS + HARD_TIMEOUT_GRACE_MS);
|
|
46706
|
+
childProcess.on("close", (code, signal) => {
|
|
46280
46707
|
const duration = Date.now() - startTime;
|
|
46281
46708
|
let truncated = false;
|
|
46282
46709
|
if (stdout.length > mergedConfig.maxOutputSize) {
|
|
@@ -46288,7 +46715,7 @@ EXAMPLES:
|
|
|
46288
46715
|
truncated = true;
|
|
46289
46716
|
}
|
|
46290
46717
|
if (killed) {
|
|
46291
|
-
|
|
46718
|
+
safeResolve({
|
|
46292
46719
|
success: false,
|
|
46293
46720
|
stdout,
|
|
46294
46721
|
stderr,
|
|
@@ -46299,7 +46726,7 @@ EXAMPLES:
|
|
|
46299
46726
|
error: `Command timed out after ${effectiveTimeout}ms`
|
|
46300
46727
|
});
|
|
46301
46728
|
} else {
|
|
46302
|
-
|
|
46729
|
+
safeResolve({
|
|
46303
46730
|
success: code === 0,
|
|
46304
46731
|
stdout,
|
|
46305
46732
|
stderr,
|
|
@@ -46312,8 +46739,7 @@ EXAMPLES:
|
|
|
46312
46739
|
}
|
|
46313
46740
|
});
|
|
46314
46741
|
childProcess.on("error", (error) => {
|
|
46315
|
-
|
|
46316
|
-
resolve4({
|
|
46742
|
+
safeResolve({
|
|
46317
46743
|
success: false,
|
|
46318
46744
|
error: `Failed to execute command: ${error.message}`,
|
|
46319
46745
|
duration: Date.now() - startTime
|
|
@@ -47579,8 +48005,8 @@ async function tryNative(args, startTime, attemptedMethods) {
|
|
|
47579
48005
|
method: "native",
|
|
47580
48006
|
title: result.title,
|
|
47581
48007
|
content: cleanContent,
|
|
47582
|
-
//
|
|
47583
|
-
|
|
48008
|
+
// Native method already returns markdown-like content — no separate markdown field needed
|
|
48009
|
+
// (would just duplicate content and waste tokens)
|
|
47584
48010
|
qualityScore: result.qualityScore,
|
|
47585
48011
|
durationMs: Date.now() - startTime,
|
|
47586
48012
|
attemptedMethods,
|
|
@@ -47616,8 +48042,7 @@ async function tryJS(args, startTime, attemptedMethods) {
|
|
|
47616
48042
|
method: "js",
|
|
47617
48043
|
title: result.title,
|
|
47618
48044
|
content: cleanContent,
|
|
47619
|
-
//
|
|
47620
|
-
markdown: args.includeMarkdown ? cleanContent : void 0,
|
|
48045
|
+
// JS method already returns markdown-like content — no separate markdown field needed
|
|
47621
48046
|
qualityScore: result.success ? 80 : 0,
|
|
47622
48047
|
durationMs: Date.now() - startTime,
|
|
47623
48048
|
attemptedMethods,
|
|
@@ -47649,8 +48074,11 @@ async function tryAPI(connectorName, args, startTime, attemptedMethods) {
|
|
|
47649
48074
|
includeLinks: args.includeLinks
|
|
47650
48075
|
};
|
|
47651
48076
|
const result = await provider.scrape(args.url, options);
|
|
47652
|
-
const
|
|
47653
|
-
const
|
|
48077
|
+
const rawContent = result.result?.content || "";
|
|
48078
|
+
const rawMarkdown = result.result?.markdown;
|
|
48079
|
+
const cleanContent = stripBase64DataUris(rawContent);
|
|
48080
|
+
const cleanMarkdown = rawMarkdown ? stripBase64DataUris(rawMarkdown) : void 0;
|
|
48081
|
+
const isDuplicate = !!cleanMarkdown && cleanContent === cleanMarkdown;
|
|
47654
48082
|
return {
|
|
47655
48083
|
success: result.success,
|
|
47656
48084
|
url: args.url,
|
|
@@ -47660,7 +48088,7 @@ async function tryAPI(connectorName, args, startTime, attemptedMethods) {
|
|
|
47660
48088
|
content: cleanContent,
|
|
47661
48089
|
html: result.result?.html,
|
|
47662
48090
|
// Keep raw HTML as-is (only used if explicitly requested)
|
|
47663
|
-
markdown: cleanMarkdown,
|
|
48091
|
+
markdown: isDuplicate ? void 0 : cleanMarkdown,
|
|
47664
48092
|
metadata: result.result?.metadata,
|
|
47665
48093
|
links: result.result?.links,
|
|
47666
48094
|
qualityScore: result.success ? 90 : 0,
|
|
@@ -47875,68 +48303,25 @@ async function executeInVM(code, input, timeout, logs) {
|
|
|
47875
48303
|
const result = await resultPromise;
|
|
47876
48304
|
return result !== void 0 ? result : sandbox.output;
|
|
47877
48305
|
}
|
|
47878
|
-
var MIME_TYPES = {
|
|
47879
|
-
png: "image/png",
|
|
47880
|
-
jpeg: "image/jpeg",
|
|
47881
|
-
jpg: "image/jpeg",
|
|
47882
|
-
webp: "image/webp",
|
|
47883
|
-
gif: "image/gif",
|
|
47884
|
-
mp4: "video/mp4",
|
|
47885
|
-
webm: "video/webm",
|
|
47886
|
-
mp3: "audio/mpeg",
|
|
47887
|
-
wav: "audio/wav",
|
|
47888
|
-
opus: "audio/opus",
|
|
47889
|
-
ogg: "audio/ogg",
|
|
47890
|
-
aac: "audio/aac",
|
|
47891
|
-
flac: "audio/flac",
|
|
47892
|
-
pcm: "audio/pcm"
|
|
47893
|
-
};
|
|
47894
|
-
var FileMediaOutputHandler = class {
|
|
47895
|
-
outputDir;
|
|
47896
|
-
initialized = false;
|
|
47897
|
-
constructor(outputDir) {
|
|
47898
|
-
this.outputDir = outputDir ?? path3__namespace.join(os__namespace.tmpdir(), "oneringai-media");
|
|
47899
|
-
}
|
|
47900
|
-
async save(data, metadata) {
|
|
47901
|
-
if (!this.initialized) {
|
|
47902
|
-
await fs14__namespace.mkdir(this.outputDir, { recursive: true });
|
|
47903
|
-
this.initialized = true;
|
|
47904
|
-
}
|
|
47905
|
-
const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
|
|
47906
|
-
const filePath = path3__namespace.join(this.outputDir, filename);
|
|
47907
|
-
await fs14__namespace.writeFile(filePath, data);
|
|
47908
|
-
const format = metadata.format.toLowerCase();
|
|
47909
|
-
const mimeType = MIME_TYPES[format] ?? `application/octet-stream`;
|
|
47910
|
-
return {
|
|
47911
|
-
location: filePath,
|
|
47912
|
-
mimeType,
|
|
47913
|
-
size: data.length
|
|
47914
|
-
};
|
|
47915
|
-
}
|
|
47916
|
-
generateFilename(metadata) {
|
|
47917
|
-
const timestamp = Date.now();
|
|
47918
|
-
const random2 = crypto2__namespace.randomBytes(4).toString("hex");
|
|
47919
|
-
const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
|
|
47920
|
-
return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
|
|
47921
|
-
}
|
|
47922
|
-
};
|
|
47923
48306
|
|
|
47924
48307
|
// src/tools/multimedia/config.ts
|
|
47925
|
-
var
|
|
47926
|
-
function
|
|
47927
|
-
if (!
|
|
47928
|
-
|
|
48308
|
+
var _storage = null;
|
|
48309
|
+
function getMediaStorage() {
|
|
48310
|
+
if (!_storage) {
|
|
48311
|
+
_storage = new FileMediaStorage();
|
|
47929
48312
|
}
|
|
47930
|
-
return
|
|
48313
|
+
return _storage;
|
|
47931
48314
|
}
|
|
47932
|
-
function
|
|
47933
|
-
|
|
48315
|
+
function setMediaStorage(storage) {
|
|
48316
|
+
_storage = storage;
|
|
47934
48317
|
}
|
|
48318
|
+
var getMediaOutputHandler = getMediaStorage;
|
|
48319
|
+
var setMediaOutputHandler = setMediaStorage;
|
|
47935
48320
|
|
|
47936
48321
|
// src/tools/multimedia/imageGeneration.ts
|
|
47937
|
-
function createImageGenerationTool(connector,
|
|
48322
|
+
function createImageGenerationTool(connector, storage, userId) {
|
|
47938
48323
|
const vendor = connector.vendor;
|
|
47939
|
-
const handler =
|
|
48324
|
+
const handler = storage ?? getMediaStorage();
|
|
47940
48325
|
const vendorModels = vendor ? getImageModelsByVendor(vendor) : [];
|
|
47941
48326
|
const modelNames = vendorModels.map((m) => m.name);
|
|
47942
48327
|
const properties = {
|
|
@@ -48009,8 +48394,9 @@ function createImageGenerationTool(connector, outputHandler) {
|
|
|
48009
48394
|
}
|
|
48010
48395
|
}
|
|
48011
48396
|
},
|
|
48012
|
-
execute: async (args) => {
|
|
48397
|
+
execute: async (args, context) => {
|
|
48013
48398
|
try {
|
|
48399
|
+
const effectiveUserId = userId ?? context?.userId;
|
|
48014
48400
|
const imageGen = ImageGeneration.create({ connector });
|
|
48015
48401
|
const response = await imageGen.generate({
|
|
48016
48402
|
prompt: args.prompt,
|
|
@@ -48041,7 +48427,8 @@ function createImageGenerationTool(connector, outputHandler) {
|
|
|
48041
48427
|
format,
|
|
48042
48428
|
model: modelName,
|
|
48043
48429
|
vendor: vendor || "unknown",
|
|
48044
|
-
index: response.data.length > 1 ? i : void 0
|
|
48430
|
+
index: response.data.length > 1 ? i : void 0,
|
|
48431
|
+
userId: effectiveUserId
|
|
48045
48432
|
});
|
|
48046
48433
|
images.push({
|
|
48047
48434
|
location: result.location,
|
|
@@ -48068,9 +48455,9 @@ function createImageGenerationTool(connector, outputHandler) {
|
|
|
48068
48455
|
|
|
48069
48456
|
// src/tools/multimedia/videoGeneration.ts
|
|
48070
48457
|
var videoGenInstances = /* @__PURE__ */ new Map();
|
|
48071
|
-
function createVideoTools(connector,
|
|
48458
|
+
function createVideoTools(connector, storage, userId) {
|
|
48072
48459
|
const vendor = connector.vendor;
|
|
48073
|
-
const handler =
|
|
48460
|
+
const handler = storage ?? getMediaStorage();
|
|
48074
48461
|
const vendorModels = vendor ? getVideoModelsByVendor(vendor) : [];
|
|
48075
48462
|
const modelNames = vendorModels.map((m) => m.name);
|
|
48076
48463
|
const generateProperties = {
|
|
@@ -48134,7 +48521,7 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48134
48521
|
}
|
|
48135
48522
|
}
|
|
48136
48523
|
},
|
|
48137
|
-
execute: async (args) => {
|
|
48524
|
+
execute: async (args, _context) => {
|
|
48138
48525
|
try {
|
|
48139
48526
|
const videoGen = VideoGeneration.create({ connector });
|
|
48140
48527
|
const response = await videoGen.generate({
|
|
@@ -48183,8 +48570,9 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48183
48570
|
}
|
|
48184
48571
|
}
|
|
48185
48572
|
},
|
|
48186
|
-
execute: async (args) => {
|
|
48573
|
+
execute: async (args, context) => {
|
|
48187
48574
|
try {
|
|
48575
|
+
const effectiveUserId = userId ?? context?.userId;
|
|
48188
48576
|
let videoGen = videoGenInstances.get(args.jobId);
|
|
48189
48577
|
if (!videoGen) {
|
|
48190
48578
|
videoGen = VideoGeneration.create({ connector });
|
|
@@ -48210,7 +48598,8 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48210
48598
|
type: "video",
|
|
48211
48599
|
format,
|
|
48212
48600
|
model: modelName,
|
|
48213
|
-
vendor: vendor || "unknown"
|
|
48601
|
+
vendor: vendor || "unknown",
|
|
48602
|
+
userId: effectiveUserId
|
|
48214
48603
|
});
|
|
48215
48604
|
videoGenInstances.delete(args.jobId);
|
|
48216
48605
|
return {
|
|
@@ -48258,9 +48647,9 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48258
48647
|
}
|
|
48259
48648
|
|
|
48260
48649
|
// src/tools/multimedia/textToSpeech.ts
|
|
48261
|
-
function createTextToSpeechTool(connector,
|
|
48650
|
+
function createTextToSpeechTool(connector, storage, userId) {
|
|
48262
48651
|
const vendor = connector.vendor;
|
|
48263
|
-
const handler =
|
|
48652
|
+
const handler = storage ?? getMediaStorage();
|
|
48264
48653
|
const vendorModels = vendor ? getTTSModelsByVendor(vendor) : [];
|
|
48265
48654
|
const modelNames = vendorModels.map((m) => m.name);
|
|
48266
48655
|
const properties = {
|
|
@@ -48321,8 +48710,9 @@ function createTextToSpeechTool(connector, outputHandler) {
|
|
|
48321
48710
|
}
|
|
48322
48711
|
}
|
|
48323
48712
|
},
|
|
48324
|
-
execute: async (args) => {
|
|
48713
|
+
execute: async (args, context) => {
|
|
48325
48714
|
try {
|
|
48715
|
+
const effectiveUserId = userId ?? context?.userId;
|
|
48326
48716
|
const tts = TextToSpeech.create({
|
|
48327
48717
|
connector,
|
|
48328
48718
|
model: args.model,
|
|
@@ -48336,7 +48726,8 @@ function createTextToSpeechTool(connector, outputHandler) {
|
|
|
48336
48726
|
type: "audio",
|
|
48337
48727
|
format,
|
|
48338
48728
|
model: args.model || modelNames[0] || "unknown",
|
|
48339
|
-
vendor: vendor || "unknown"
|
|
48729
|
+
vendor: vendor || "unknown",
|
|
48730
|
+
userId: effectiveUserId
|
|
48340
48731
|
});
|
|
48341
48732
|
return {
|
|
48342
48733
|
success: true,
|
|
@@ -48359,14 +48750,17 @@ function createTextToSpeechTool(connector, outputHandler) {
|
|
|
48359
48750
|
}
|
|
48360
48751
|
};
|
|
48361
48752
|
}
|
|
48362
|
-
|
|
48753
|
+
|
|
48754
|
+
// src/tools/multimedia/speechToText.ts
|
|
48755
|
+
function createSpeechToTextTool(connector, storage, _userId) {
|
|
48363
48756
|
const vendor = connector.vendor;
|
|
48757
|
+
const handler = storage ?? getMediaStorage();
|
|
48364
48758
|
const vendorModels = vendor ? getSTTModelsByVendor(vendor) : [];
|
|
48365
48759
|
const modelNames = vendorModels.map((m) => m.name);
|
|
48366
48760
|
const properties = {
|
|
48367
|
-
|
|
48761
|
+
audioSource: {
|
|
48368
48762
|
type: "string",
|
|
48369
|
-
description: "Path
|
|
48763
|
+
description: "Path or location of the audio file to transcribe (file path, storage location, etc.)"
|
|
48370
48764
|
}
|
|
48371
48765
|
};
|
|
48372
48766
|
if (modelNames.length > 0) {
|
|
@@ -48394,13 +48788,19 @@ function createSpeechToTextTool(connector) {
|
|
|
48394
48788
|
parameters: {
|
|
48395
48789
|
type: "object",
|
|
48396
48790
|
properties,
|
|
48397
|
-
required: ["
|
|
48791
|
+
required: ["audioSource"]
|
|
48398
48792
|
}
|
|
48399
48793
|
}
|
|
48400
48794
|
},
|
|
48401
|
-
execute: async (args) => {
|
|
48795
|
+
execute: async (args, _context) => {
|
|
48402
48796
|
try {
|
|
48403
|
-
const audioBuffer = await
|
|
48797
|
+
const audioBuffer = await handler.read(args.audioSource);
|
|
48798
|
+
if (!audioBuffer) {
|
|
48799
|
+
return {
|
|
48800
|
+
success: false,
|
|
48801
|
+
error: `Audio not found at: ${args.audioSource}`
|
|
48802
|
+
};
|
|
48803
|
+
}
|
|
48404
48804
|
const stt = SpeechToText.create({
|
|
48405
48805
|
connector,
|
|
48406
48806
|
model: args.model,
|
|
@@ -48422,7 +48822,7 @@ function createSpeechToTextTool(connector) {
|
|
|
48422
48822
|
};
|
|
48423
48823
|
}
|
|
48424
48824
|
},
|
|
48425
|
-
describeCall: (args) => args.
|
|
48825
|
+
describeCall: (args) => args.audioSource,
|
|
48426
48826
|
permission: {
|
|
48427
48827
|
scope: "session",
|
|
48428
48828
|
riskLevel: "low",
|
|
@@ -48437,21 +48837,22 @@ var VENDOR_CAPABILITIES = {
|
|
|
48437
48837
|
[Vendor.Google]: ["image", "video", "tts"],
|
|
48438
48838
|
[Vendor.Grok]: ["image", "video"]
|
|
48439
48839
|
};
|
|
48440
|
-
function registerMultimediaTools() {
|
|
48840
|
+
function registerMultimediaTools(storage) {
|
|
48441
48841
|
for (const [vendor, capabilities] of Object.entries(VENDOR_CAPABILITIES)) {
|
|
48442
|
-
ConnectorTools.registerService(vendor, (connector,
|
|
48842
|
+
ConnectorTools.registerService(vendor, (connector, userId) => {
|
|
48843
|
+
const handler = getMediaStorage();
|
|
48443
48844
|
const tools = [];
|
|
48444
48845
|
if (capabilities.includes("image")) {
|
|
48445
|
-
tools.push(createImageGenerationTool(connector));
|
|
48846
|
+
tools.push(createImageGenerationTool(connector, handler, userId));
|
|
48446
48847
|
}
|
|
48447
48848
|
if (capabilities.includes("video")) {
|
|
48448
|
-
tools.push(...createVideoTools(connector));
|
|
48849
|
+
tools.push(...createVideoTools(connector, handler, userId));
|
|
48449
48850
|
}
|
|
48450
48851
|
if (capabilities.includes("tts")) {
|
|
48451
|
-
tools.push(createTextToSpeechTool(connector));
|
|
48852
|
+
tools.push(createTextToSpeechTool(connector, handler, userId));
|
|
48452
48853
|
}
|
|
48453
48854
|
if (capabilities.includes("stt")) {
|
|
48454
|
-
tools.push(createSpeechToTextTool(connector));
|
|
48855
|
+
tools.push(createSpeechToTextTool(connector, handler));
|
|
48455
48856
|
}
|
|
48456
48857
|
return tools;
|
|
48457
48858
|
});
|
|
@@ -48461,6 +48862,851 @@ function registerMultimediaTools() {
|
|
|
48461
48862
|
// src/tools/multimedia/index.ts
|
|
48462
48863
|
registerMultimediaTools();
|
|
48463
48864
|
|
|
48865
|
+
// src/tools/github/types.ts
|
|
48866
|
+
function parseRepository(input) {
|
|
48867
|
+
if (!input || input.trim().length === 0) {
|
|
48868
|
+
throw new Error("Repository cannot be empty");
|
|
48869
|
+
}
|
|
48870
|
+
const trimmed = input.trim();
|
|
48871
|
+
try {
|
|
48872
|
+
const url2 = new URL(trimmed);
|
|
48873
|
+
if (url2.hostname === "github.com" || url2.hostname === "www.github.com") {
|
|
48874
|
+
const segments = url2.pathname.split("/").filter(Boolean);
|
|
48875
|
+
if (segments.length >= 2) {
|
|
48876
|
+
return { owner: segments[0], repo: segments[1].replace(/\.git$/, "") };
|
|
48877
|
+
}
|
|
48878
|
+
}
|
|
48879
|
+
} catch {
|
|
48880
|
+
}
|
|
48881
|
+
const parts = trimmed.split("/");
|
|
48882
|
+
if (parts.length === 2 && parts[0].length > 0 && parts[1].length > 0) {
|
|
48883
|
+
return { owner: parts[0], repo: parts[1] };
|
|
48884
|
+
}
|
|
48885
|
+
throw new Error(
|
|
48886
|
+
`Invalid repository format: "${input}". Expected "owner/repo" or "https://github.com/owner/repo"`
|
|
48887
|
+
);
|
|
48888
|
+
}
|
|
48889
|
+
function resolveRepository(repository, connector) {
|
|
48890
|
+
const repoStr = repository ?? connector.getOptions().defaultRepository;
|
|
48891
|
+
if (!repoStr) {
|
|
48892
|
+
return {
|
|
48893
|
+
success: false,
|
|
48894
|
+
error: 'No repository specified. Provide a "repository" parameter (e.g., "owner/repo") or configure defaultRepository on the connector.'
|
|
48895
|
+
};
|
|
48896
|
+
}
|
|
48897
|
+
try {
|
|
48898
|
+
return { success: true, repo: parseRepository(repoStr) };
|
|
48899
|
+
} catch (err) {
|
|
48900
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
48901
|
+
}
|
|
48902
|
+
}
|
|
48903
|
+
var GitHubAPIError = class extends Error {
|
|
48904
|
+
constructor(status, statusText, body) {
|
|
48905
|
+
const msg = typeof body === "object" && body !== null && "message" in body ? body.message : statusText;
|
|
48906
|
+
super(`GitHub API error ${status}: ${msg}`);
|
|
48907
|
+
this.status = status;
|
|
48908
|
+
this.statusText = statusText;
|
|
48909
|
+
this.body = body;
|
|
48910
|
+
this.name = "GitHubAPIError";
|
|
48911
|
+
}
|
|
48912
|
+
};
|
|
48913
|
+
async function githubFetch(connector, endpoint, options) {
|
|
48914
|
+
let url2 = endpoint;
|
|
48915
|
+
if (options?.queryParams && Object.keys(options.queryParams).length > 0) {
|
|
48916
|
+
const params = new URLSearchParams();
|
|
48917
|
+
for (const [key, value] of Object.entries(options.queryParams)) {
|
|
48918
|
+
params.append(key, String(value));
|
|
48919
|
+
}
|
|
48920
|
+
url2 += (url2.includes("?") ? "&" : "?") + params.toString();
|
|
48921
|
+
}
|
|
48922
|
+
const headers = {
|
|
48923
|
+
"Accept": options?.accept ?? "application/vnd.github+json",
|
|
48924
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
48925
|
+
};
|
|
48926
|
+
if (options?.body) {
|
|
48927
|
+
headers["Content-Type"] = "application/json";
|
|
48928
|
+
}
|
|
48929
|
+
const response = await connector.fetch(
|
|
48930
|
+
url2,
|
|
48931
|
+
{
|
|
48932
|
+
method: options?.method ?? "GET",
|
|
48933
|
+
headers,
|
|
48934
|
+
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
48935
|
+
},
|
|
48936
|
+
options?.userId
|
|
48937
|
+
);
|
|
48938
|
+
const text = await response.text();
|
|
48939
|
+
let data;
|
|
48940
|
+
try {
|
|
48941
|
+
data = JSON.parse(text);
|
|
48942
|
+
} catch {
|
|
48943
|
+
data = text;
|
|
48944
|
+
}
|
|
48945
|
+
if (!response.ok) {
|
|
48946
|
+
throw new GitHubAPIError(response.status, response.statusText, data);
|
|
48947
|
+
}
|
|
48948
|
+
return data;
|
|
48949
|
+
}
|
|
48950
|
+
|
|
48951
|
+
// src/tools/github/searchFiles.ts
|
|
48952
|
+
function matchGlobPattern2(pattern, filePath) {
|
|
48953
|
+
let regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, ".").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
48954
|
+
regexPattern = "^" + regexPattern + "$";
|
|
48955
|
+
try {
|
|
48956
|
+
const regex = new RegExp(regexPattern);
|
|
48957
|
+
return regex.test(filePath);
|
|
48958
|
+
} catch {
|
|
48959
|
+
return false;
|
|
48960
|
+
}
|
|
48961
|
+
}
|
|
48962
|
+
function createSearchFilesTool(connector, userId) {
|
|
48963
|
+
return {
|
|
48964
|
+
definition: {
|
|
48965
|
+
type: "function",
|
|
48966
|
+
function: {
|
|
48967
|
+
name: "search_files",
|
|
48968
|
+
description: `Search for files by name/path pattern in a GitHub repository.
|
|
48969
|
+
|
|
48970
|
+
USAGE:
|
|
48971
|
+
- Supports glob patterns like "**/*.ts", "src/**/*.tsx"
|
|
48972
|
+
- Returns matching file paths sorted alphabetically
|
|
48973
|
+
- Uses the repository's file tree for fast matching
|
|
48974
|
+
|
|
48975
|
+
PATTERN SYNTAX:
|
|
48976
|
+
- * matches any characters except /
|
|
48977
|
+
- ** matches any characters including /
|
|
48978
|
+
- ? matches a single character
|
|
48979
|
+
|
|
48980
|
+
EXAMPLES:
|
|
48981
|
+
- Find all TypeScript files: { "pattern": "**/*.ts" }
|
|
48982
|
+
- Find files in src: { "pattern": "src/**/*.{ts,tsx}" }
|
|
48983
|
+
- Find package.json: { "pattern": "**/package.json" }
|
|
48984
|
+
- Search specific branch: { "pattern": "**/*.ts", "ref": "develop" }`,
|
|
48985
|
+
parameters: {
|
|
48986
|
+
type: "object",
|
|
48987
|
+
properties: {
|
|
48988
|
+
repository: {
|
|
48989
|
+
type: "string",
|
|
48990
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
48991
|
+
},
|
|
48992
|
+
pattern: {
|
|
48993
|
+
type: "string",
|
|
48994
|
+
description: 'Glob pattern to match files (e.g., "**/*.ts", "src/**/*.tsx")'
|
|
48995
|
+
},
|
|
48996
|
+
ref: {
|
|
48997
|
+
type: "string",
|
|
48998
|
+
description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
|
|
48999
|
+
}
|
|
49000
|
+
},
|
|
49001
|
+
required: ["pattern"]
|
|
49002
|
+
}
|
|
49003
|
+
}
|
|
49004
|
+
},
|
|
49005
|
+
describeCall: (args) => {
|
|
49006
|
+
const parts = [args.pattern];
|
|
49007
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49008
|
+
if (args.ref) parts.push(`@${args.ref}`);
|
|
49009
|
+
return parts.join(" ");
|
|
49010
|
+
},
|
|
49011
|
+
permission: {
|
|
49012
|
+
scope: "session",
|
|
49013
|
+
riskLevel: "low",
|
|
49014
|
+
approvalMessage: `Search files in a GitHub repository via ${connector.displayName}`
|
|
49015
|
+
},
|
|
49016
|
+
execute: async (args) => {
|
|
49017
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49018
|
+
if (!resolved.success) {
|
|
49019
|
+
return { success: false, error: resolved.error };
|
|
49020
|
+
}
|
|
49021
|
+
const { owner, repo } = resolved.repo;
|
|
49022
|
+
try {
|
|
49023
|
+
let ref = args.ref;
|
|
49024
|
+
if (!ref) {
|
|
49025
|
+
const repoInfo = await githubFetch(
|
|
49026
|
+
connector,
|
|
49027
|
+
`/repos/${owner}/${repo}`,
|
|
49028
|
+
{ userId }
|
|
49029
|
+
);
|
|
49030
|
+
ref = repoInfo.default_branch;
|
|
49031
|
+
}
|
|
49032
|
+
const tree = await githubFetch(
|
|
49033
|
+
connector,
|
|
49034
|
+
`/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`,
|
|
49035
|
+
{ userId }
|
|
49036
|
+
);
|
|
49037
|
+
const matching = tree.tree.filter(
|
|
49038
|
+
(entry) => entry.type === "blob" && matchGlobPattern2(args.pattern, entry.path)
|
|
49039
|
+
).map((entry) => ({
|
|
49040
|
+
path: entry.path,
|
|
49041
|
+
size: entry.size ?? 0,
|
|
49042
|
+
type: entry.type
|
|
49043
|
+
})).sort((a, b) => a.path.localeCompare(b.path));
|
|
49044
|
+
return {
|
|
49045
|
+
success: true,
|
|
49046
|
+
files: matching,
|
|
49047
|
+
count: matching.length,
|
|
49048
|
+
truncated: tree.truncated
|
|
49049
|
+
};
|
|
49050
|
+
} catch (error) {
|
|
49051
|
+
return {
|
|
49052
|
+
success: false,
|
|
49053
|
+
error: `Failed to search files: ${error instanceof Error ? error.message : String(error)}`
|
|
49054
|
+
};
|
|
49055
|
+
}
|
|
49056
|
+
}
|
|
49057
|
+
};
|
|
49058
|
+
}
|
|
49059
|
+
|
|
49060
|
+
// src/tools/github/searchCode.ts
|
|
49061
|
+
function createSearchCodeTool(connector, userId) {
|
|
49062
|
+
return {
|
|
49063
|
+
definition: {
|
|
49064
|
+
type: "function",
|
|
49065
|
+
function: {
|
|
49066
|
+
name: "search_code",
|
|
49067
|
+
description: `Search for code content across a GitHub repository.
|
|
49068
|
+
|
|
49069
|
+
USAGE:
|
|
49070
|
+
- Search by keyword, function name, class name, or any text
|
|
49071
|
+
- Filter by language, path, or file extension
|
|
49072
|
+
- Returns matching files with text fragments showing context
|
|
49073
|
+
|
|
49074
|
+
RATE LIMITS:
|
|
49075
|
+
- GitHub's code search API is limited to 30 requests per minute
|
|
49076
|
+
- Results may be incomplete for very large repositories
|
|
49077
|
+
|
|
49078
|
+
EXAMPLES:
|
|
49079
|
+
- Find function: { "query": "function handleAuth", "language": "typescript" }
|
|
49080
|
+
- Find imports: { "query": "import React", "extension": "tsx" }
|
|
49081
|
+
- Search in path: { "query": "TODO", "path": "src/utils" }
|
|
49082
|
+
- Limit results: { "query": "console.log", "limit": 10 }`,
|
|
49083
|
+
parameters: {
|
|
49084
|
+
type: "object",
|
|
49085
|
+
properties: {
|
|
49086
|
+
repository: {
|
|
49087
|
+
type: "string",
|
|
49088
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49089
|
+
},
|
|
49090
|
+
query: {
|
|
49091
|
+
type: "string",
|
|
49092
|
+
description: "Search query \u2014 keyword, function name, or any text to find in code"
|
|
49093
|
+
},
|
|
49094
|
+
language: {
|
|
49095
|
+
type: "string",
|
|
49096
|
+
description: 'Filter by programming language (e.g., "typescript", "python", "go")'
|
|
49097
|
+
},
|
|
49098
|
+
path: {
|
|
49099
|
+
type: "string",
|
|
49100
|
+
description: 'Filter by file path prefix (e.g., "src/", "lib/utils")'
|
|
49101
|
+
},
|
|
49102
|
+
extension: {
|
|
49103
|
+
type: "string",
|
|
49104
|
+
description: 'Filter by file extension without dot (e.g., "ts", "py", "go")'
|
|
49105
|
+
},
|
|
49106
|
+
limit: {
|
|
49107
|
+
type: "number",
|
|
49108
|
+
description: "Maximum number of results (default: 30, max: 100)"
|
|
49109
|
+
}
|
|
49110
|
+
},
|
|
49111
|
+
required: ["query"]
|
|
49112
|
+
}
|
|
49113
|
+
}
|
|
49114
|
+
},
|
|
49115
|
+
describeCall: (args) => {
|
|
49116
|
+
const parts = [`"${args.query}"`];
|
|
49117
|
+
if (args.language) parts.push(`lang:${args.language}`);
|
|
49118
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49119
|
+
return parts.join(" ");
|
|
49120
|
+
},
|
|
49121
|
+
permission: {
|
|
49122
|
+
scope: "session",
|
|
49123
|
+
riskLevel: "low",
|
|
49124
|
+
approvalMessage: `Search code in a GitHub repository via ${connector.displayName}`
|
|
49125
|
+
},
|
|
49126
|
+
execute: async (args) => {
|
|
49127
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49128
|
+
if (!resolved.success) {
|
|
49129
|
+
return { success: false, error: resolved.error };
|
|
49130
|
+
}
|
|
49131
|
+
const { owner, repo } = resolved.repo;
|
|
49132
|
+
try {
|
|
49133
|
+
const qualifiers = [`repo:${owner}/${repo}`];
|
|
49134
|
+
if (args.language) qualifiers.push(`language:${args.language}`);
|
|
49135
|
+
if (args.path) qualifiers.push(`path:${args.path}`);
|
|
49136
|
+
if (args.extension) qualifiers.push(`extension:${args.extension}`);
|
|
49137
|
+
const q = `${args.query} ${qualifiers.join(" ")}`;
|
|
49138
|
+
const perPage = Math.min(args.limit ?? 30, 100);
|
|
49139
|
+
const result = await githubFetch(
|
|
49140
|
+
connector,
|
|
49141
|
+
`/search/code`,
|
|
49142
|
+
{
|
|
49143
|
+
userId,
|
|
49144
|
+
// Request text-match fragments
|
|
49145
|
+
accept: "application/vnd.github.text-match+json",
|
|
49146
|
+
queryParams: { q, per_page: perPage }
|
|
49147
|
+
}
|
|
49148
|
+
);
|
|
49149
|
+
const matches = result.items.map((item) => ({
|
|
49150
|
+
file: item.path,
|
|
49151
|
+
fragment: item.text_matches?.[0]?.fragment
|
|
49152
|
+
}));
|
|
49153
|
+
return {
|
|
49154
|
+
success: true,
|
|
49155
|
+
matches,
|
|
49156
|
+
count: result.total_count,
|
|
49157
|
+
truncated: result.incomplete_results || result.total_count > perPage
|
|
49158
|
+
};
|
|
49159
|
+
} catch (error) {
|
|
49160
|
+
return {
|
|
49161
|
+
success: false,
|
|
49162
|
+
error: `Failed to search code: ${error instanceof Error ? error.message : String(error)}`
|
|
49163
|
+
};
|
|
49164
|
+
}
|
|
49165
|
+
}
|
|
49166
|
+
};
|
|
49167
|
+
}
|
|
49168
|
+
|
|
49169
|
+
// src/tools/github/readFile.ts
|
|
49170
|
+
function createGitHubReadFileTool(connector, userId) {
|
|
49171
|
+
return {
|
|
49172
|
+
definition: {
|
|
49173
|
+
type: "function",
|
|
49174
|
+
function: {
|
|
49175
|
+
name: "read_file",
|
|
49176
|
+
description: `Read file content from a GitHub repository.
|
|
49177
|
+
|
|
49178
|
+
USAGE:
|
|
49179
|
+
- Reads a file and returns content with line numbers
|
|
49180
|
+
- Supports line range selection with offset/limit for large files
|
|
49181
|
+
- By default reads up to 2000 lines from the beginning
|
|
49182
|
+
|
|
49183
|
+
EXAMPLES:
|
|
49184
|
+
- Read entire file: { "path": "src/index.ts" }
|
|
49185
|
+
- Read specific branch: { "path": "README.md", "ref": "develop" }
|
|
49186
|
+
- Read lines 100-200: { "path": "src/app.ts", "offset": 100, "limit": 100 }
|
|
49187
|
+
- Specific repo: { "repository": "owner/repo", "path": "package.json" }
|
|
49188
|
+
|
|
49189
|
+
NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (>5MB) may be truncated.`,
|
|
49190
|
+
parameters: {
|
|
49191
|
+
type: "object",
|
|
49192
|
+
properties: {
|
|
49193
|
+
repository: {
|
|
49194
|
+
type: "string",
|
|
49195
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49196
|
+
},
|
|
49197
|
+
path: {
|
|
49198
|
+
type: "string",
|
|
49199
|
+
description: 'File path within the repository (e.g., "src/index.ts")'
|
|
49200
|
+
},
|
|
49201
|
+
ref: {
|
|
49202
|
+
type: "string",
|
|
49203
|
+
description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
|
|
49204
|
+
},
|
|
49205
|
+
offset: {
|
|
49206
|
+
type: "number",
|
|
49207
|
+
description: "Line number to start reading from (1-indexed). Only provide if the file is too large."
|
|
49208
|
+
},
|
|
49209
|
+
limit: {
|
|
49210
|
+
type: "number",
|
|
49211
|
+
description: "Number of lines to read (default: 2000). Only provide if the file is too large."
|
|
49212
|
+
}
|
|
49213
|
+
},
|
|
49214
|
+
required: ["path"]
|
|
49215
|
+
}
|
|
49216
|
+
}
|
|
49217
|
+
},
|
|
49218
|
+
describeCall: (args) => {
|
|
49219
|
+
const parts = [args.path];
|
|
49220
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49221
|
+
if (args.ref) parts.push(`@${args.ref}`);
|
|
49222
|
+
if (args.offset && args.limit) parts.push(`[lines ${args.offset}-${args.offset + args.limit}]`);
|
|
49223
|
+
return parts.join(" ");
|
|
49224
|
+
},
|
|
49225
|
+
permission: {
|
|
49226
|
+
scope: "session",
|
|
49227
|
+
riskLevel: "low",
|
|
49228
|
+
approvalMessage: `Read a file from a GitHub repository via ${connector.displayName}`
|
|
49229
|
+
},
|
|
49230
|
+
execute: async (args) => {
|
|
49231
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49232
|
+
if (!resolved.success) {
|
|
49233
|
+
return { success: false, error: resolved.error };
|
|
49234
|
+
}
|
|
49235
|
+
const { owner, repo } = resolved.repo;
|
|
49236
|
+
try {
|
|
49237
|
+
let fileContent;
|
|
49238
|
+
let fileSha;
|
|
49239
|
+
let fileSize;
|
|
49240
|
+
const refParam = args.ref ? `?ref=${encodeURIComponent(args.ref)}` : "";
|
|
49241
|
+
const contentResp = await githubFetch(
|
|
49242
|
+
connector,
|
|
49243
|
+
`/repos/${owner}/${repo}/contents/${args.path}${refParam}`,
|
|
49244
|
+
{ userId }
|
|
49245
|
+
);
|
|
49246
|
+
if (contentResp.type !== "file") {
|
|
49247
|
+
return {
|
|
49248
|
+
success: false,
|
|
49249
|
+
error: `Path is not a file: ${args.path} (type: ${contentResp.type}). Use search_files to explore the repository.`,
|
|
49250
|
+
path: args.path
|
|
49251
|
+
};
|
|
49252
|
+
}
|
|
49253
|
+
fileSha = contentResp.sha;
|
|
49254
|
+
fileSize = contentResp.size;
|
|
49255
|
+
if (contentResp.content && contentResp.encoding === "base64") {
|
|
49256
|
+
fileContent = Buffer.from(contentResp.content, "base64").toString("utf-8");
|
|
49257
|
+
} else if (contentResp.git_url) {
|
|
49258
|
+
const blob = await githubFetch(
|
|
49259
|
+
connector,
|
|
49260
|
+
contentResp.git_url,
|
|
49261
|
+
{ userId }
|
|
49262
|
+
);
|
|
49263
|
+
fileContent = Buffer.from(blob.content, "base64").toString("utf-8");
|
|
49264
|
+
fileSize = blob.size;
|
|
49265
|
+
} else {
|
|
49266
|
+
return {
|
|
49267
|
+
success: false,
|
|
49268
|
+
error: `Cannot read file content: ${args.path} (no content or git_url in response)`,
|
|
49269
|
+
path: args.path
|
|
49270
|
+
};
|
|
49271
|
+
}
|
|
49272
|
+
const offset = args.offset ?? 1;
|
|
49273
|
+
const limit = args.limit ?? 2e3;
|
|
49274
|
+
const allLines = fileContent.split("\n");
|
|
49275
|
+
const totalLines = allLines.length;
|
|
49276
|
+
const startIndex = Math.max(0, offset - 1);
|
|
49277
|
+
const endIndex = Math.min(totalLines, startIndex + limit);
|
|
49278
|
+
const selectedLines = allLines.slice(startIndex, endIndex);
|
|
49279
|
+
const lineNumberWidth = String(endIndex).length;
|
|
49280
|
+
const formattedLines = selectedLines.map((line, i) => {
|
|
49281
|
+
const lineNum = startIndex + i + 1;
|
|
49282
|
+
const paddedNum = String(lineNum).padStart(lineNumberWidth, " ");
|
|
49283
|
+
const truncatedLine = line.length > 2e3 ? line.substring(0, 2e3) + "..." : line;
|
|
49284
|
+
return `${paddedNum} ${truncatedLine}`;
|
|
49285
|
+
});
|
|
49286
|
+
const truncated = endIndex < totalLines;
|
|
49287
|
+
const result = formattedLines.join("\n");
|
|
49288
|
+
return {
|
|
49289
|
+
success: true,
|
|
49290
|
+
content: result,
|
|
49291
|
+
path: args.path,
|
|
49292
|
+
size: fileSize,
|
|
49293
|
+
lines: totalLines,
|
|
49294
|
+
truncated,
|
|
49295
|
+
sha: fileSha
|
|
49296
|
+
};
|
|
49297
|
+
} catch (error) {
|
|
49298
|
+
return {
|
|
49299
|
+
success: false,
|
|
49300
|
+
error: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
|
|
49301
|
+
path: args.path
|
|
49302
|
+
};
|
|
49303
|
+
}
|
|
49304
|
+
}
|
|
49305
|
+
};
|
|
49306
|
+
}
|
|
49307
|
+
|
|
49308
|
+
// src/tools/github/getPR.ts
|
|
49309
|
+
function createGetPRTool(connector, userId) {
|
|
49310
|
+
return {
|
|
49311
|
+
definition: {
|
|
49312
|
+
type: "function",
|
|
49313
|
+
function: {
|
|
49314
|
+
name: "get_pr",
|
|
49315
|
+
description: `Get full details of a pull request from a GitHub repository.
|
|
49316
|
+
|
|
49317
|
+
Returns: title, description, state, author, labels, reviewers, merge status, branches, file stats, and more.
|
|
49318
|
+
|
|
49319
|
+
EXAMPLES:
|
|
49320
|
+
- Get PR: { "pull_number": 123 }
|
|
49321
|
+
- Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
|
|
49322
|
+
parameters: {
|
|
49323
|
+
type: "object",
|
|
49324
|
+
properties: {
|
|
49325
|
+
repository: {
|
|
49326
|
+
type: "string",
|
|
49327
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49328
|
+
},
|
|
49329
|
+
pull_number: {
|
|
49330
|
+
type: "number",
|
|
49331
|
+
description: "Pull request number"
|
|
49332
|
+
}
|
|
49333
|
+
},
|
|
49334
|
+
required: ["pull_number"]
|
|
49335
|
+
}
|
|
49336
|
+
}
|
|
49337
|
+
},
|
|
49338
|
+
describeCall: (args) => {
|
|
49339
|
+
const parts = [`#${args.pull_number}`];
|
|
49340
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49341
|
+
return parts.join(" ");
|
|
49342
|
+
},
|
|
49343
|
+
permission: {
|
|
49344
|
+
scope: "session",
|
|
49345
|
+
riskLevel: "low",
|
|
49346
|
+
approvalMessage: `Get pull request details from GitHub via ${connector.displayName}`
|
|
49347
|
+
},
|
|
49348
|
+
execute: async (args) => {
|
|
49349
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49350
|
+
if (!resolved.success) {
|
|
49351
|
+
return { success: false, error: resolved.error };
|
|
49352
|
+
}
|
|
49353
|
+
const { owner, repo } = resolved.repo;
|
|
49354
|
+
try {
|
|
49355
|
+
const pr = await githubFetch(
|
|
49356
|
+
connector,
|
|
49357
|
+
`/repos/${owner}/${repo}/pulls/${args.pull_number}`,
|
|
49358
|
+
{ userId }
|
|
49359
|
+
);
|
|
49360
|
+
return {
|
|
49361
|
+
success: true,
|
|
49362
|
+
data: {
|
|
49363
|
+
number: pr.number,
|
|
49364
|
+
title: pr.title,
|
|
49365
|
+
body: pr.body,
|
|
49366
|
+
state: pr.state,
|
|
49367
|
+
draft: pr.draft,
|
|
49368
|
+
author: pr.user.login,
|
|
49369
|
+
labels: pr.labels.map((l) => l.name),
|
|
49370
|
+
reviewers: pr.requested_reviewers.map((r) => r.login),
|
|
49371
|
+
mergeable: pr.mergeable,
|
|
49372
|
+
head: pr.head.ref,
|
|
49373
|
+
base: pr.base.ref,
|
|
49374
|
+
url: pr.html_url,
|
|
49375
|
+
created_at: pr.created_at,
|
|
49376
|
+
updated_at: pr.updated_at,
|
|
49377
|
+
additions: pr.additions,
|
|
49378
|
+
deletions: pr.deletions,
|
|
49379
|
+
changed_files: pr.changed_files
|
|
49380
|
+
}
|
|
49381
|
+
};
|
|
49382
|
+
} catch (error) {
|
|
49383
|
+
return {
|
|
49384
|
+
success: false,
|
|
49385
|
+
error: `Failed to get PR: ${error instanceof Error ? error.message : String(error)}`
|
|
49386
|
+
};
|
|
49387
|
+
}
|
|
49388
|
+
}
|
|
49389
|
+
};
|
|
49390
|
+
}
|
|
49391
|
+
|
|
49392
|
+
// src/tools/github/prFiles.ts
|
|
49393
|
+
function createPRFilesTool(connector, userId) {
|
|
49394
|
+
return {
|
|
49395
|
+
definition: {
|
|
49396
|
+
type: "function",
|
|
49397
|
+
function: {
|
|
49398
|
+
name: "pr_files",
|
|
49399
|
+
description: `Get the files changed in a pull request with diffs.
|
|
49400
|
+
|
|
49401
|
+
Returns: filename, status (added/modified/removed/renamed), additions, deletions, and patch (diff) content for each file.
|
|
49402
|
+
|
|
49403
|
+
EXAMPLES:
|
|
49404
|
+
- Get files: { "pull_number": 123 }
|
|
49405
|
+
- Specific repo: { "repository": "owner/repo", "pull_number": 456 }
|
|
49406
|
+
|
|
49407
|
+
NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent for binary files.`,
|
|
49408
|
+
parameters: {
|
|
49409
|
+
type: "object",
|
|
49410
|
+
properties: {
|
|
49411
|
+
repository: {
|
|
49412
|
+
type: "string",
|
|
49413
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49414
|
+
},
|
|
49415
|
+
pull_number: {
|
|
49416
|
+
type: "number",
|
|
49417
|
+
description: "Pull request number"
|
|
49418
|
+
}
|
|
49419
|
+
},
|
|
49420
|
+
required: ["pull_number"]
|
|
49421
|
+
}
|
|
49422
|
+
}
|
|
49423
|
+
},
|
|
49424
|
+
describeCall: (args) => {
|
|
49425
|
+
const parts = [`files for #${args.pull_number}`];
|
|
49426
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49427
|
+
return parts.join(" ");
|
|
49428
|
+
},
|
|
49429
|
+
permission: {
|
|
49430
|
+
scope: "session",
|
|
49431
|
+
riskLevel: "low",
|
|
49432
|
+
approvalMessage: `Get PR changed files from GitHub via ${connector.displayName}`
|
|
49433
|
+
},
|
|
49434
|
+
execute: async (args) => {
|
|
49435
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49436
|
+
if (!resolved.success) {
|
|
49437
|
+
return { success: false, error: resolved.error };
|
|
49438
|
+
}
|
|
49439
|
+
const { owner, repo } = resolved.repo;
|
|
49440
|
+
try {
|
|
49441
|
+
const files = await githubFetch(
|
|
49442
|
+
connector,
|
|
49443
|
+
`/repos/${owner}/${repo}/pulls/${args.pull_number}/files`,
|
|
49444
|
+
{
|
|
49445
|
+
userId,
|
|
49446
|
+
queryParams: { per_page: 100 }
|
|
49447
|
+
}
|
|
49448
|
+
);
|
|
49449
|
+
return {
|
|
49450
|
+
success: true,
|
|
49451
|
+
files: files.map((f) => ({
|
|
49452
|
+
filename: f.filename,
|
|
49453
|
+
status: f.status,
|
|
49454
|
+
additions: f.additions,
|
|
49455
|
+
deletions: f.deletions,
|
|
49456
|
+
changes: f.changes,
|
|
49457
|
+
patch: f.patch
|
|
49458
|
+
})),
|
|
49459
|
+
count: files.length
|
|
49460
|
+
};
|
|
49461
|
+
} catch (error) {
|
|
49462
|
+
return {
|
|
49463
|
+
success: false,
|
|
49464
|
+
error: `Failed to get PR files: ${error instanceof Error ? error.message : String(error)}`
|
|
49465
|
+
};
|
|
49466
|
+
}
|
|
49467
|
+
}
|
|
49468
|
+
};
|
|
49469
|
+
}
|
|
49470
|
+
|
|
49471
|
+
// src/tools/github/prComments.ts
|
|
49472
|
+
function createPRCommentsTool(connector, userId) {
|
|
49473
|
+
return {
|
|
49474
|
+
definition: {
|
|
49475
|
+
type: "function",
|
|
49476
|
+
function: {
|
|
49477
|
+
name: "pr_comments",
|
|
49478
|
+
description: `Get all comments and reviews on a pull request.
|
|
49479
|
+
|
|
49480
|
+
Returns a unified list of:
|
|
49481
|
+
- **review_comment**: Line-level comments on specific code (includes file path and line number)
|
|
49482
|
+
- **review**: Full reviews (approve/request changes/comment)
|
|
49483
|
+
- **comment**: General comments on the PR (issue-level)
|
|
49484
|
+
|
|
49485
|
+
All entries are sorted by creation date (oldest first).
|
|
49486
|
+
|
|
49487
|
+
EXAMPLES:
|
|
49488
|
+
- Get comments: { "pull_number": 123 }
|
|
49489
|
+
- Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
|
|
49490
|
+
parameters: {
|
|
49491
|
+
type: "object",
|
|
49492
|
+
properties: {
|
|
49493
|
+
repository: {
|
|
49494
|
+
type: "string",
|
|
49495
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49496
|
+
},
|
|
49497
|
+
pull_number: {
|
|
49498
|
+
type: "number",
|
|
49499
|
+
description: "Pull request number"
|
|
49500
|
+
}
|
|
49501
|
+
},
|
|
49502
|
+
required: ["pull_number"]
|
|
49503
|
+
}
|
|
49504
|
+
}
|
|
49505
|
+
},
|
|
49506
|
+
describeCall: (args) => {
|
|
49507
|
+
const parts = [`comments for #${args.pull_number}`];
|
|
49508
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49509
|
+
return parts.join(" ");
|
|
49510
|
+
},
|
|
49511
|
+
permission: {
|
|
49512
|
+
scope: "session",
|
|
49513
|
+
riskLevel: "low",
|
|
49514
|
+
approvalMessage: `Get PR comments and reviews from GitHub via ${connector.displayName}`
|
|
49515
|
+
},
|
|
49516
|
+
execute: async (args) => {
|
|
49517
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49518
|
+
if (!resolved.success) {
|
|
49519
|
+
return { success: false, error: resolved.error };
|
|
49520
|
+
}
|
|
49521
|
+
const { owner, repo } = resolved.repo;
|
|
49522
|
+
try {
|
|
49523
|
+
const basePath = `/repos/${owner}/${repo}`;
|
|
49524
|
+
const queryOpts = { userId, queryParams: { per_page: 100 } };
|
|
49525
|
+
const [reviewComments, reviews, issueComments] = await Promise.all([
|
|
49526
|
+
githubFetch(
|
|
49527
|
+
connector,
|
|
49528
|
+
`${basePath}/pulls/${args.pull_number}/comments`,
|
|
49529
|
+
queryOpts
|
|
49530
|
+
),
|
|
49531
|
+
githubFetch(
|
|
49532
|
+
connector,
|
|
49533
|
+
`${basePath}/pulls/${args.pull_number}/reviews`,
|
|
49534
|
+
queryOpts
|
|
49535
|
+
),
|
|
49536
|
+
githubFetch(
|
|
49537
|
+
connector,
|
|
49538
|
+
`${basePath}/issues/${args.pull_number}/comments`,
|
|
49539
|
+
queryOpts
|
|
49540
|
+
)
|
|
49541
|
+
]);
|
|
49542
|
+
const allComments = [];
|
|
49543
|
+
for (const rc of reviewComments) {
|
|
49544
|
+
allComments.push({
|
|
49545
|
+
id: rc.id,
|
|
49546
|
+
type: "review_comment",
|
|
49547
|
+
author: rc.user.login,
|
|
49548
|
+
body: rc.body,
|
|
49549
|
+
created_at: rc.created_at,
|
|
49550
|
+
path: rc.path,
|
|
49551
|
+
line: rc.line ?? rc.original_line ?? void 0
|
|
49552
|
+
});
|
|
49553
|
+
}
|
|
49554
|
+
for (const r of reviews) {
|
|
49555
|
+
if (!r.body && r.state === "APPROVED") continue;
|
|
49556
|
+
allComments.push({
|
|
49557
|
+
id: r.id,
|
|
49558
|
+
type: "review",
|
|
49559
|
+
author: r.user.login,
|
|
49560
|
+
body: r.body || `[${r.state}]`,
|
|
49561
|
+
created_at: r.submitted_at,
|
|
49562
|
+
state: r.state
|
|
49563
|
+
});
|
|
49564
|
+
}
|
|
49565
|
+
for (const ic of issueComments) {
|
|
49566
|
+
allComments.push({
|
|
49567
|
+
id: ic.id,
|
|
49568
|
+
type: "comment",
|
|
49569
|
+
author: ic.user.login,
|
|
49570
|
+
body: ic.body,
|
|
49571
|
+
created_at: ic.created_at
|
|
49572
|
+
});
|
|
49573
|
+
}
|
|
49574
|
+
allComments.sort(
|
|
49575
|
+
(a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
|
|
49576
|
+
);
|
|
49577
|
+
return {
|
|
49578
|
+
success: true,
|
|
49579
|
+
comments: allComments,
|
|
49580
|
+
count: allComments.length
|
|
49581
|
+
};
|
|
49582
|
+
} catch (error) {
|
|
49583
|
+
return {
|
|
49584
|
+
success: false,
|
|
49585
|
+
error: `Failed to get PR comments: ${error instanceof Error ? error.message : String(error)}`
|
|
49586
|
+
};
|
|
49587
|
+
}
|
|
49588
|
+
}
|
|
49589
|
+
};
|
|
49590
|
+
}
|
|
49591
|
+
|
|
49592
|
+
// src/tools/github/createPR.ts
|
|
49593
|
+
function createCreatePRTool(connector, userId) {
|
|
49594
|
+
return {
|
|
49595
|
+
definition: {
|
|
49596
|
+
type: "function",
|
|
49597
|
+
function: {
|
|
49598
|
+
name: "create_pr",
|
|
49599
|
+
description: `Create a pull request on a GitHub repository.
|
|
49600
|
+
|
|
49601
|
+
USAGE:
|
|
49602
|
+
- Specify source branch (head) and target branch (base)
|
|
49603
|
+
- Optionally create as draft
|
|
49604
|
+
|
|
49605
|
+
EXAMPLES:
|
|
49606
|
+
- Create PR: { "title": "Add feature", "head": "feature-branch", "base": "main" }
|
|
49607
|
+
- Draft PR: { "title": "WIP: Refactor", "head": "refactor", "base": "develop", "draft": true }
|
|
49608
|
+
- With body: { "title": "Fix bug #42", "body": "Fixes the login issue\\n\\n## Changes\\n- Fixed auth flow", "head": "fix/42", "base": "main" }`,
|
|
49609
|
+
parameters: {
|
|
49610
|
+
type: "object",
|
|
49611
|
+
properties: {
|
|
49612
|
+
repository: {
|
|
49613
|
+
type: "string",
|
|
49614
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49615
|
+
},
|
|
49616
|
+
title: {
|
|
49617
|
+
type: "string",
|
|
49618
|
+
description: "Pull request title"
|
|
49619
|
+
},
|
|
49620
|
+
body: {
|
|
49621
|
+
type: "string",
|
|
49622
|
+
description: "Pull request description/body (Markdown supported)"
|
|
49623
|
+
},
|
|
49624
|
+
head: {
|
|
49625
|
+
type: "string",
|
|
49626
|
+
description: "Source branch name (the branch with your changes)"
|
|
49627
|
+
},
|
|
49628
|
+
base: {
|
|
49629
|
+
type: "string",
|
|
49630
|
+
description: 'Target branch name (the branch you want to merge into, e.g., "main")'
|
|
49631
|
+
},
|
|
49632
|
+
draft: {
|
|
49633
|
+
type: "boolean",
|
|
49634
|
+
description: "Create as a draft pull request (default: false)"
|
|
49635
|
+
}
|
|
49636
|
+
},
|
|
49637
|
+
required: ["title", "head", "base"]
|
|
49638
|
+
}
|
|
49639
|
+
}
|
|
49640
|
+
},
|
|
49641
|
+
describeCall: (args) => {
|
|
49642
|
+
const parts = [args.title];
|
|
49643
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49644
|
+
return parts.join(" ");
|
|
49645
|
+
},
|
|
49646
|
+
permission: {
|
|
49647
|
+
scope: "session",
|
|
49648
|
+
riskLevel: "medium",
|
|
49649
|
+
approvalMessage: `Create a pull request on GitHub via ${connector.displayName}`
|
|
49650
|
+
},
|
|
49651
|
+
execute: async (args) => {
|
|
49652
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49653
|
+
if (!resolved.success) {
|
|
49654
|
+
return { success: false, error: resolved.error };
|
|
49655
|
+
}
|
|
49656
|
+
const { owner, repo } = resolved.repo;
|
|
49657
|
+
try {
|
|
49658
|
+
const pr = await githubFetch(
|
|
49659
|
+
connector,
|
|
49660
|
+
`/repos/${owner}/${repo}/pulls`,
|
|
49661
|
+
{
|
|
49662
|
+
method: "POST",
|
|
49663
|
+
userId,
|
|
49664
|
+
body: {
|
|
49665
|
+
title: args.title,
|
|
49666
|
+
body: args.body,
|
|
49667
|
+
head: args.head,
|
|
49668
|
+
base: args.base,
|
|
49669
|
+
draft: args.draft ?? false
|
|
49670
|
+
}
|
|
49671
|
+
}
|
|
49672
|
+
);
|
|
49673
|
+
return {
|
|
49674
|
+
success: true,
|
|
49675
|
+
data: {
|
|
49676
|
+
number: pr.number,
|
|
49677
|
+
url: pr.html_url,
|
|
49678
|
+
state: pr.state,
|
|
49679
|
+
title: pr.title
|
|
49680
|
+
}
|
|
49681
|
+
};
|
|
49682
|
+
} catch (error) {
|
|
49683
|
+
return {
|
|
49684
|
+
success: false,
|
|
49685
|
+
error: `Failed to create PR: ${error instanceof Error ? error.message : String(error)}`
|
|
49686
|
+
};
|
|
49687
|
+
}
|
|
49688
|
+
}
|
|
49689
|
+
};
|
|
49690
|
+
}
|
|
49691
|
+
|
|
49692
|
+
// src/tools/github/register.ts
|
|
49693
|
+
function registerGitHubTools() {
|
|
49694
|
+
ConnectorTools.registerService("github", (connector, userId) => {
|
|
49695
|
+
return [
|
|
49696
|
+
createSearchFilesTool(connector, userId),
|
|
49697
|
+
createSearchCodeTool(connector, userId),
|
|
49698
|
+
createGitHubReadFileTool(connector, userId),
|
|
49699
|
+
createGetPRTool(connector, userId),
|
|
49700
|
+
createPRFilesTool(connector, userId),
|
|
49701
|
+
createPRCommentsTool(connector, userId),
|
|
49702
|
+
createCreatePRTool(connector, userId)
|
|
49703
|
+
];
|
|
49704
|
+
});
|
|
49705
|
+
}
|
|
49706
|
+
|
|
49707
|
+
// src/tools/github/index.ts
|
|
49708
|
+
registerGitHubTools();
|
|
49709
|
+
|
|
48464
49710
|
// src/tools/registry.generated.ts
|
|
48465
49711
|
var toolRegistry = [
|
|
48466
49712
|
{
|
|
@@ -48514,7 +49760,7 @@ var toolRegistry = [
|
|
|
48514
49760
|
displayName: "Read File",
|
|
48515
49761
|
category: "filesystem",
|
|
48516
49762
|
description: "Read content from a file on the local filesystem.",
|
|
48517
|
-
tool:
|
|
49763
|
+
tool: readFile5,
|
|
48518
49764
|
safeByDefault: true
|
|
48519
49765
|
},
|
|
48520
49766
|
{
|
|
@@ -48523,7 +49769,7 @@ var toolRegistry = [
|
|
|
48523
49769
|
displayName: "Write File",
|
|
48524
49770
|
category: "filesystem",
|
|
48525
49771
|
description: "Write content to a file on the local filesystem.",
|
|
48526
|
-
tool:
|
|
49772
|
+
tool: writeFile5,
|
|
48527
49773
|
safeByDefault: false
|
|
48528
49774
|
},
|
|
48529
49775
|
{
|
|
@@ -48752,8 +49998,8 @@ var ToolRegistry = class {
|
|
|
48752
49998
|
|
|
48753
49999
|
// src/tools/index.ts
|
|
48754
50000
|
var developerTools = [
|
|
48755
|
-
|
|
48756
|
-
|
|
50001
|
+
readFile5,
|
|
50002
|
+
writeFile5,
|
|
48757
50003
|
editFile,
|
|
48758
50004
|
glob,
|
|
48759
50005
|
grep,
|
|
@@ -48977,7 +50223,8 @@ exports.ExternalDependencyHandler = ExternalDependencyHandler;
|
|
|
48977
50223
|
exports.FileAgentDefinitionStorage = FileAgentDefinitionStorage;
|
|
48978
50224
|
exports.FileConnectorStorage = FileConnectorStorage;
|
|
48979
50225
|
exports.FileContextStorage = FileContextStorage;
|
|
48980
|
-
exports.FileMediaOutputHandler =
|
|
50226
|
+
exports.FileMediaOutputHandler = FileMediaStorage;
|
|
50227
|
+
exports.FileMediaStorage = FileMediaStorage;
|
|
48981
50228
|
exports.FilePersistentInstructionsStorage = FilePersistentInstructionsStorage;
|
|
48982
50229
|
exports.FileStorage = FileStorage;
|
|
48983
50230
|
exports.HookManager = HookManager;
|
|
@@ -49083,11 +50330,15 @@ exports.createAgentStorage = createAgentStorage;
|
|
|
49083
50330
|
exports.createAuthenticatedFetch = createAuthenticatedFetch;
|
|
49084
50331
|
exports.createBashTool = createBashTool;
|
|
49085
50332
|
exports.createConnectorFromTemplate = createConnectorFromTemplate;
|
|
50333
|
+
exports.createCreatePRTool = createCreatePRTool;
|
|
49086
50334
|
exports.createEditFileTool = createEditFileTool;
|
|
49087
50335
|
exports.createEstimator = createEstimator;
|
|
49088
50336
|
exports.createExecuteJavaScriptTool = createExecuteJavaScriptTool;
|
|
49089
50337
|
exports.createFileAgentDefinitionStorage = createFileAgentDefinitionStorage;
|
|
49090
50338
|
exports.createFileContextStorage = createFileContextStorage;
|
|
50339
|
+
exports.createFileMediaStorage = createFileMediaStorage;
|
|
50340
|
+
exports.createGetPRTool = createGetPRTool;
|
|
50341
|
+
exports.createGitHubReadFileTool = createGitHubReadFileTool;
|
|
49091
50342
|
exports.createGlobTool = createGlobTool;
|
|
49092
50343
|
exports.createGrepTool = createGrepTool;
|
|
49093
50344
|
exports.createImageGenerationTool = createImageGenerationTool;
|
|
@@ -49095,9 +50346,13 @@ exports.createImageProvider = createImageProvider;
|
|
|
49095
50346
|
exports.createListDirectoryTool = createListDirectoryTool;
|
|
49096
50347
|
exports.createMessageWithImages = createMessageWithImages;
|
|
49097
50348
|
exports.createMetricsCollector = createMetricsCollector;
|
|
50349
|
+
exports.createPRCommentsTool = createPRCommentsTool;
|
|
50350
|
+
exports.createPRFilesTool = createPRFilesTool;
|
|
49098
50351
|
exports.createPlan = createPlan;
|
|
49099
50352
|
exports.createProvider = createProvider;
|
|
49100
50353
|
exports.createReadFileTool = createReadFileTool;
|
|
50354
|
+
exports.createSearchCodeTool = createSearchCodeTool;
|
|
50355
|
+
exports.createSearchFilesTool = createSearchFilesTool;
|
|
49101
50356
|
exports.createSpeechToTextTool = createSpeechToTextTool;
|
|
49102
50357
|
exports.createTask = createTask;
|
|
49103
50358
|
exports.createTextMessage = createTextMessage;
|
|
@@ -49137,6 +50392,7 @@ exports.getImageModelInfo = getImageModelInfo;
|
|
|
49137
50392
|
exports.getImageModelsByVendor = getImageModelsByVendor;
|
|
49138
50393
|
exports.getImageModelsWithFeature = getImageModelsWithFeature;
|
|
49139
50394
|
exports.getMediaOutputHandler = getMediaOutputHandler;
|
|
50395
|
+
exports.getMediaStorage = getMediaStorage;
|
|
49140
50396
|
exports.getModelInfo = getModelInfo;
|
|
49141
50397
|
exports.getModelsByVendor = getModelsByVendor;
|
|
49142
50398
|
exports.getNextExecutableTasks = getNextExecutableTasks;
|
|
@@ -49159,6 +50415,7 @@ exports.getToolsByCategory = getToolsByCategory;
|
|
|
49159
50415
|
exports.getToolsRequiringConnector = getToolsRequiringConnector;
|
|
49160
50416
|
exports.getVendorAuthTemplate = getVendorAuthTemplate;
|
|
49161
50417
|
exports.getVendorColor = getVendorColor;
|
|
50418
|
+
exports.getVendorDefaultBaseURL = getVendorDefaultBaseURL;
|
|
49162
50419
|
exports.getVendorInfo = getVendorInfo;
|
|
49163
50420
|
exports.getVendorLogo = getVendorLogo;
|
|
49164
50421
|
exports.getVendorLogoCdnUrl = getVendorLogoCdnUrl;
|
|
@@ -49197,15 +50454,18 @@ exports.listVendors = listVendors;
|
|
|
49197
50454
|
exports.listVendorsByAuthType = listVendorsByAuthType;
|
|
49198
50455
|
exports.listVendorsByCategory = listVendorsByCategory;
|
|
49199
50456
|
exports.listVendorsWithLogos = listVendorsWithLogos;
|
|
50457
|
+
exports.parseRepository = parseRepository;
|
|
49200
50458
|
exports.readClipboardImage = readClipboardImage;
|
|
49201
|
-
exports.readFile =
|
|
50459
|
+
exports.readFile = readFile5;
|
|
49202
50460
|
exports.registerScrapeProvider = registerScrapeProvider;
|
|
49203
50461
|
exports.resolveConnector = resolveConnector;
|
|
49204
50462
|
exports.resolveDependencies = resolveDependencies;
|
|
50463
|
+
exports.resolveRepository = resolveRepository;
|
|
49205
50464
|
exports.retryWithBackoff = retryWithBackoff;
|
|
49206
50465
|
exports.scopeEquals = scopeEquals;
|
|
49207
50466
|
exports.scopeMatches = scopeMatches;
|
|
49208
50467
|
exports.setMediaOutputHandler = setMediaOutputHandler;
|
|
50468
|
+
exports.setMediaStorage = setMediaStorage;
|
|
49209
50469
|
exports.setMetricsCollector = setMetricsCollector;
|
|
49210
50470
|
exports.simpleTokenEstimator = simpleTokenEstimator;
|
|
49211
50471
|
exports.toConnectorOptions = toConnectorOptions;
|
|
@@ -49213,6 +50473,6 @@ exports.toolRegistry = toolRegistry;
|
|
|
49213
50473
|
exports.tools = tools_exports;
|
|
49214
50474
|
exports.updateTaskStatus = updateTaskStatus;
|
|
49215
50475
|
exports.validatePath = validatePath;
|
|
49216
|
-
exports.writeFile =
|
|
50476
|
+
exports.writeFile = writeFile5;
|
|
49217
50477
|
//# sourceMappingURL=index.cjs.map
|
|
49218
50478
|
//# sourceMappingURL=index.cjs.map
|