@everworker/oneringai 0.1.3 → 0.2.0
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 +41 -27
- package/dist/{ImageModel-BkAX5Rr5.d.ts → IProvider-DcYJ3YE-.d.ts} +25 -358
- package/dist/{ImageModel-DtN780fU.d.cts → IProvider-c4QCbPjn.d.cts} +25 -358
- package/dist/ImageModel-BJ2mVPGV.d.ts +337 -0
- package/dist/ImageModel-BWN6VVS6.d.cts +337 -0
- 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 +3 -2
- package/dist/capabilities/agents/index.d.ts +3 -2
- package/dist/capabilities/images/index.cjs +8 -1
- package/dist/capabilities/images/index.cjs.map +1 -1
- package/dist/capabilities/images/index.d.cts +3 -2
- package/dist/capabilities/images/index.d.ts +3 -2
- package/dist/capabilities/images/index.js +8 -1
- package/dist/capabilities/images/index.js.map +1 -1
- package/dist/{index-BmOYeqU7.d.ts → index-B5UaeEvK.d.ts} +10 -5
- package/dist/{index-DCzFlLoN.d.cts → index-MJ14lkui.d.cts} +10 -5
- package/dist/index.cjs +2020 -1094
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +733 -417
- package/dist/index.d.ts +733 -417
- package/dist/index.js +1898 -986
- 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 +6 -4
- package/dist/IProvider-BP49c93d.d.cts +0 -22
- package/dist/IProvider-BP49c93d.d.ts +0 -22
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"
|
|
@@ -2034,7 +2034,14 @@ var init_Connector = __esm({
|
|
|
2034
2034
|
}
|
|
2035
2035
|
const startTime = Date.now();
|
|
2036
2036
|
this.requestCount++;
|
|
2037
|
-
|
|
2037
|
+
let url2;
|
|
2038
|
+
if (endpoint.startsWith("http")) {
|
|
2039
|
+
url2 = endpoint;
|
|
2040
|
+
} else {
|
|
2041
|
+
const base = (this.baseURL ?? "").replace(/\/+$/, "");
|
|
2042
|
+
const path6 = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
|
|
2043
|
+
url2 = `${base}${path6}`;
|
|
2044
|
+
}
|
|
2038
2045
|
const timeout = options?.timeout ?? this.config.timeout ?? exports.DEFAULT_CONNECTOR_TIMEOUT;
|
|
2039
2046
|
if (this.config.logging?.enabled) {
|
|
2040
2047
|
this.logRequest(url2, options);
|
|
@@ -14555,12 +14562,12 @@ var require_dist = __commonJS({
|
|
|
14555
14562
|
throw new Error(`Unknown format "${name}"`);
|
|
14556
14563
|
return f;
|
|
14557
14564
|
};
|
|
14558
|
-
function addFormats(ajv, list,
|
|
14565
|
+
function addFormats(ajv, list, fs17, exportName) {
|
|
14559
14566
|
var _a;
|
|
14560
14567
|
var _b;
|
|
14561
14568
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
14562
14569
|
for (const f of list)
|
|
14563
|
-
ajv.addFormat(f,
|
|
14570
|
+
ajv.addFormat(f, fs17[f]);
|
|
14564
14571
|
}
|
|
14565
14572
|
module.exports = exports$1 = formatsPlugin;
|
|
14566
14573
|
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
@@ -14573,7 +14580,7 @@ var require_windows = __commonJS({
|
|
|
14573
14580
|
"node_modules/isexe/windows.js"(exports$1, module) {
|
|
14574
14581
|
module.exports = isexe;
|
|
14575
14582
|
isexe.sync = sync;
|
|
14576
|
-
var
|
|
14583
|
+
var fs17 = __require("fs");
|
|
14577
14584
|
function checkPathExt(path6, options) {
|
|
14578
14585
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
14579
14586
|
if (!pathext) {
|
|
@@ -14591,19 +14598,19 @@ var require_windows = __commonJS({
|
|
|
14591
14598
|
}
|
|
14592
14599
|
return false;
|
|
14593
14600
|
}
|
|
14594
|
-
function checkStat(
|
|
14595
|
-
if (!
|
|
14601
|
+
function checkStat(stat6, path6, options) {
|
|
14602
|
+
if (!stat6.isSymbolicLink() && !stat6.isFile()) {
|
|
14596
14603
|
return false;
|
|
14597
14604
|
}
|
|
14598
14605
|
return checkPathExt(path6, options);
|
|
14599
14606
|
}
|
|
14600
14607
|
function isexe(path6, options, cb) {
|
|
14601
|
-
|
|
14602
|
-
cb(er, er ? false : checkStat(
|
|
14608
|
+
fs17.stat(path6, function(er, stat6) {
|
|
14609
|
+
cb(er, er ? false : checkStat(stat6, path6, options));
|
|
14603
14610
|
});
|
|
14604
14611
|
}
|
|
14605
14612
|
function sync(path6, options) {
|
|
14606
|
-
return checkStat(
|
|
14613
|
+
return checkStat(fs17.statSync(path6), path6, options);
|
|
14607
14614
|
}
|
|
14608
14615
|
}
|
|
14609
14616
|
});
|
|
@@ -14613,22 +14620,22 @@ var require_mode = __commonJS({
|
|
|
14613
14620
|
"node_modules/isexe/mode.js"(exports$1, module) {
|
|
14614
14621
|
module.exports = isexe;
|
|
14615
14622
|
isexe.sync = sync;
|
|
14616
|
-
var
|
|
14623
|
+
var fs17 = __require("fs");
|
|
14617
14624
|
function isexe(path6, options, cb) {
|
|
14618
|
-
|
|
14619
|
-
cb(er, er ? false : checkStat(
|
|
14625
|
+
fs17.stat(path6, function(er, stat6) {
|
|
14626
|
+
cb(er, er ? false : checkStat(stat6, options));
|
|
14620
14627
|
});
|
|
14621
14628
|
}
|
|
14622
14629
|
function sync(path6, options) {
|
|
14623
|
-
return checkStat(
|
|
14630
|
+
return checkStat(fs17.statSync(path6), options);
|
|
14624
14631
|
}
|
|
14625
|
-
function checkStat(
|
|
14626
|
-
return
|
|
14632
|
+
function checkStat(stat6, options) {
|
|
14633
|
+
return stat6.isFile() && checkMode(stat6, options);
|
|
14627
14634
|
}
|
|
14628
|
-
function checkMode(
|
|
14629
|
-
var mod =
|
|
14630
|
-
var uid =
|
|
14631
|
-
var gid =
|
|
14635
|
+
function checkMode(stat6, options) {
|
|
14636
|
+
var mod = stat6.mode;
|
|
14637
|
+
var uid = stat6.uid;
|
|
14638
|
+
var gid = stat6.gid;
|
|
14632
14639
|
var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
|
|
14633
14640
|
var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
|
|
14634
14641
|
var u = parseInt("100", 8);
|
|
@@ -14902,16 +14909,16 @@ var require_shebang_command = __commonJS({
|
|
|
14902
14909
|
// node_modules/cross-spawn/lib/util/readShebang.js
|
|
14903
14910
|
var require_readShebang = __commonJS({
|
|
14904
14911
|
"node_modules/cross-spawn/lib/util/readShebang.js"(exports$1, module) {
|
|
14905
|
-
var
|
|
14912
|
+
var fs17 = __require("fs");
|
|
14906
14913
|
var shebangCommand = require_shebang_command();
|
|
14907
14914
|
function readShebang(command) {
|
|
14908
14915
|
const size = 150;
|
|
14909
14916
|
const buffer = Buffer.alloc(size);
|
|
14910
14917
|
let fd;
|
|
14911
14918
|
try {
|
|
14912
|
-
fd =
|
|
14913
|
-
|
|
14914
|
-
|
|
14919
|
+
fd = fs17.openSync(command, "r");
|
|
14920
|
+
fs17.readSync(fd, buffer, 0, size, 0);
|
|
14921
|
+
fs17.closeSync(fd);
|
|
14915
14922
|
} catch (e) {
|
|
14916
14923
|
}
|
|
14917
14924
|
return shebangCommand(buffer.toString());
|
|
@@ -16020,13 +16027,26 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16020
16027
|
pipeline;
|
|
16021
16028
|
/** Optional tool context for execution (set by agent before runs) */
|
|
16022
16029
|
_toolContext;
|
|
16023
|
-
|
|
16030
|
+
/** Hard timeout for tool execution (0 = disabled) */
|
|
16031
|
+
_toolExecutionTimeout;
|
|
16032
|
+
constructor(config) {
|
|
16024
16033
|
super();
|
|
16034
|
+
this._toolExecutionTimeout = config?.toolExecutionTimeout ?? 0;
|
|
16025
16035
|
this.namespaceIndex.set("default", /* @__PURE__ */ new Set());
|
|
16026
16036
|
this.toolLogger = exports.logger.child({ component: "ToolManager" });
|
|
16027
16037
|
this.pipeline = new ToolExecutionPipeline();
|
|
16028
16038
|
this.pipeline.use(new ResultNormalizerPlugin());
|
|
16029
16039
|
}
|
|
16040
|
+
/**
|
|
16041
|
+
* Get or set the hard tool execution timeout in milliseconds.
|
|
16042
|
+
* 0 = disabled (relies on tool's own timeout).
|
|
16043
|
+
*/
|
|
16044
|
+
get toolExecutionTimeout() {
|
|
16045
|
+
return this._toolExecutionTimeout;
|
|
16046
|
+
}
|
|
16047
|
+
set toolExecutionTimeout(value) {
|
|
16048
|
+
this._toolExecutionTimeout = Math.max(0, value);
|
|
16049
|
+
}
|
|
16030
16050
|
/**
|
|
16031
16051
|
* Access the execution pipeline for plugin management.
|
|
16032
16052
|
*
|
|
@@ -16524,7 +16544,7 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16524
16544
|
const startTime = Date.now();
|
|
16525
16545
|
exports.metrics.increment("tool.executed", 1, { tool: toolName });
|
|
16526
16546
|
try {
|
|
16527
|
-
const
|
|
16547
|
+
const executionPromise = breaker.execute(async () => {
|
|
16528
16548
|
const toolWithContext = {
|
|
16529
16549
|
...registration.tool,
|
|
16530
16550
|
execute: async (pipelineArgs) => {
|
|
@@ -16533,6 +16553,7 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16533
16553
|
};
|
|
16534
16554
|
return await this.pipeline.execute(toolWithContext, args);
|
|
16535
16555
|
});
|
|
16556
|
+
const result = this._toolExecutionTimeout > 0 ? await this.withHardTimeout(executionPromise, toolName, this._toolExecutionTimeout) : await executionPromise;
|
|
16536
16557
|
const duration = Date.now() - startTime;
|
|
16537
16558
|
this.recordExecution(toolName, duration, true);
|
|
16538
16559
|
const resultSummary = this.summarizeResult(result);
|
|
@@ -16595,6 +16616,29 @@ var ToolManager = class extends eventemitter3.EventEmitter {
|
|
|
16595
16616
|
return this.list();
|
|
16596
16617
|
}
|
|
16597
16618
|
// ==========================================================================
|
|
16619
|
+
// Hard Timeout
|
|
16620
|
+
// ==========================================================================
|
|
16621
|
+
/**
|
|
16622
|
+
* Wrap a promise with a hard timeout safety net.
|
|
16623
|
+
* If the promise doesn't resolve within the timeout, throws ToolExecutionError.
|
|
16624
|
+
*/
|
|
16625
|
+
async withHardTimeout(promise, toolName, timeoutMs) {
|
|
16626
|
+
let timeoutId;
|
|
16627
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
16628
|
+
timeoutId = setTimeout(() => {
|
|
16629
|
+
reject(new ToolExecutionError(
|
|
16630
|
+
toolName,
|
|
16631
|
+
`Tool execution hard timeout after ${timeoutMs}ms (safety net - tool's own timeout may have failed)`
|
|
16632
|
+
));
|
|
16633
|
+
}, timeoutMs);
|
|
16634
|
+
});
|
|
16635
|
+
try {
|
|
16636
|
+
return await Promise.race([promise, timeoutPromise]);
|
|
16637
|
+
} finally {
|
|
16638
|
+
clearTimeout(timeoutId);
|
|
16639
|
+
}
|
|
16640
|
+
}
|
|
16641
|
+
// ==========================================================================
|
|
16598
16642
|
// Circuit Breaker Management
|
|
16599
16643
|
// ==========================================================================
|
|
16600
16644
|
/**
|
|
@@ -18400,6 +18444,9 @@ var BasePluginNextGen = class {
|
|
|
18400
18444
|
}
|
|
18401
18445
|
};
|
|
18402
18446
|
|
|
18447
|
+
// src/core/context-nextgen/AgentContextNextGen.ts
|
|
18448
|
+
init_Connector();
|
|
18449
|
+
|
|
18403
18450
|
// src/domain/entities/Memory.ts
|
|
18404
18451
|
function isTaskAwareScope(scope) {
|
|
18405
18452
|
return typeof scope === "object" && scope !== null && "type" in scope;
|
|
@@ -19338,13 +19385,18 @@ Values are immediately visible - no retrieval needed.
|
|
|
19338
19385
|
- \`high\`: Keep longer. Important state.
|
|
19339
19386
|
- \`critical\`: Never auto-evicted.
|
|
19340
19387
|
|
|
19388
|
+
**UI Display:** Set \`showInUI: true\` in context_set to display the entry in the user's side panel.
|
|
19389
|
+
Values shown in the UI support the same rich markdown formatting as the chat window
|
|
19390
|
+
(see formatting instructions above). Use this for dashboards, progress displays, and results the user should see.
|
|
19391
|
+
|
|
19341
19392
|
**Tools:** context_set, context_delete, context_list`;
|
|
19342
19393
|
var contextSetDefinition = {
|
|
19343
19394
|
type: "function",
|
|
19344
19395
|
function: {
|
|
19345
19396
|
name: "context_set",
|
|
19346
19397
|
description: `Store or update a key-value pair in live context.
|
|
19347
|
-
Value appears directly in context - no retrieval needed
|
|
19398
|
+
Value appears directly in context - no retrieval needed.
|
|
19399
|
+
Set showInUI to true to also display the entry in the user's side panel.`,
|
|
19348
19400
|
parameters: {
|
|
19349
19401
|
type: "object",
|
|
19350
19402
|
properties: {
|
|
@@ -19355,6 +19407,10 @@ Value appears directly in context - no retrieval needed.`,
|
|
|
19355
19407
|
type: "string",
|
|
19356
19408
|
enum: ["low", "normal", "high", "critical"],
|
|
19357
19409
|
description: 'Eviction priority. Default: "normal"'
|
|
19410
|
+
},
|
|
19411
|
+
showInUI: {
|
|
19412
|
+
type: "boolean",
|
|
19413
|
+
description: "If true, display this entry in the user's side panel with full rich markdown rendering \u2014 same capabilities as the chat window (code blocks, tables, LaTeX, Mermaid diagrams, Vega-Lite charts, mindmaps, etc. \u2014 see formatting instructions in system prompt). Use this for dashboards, status displays, and structured results the user should see. Default: false"
|
|
19358
19414
|
}
|
|
19359
19415
|
},
|
|
19360
19416
|
required: ["key", "description", "value"]
|
|
@@ -19395,6 +19451,7 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19395
19451
|
_destroyed = false;
|
|
19396
19452
|
_tokenCache = null;
|
|
19397
19453
|
_instructionsTokenCache = null;
|
|
19454
|
+
_notifyTimer = null;
|
|
19398
19455
|
constructor(config = {}) {
|
|
19399
19456
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
19400
19457
|
}
|
|
@@ -19435,15 +19492,18 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19435
19492
|
return a.updatedAt - b.updatedAt;
|
|
19436
19493
|
});
|
|
19437
19494
|
let freed = 0;
|
|
19495
|
+
let evicted = false;
|
|
19438
19496
|
for (const entry of evictable) {
|
|
19439
19497
|
if (freed >= targetTokensToFree) break;
|
|
19440
19498
|
const entryTokens = this.estimator.estimateTokens(this.formatEntry(entry));
|
|
19441
19499
|
this.entries.delete(entry.key);
|
|
19442
19500
|
freed += entryTokens;
|
|
19501
|
+
evicted = true;
|
|
19443
19502
|
}
|
|
19444
19503
|
this._tokenCache = null;
|
|
19445
19504
|
const content = await this.getContent();
|
|
19446
19505
|
const after = content ? this.estimator.estimateTokens(content) : 0;
|
|
19506
|
+
if (evicted) this.notifyEntriesChanged();
|
|
19447
19507
|
return Math.max(0, before - after);
|
|
19448
19508
|
}
|
|
19449
19509
|
getTools() {
|
|
@@ -19455,6 +19515,7 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19455
19515
|
}
|
|
19456
19516
|
destroy() {
|
|
19457
19517
|
if (this._destroyed) return;
|
|
19518
|
+
if (this._notifyTimer) clearTimeout(this._notifyTimer);
|
|
19458
19519
|
this.entries.clear();
|
|
19459
19520
|
this._destroyed = true;
|
|
19460
19521
|
this._tokenCache = null;
|
|
@@ -19472,6 +19533,7 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19472
19533
|
this.entries.set(entry.key, entry);
|
|
19473
19534
|
}
|
|
19474
19535
|
this._tokenCache = null;
|
|
19536
|
+
this.notifyEntriesChanged();
|
|
19475
19537
|
}
|
|
19476
19538
|
// ============================================================================
|
|
19477
19539
|
// Entry Management
|
|
@@ -19479,19 +19541,21 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19479
19541
|
/**
|
|
19480
19542
|
* Store or update a key-value pair
|
|
19481
19543
|
*/
|
|
19482
|
-
set(key, description, value, priority) {
|
|
19544
|
+
set(key, description, value, priority, showInUI) {
|
|
19483
19545
|
this.assertNotDestroyed();
|
|
19484
19546
|
const entry = {
|
|
19485
19547
|
key,
|
|
19486
19548
|
description,
|
|
19487
19549
|
value,
|
|
19488
19550
|
updatedAt: Date.now(),
|
|
19489
|
-
priority: priority ?? this.config.defaultPriority
|
|
19551
|
+
priority: priority ?? this.config.defaultPriority,
|
|
19552
|
+
showInUI: showInUI ?? false
|
|
19490
19553
|
};
|
|
19491
19554
|
this.entries.set(key, entry);
|
|
19492
19555
|
this.enforceMaxEntries();
|
|
19493
19556
|
this.enforceTokenLimit();
|
|
19494
19557
|
this._tokenCache = null;
|
|
19558
|
+
this.notifyEntriesChanged();
|
|
19495
19559
|
}
|
|
19496
19560
|
/**
|
|
19497
19561
|
* Get a value by key
|
|
@@ -19513,7 +19577,10 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19513
19577
|
delete(key) {
|
|
19514
19578
|
this.assertNotDestroyed();
|
|
19515
19579
|
const deleted = this.entries.delete(key);
|
|
19516
|
-
if (deleted)
|
|
19580
|
+
if (deleted) {
|
|
19581
|
+
this._tokenCache = null;
|
|
19582
|
+
this.notifyEntriesChanged();
|
|
19583
|
+
}
|
|
19517
19584
|
return deleted;
|
|
19518
19585
|
}
|
|
19519
19586
|
/**
|
|
@@ -19525,7 +19592,8 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19525
19592
|
key: e.key,
|
|
19526
19593
|
description: e.description,
|
|
19527
19594
|
priority: e.priority,
|
|
19528
|
-
updatedAt: e.updatedAt
|
|
19595
|
+
updatedAt: e.updatedAt,
|
|
19596
|
+
showInUI: e.showInUI ?? false
|
|
19529
19597
|
}));
|
|
19530
19598
|
}
|
|
19531
19599
|
/**
|
|
@@ -19535,6 +19603,7 @@ var InContextMemoryPluginNextGen = class {
|
|
|
19535
19603
|
this.assertNotDestroyed();
|
|
19536
19604
|
this.entries.clear();
|
|
19537
19605
|
this._tokenCache = null;
|
|
19606
|
+
this.notifyEntriesChanged();
|
|
19538
19607
|
}
|
|
19539
19608
|
// ============================================================================
|
|
19540
19609
|
// Private Helpers
|
|
@@ -19598,6 +19667,20 @@ ${valueStr}
|
|
|
19598
19667
|
return a.updatedAt - b.updatedAt;
|
|
19599
19668
|
});
|
|
19600
19669
|
}
|
|
19670
|
+
/**
|
|
19671
|
+
* Debounced notification when entries change.
|
|
19672
|
+
* Calls config.onEntriesChanged with all current entries.
|
|
19673
|
+
*/
|
|
19674
|
+
notifyEntriesChanged() {
|
|
19675
|
+
if (!this.config.onEntriesChanged) return;
|
|
19676
|
+
if (this._notifyTimer) clearTimeout(this._notifyTimer);
|
|
19677
|
+
this._notifyTimer = setTimeout(() => {
|
|
19678
|
+
this._notifyTimer = null;
|
|
19679
|
+
if (!this._destroyed && this.config.onEntriesChanged) {
|
|
19680
|
+
this.config.onEntriesChanged(Array.from(this.entries.values()));
|
|
19681
|
+
}
|
|
19682
|
+
}, 100);
|
|
19683
|
+
}
|
|
19601
19684
|
assertNotDestroyed() {
|
|
19602
19685
|
if (this._destroyed) {
|
|
19603
19686
|
throw new Error("InContextMemoryPluginNextGen is destroyed");
|
|
@@ -19614,16 +19697,18 @@ ${valueStr}
|
|
|
19614
19697
|
args.key,
|
|
19615
19698
|
args.description,
|
|
19616
19699
|
args.value,
|
|
19617
|
-
args.priority
|
|
19700
|
+
args.priority,
|
|
19701
|
+
args.showInUI
|
|
19618
19702
|
);
|
|
19619
19703
|
return {
|
|
19620
19704
|
success: true,
|
|
19621
19705
|
key: args.key,
|
|
19622
|
-
|
|
19706
|
+
showInUI: args.showInUI ?? false,
|
|
19707
|
+
message: `Stored "${args.key}" in live context${args.showInUI ? " (visible in UI)" : ""}`
|
|
19623
19708
|
};
|
|
19624
19709
|
},
|
|
19625
19710
|
permission: { scope: "always", riskLevel: "low" },
|
|
19626
|
-
describeCall: (args) => `set ${args.key}`
|
|
19711
|
+
describeCall: (args) => `set ${args.key}${args.showInUI ? " [UI]" : ""}`
|
|
19627
19712
|
};
|
|
19628
19713
|
}
|
|
19629
19714
|
createContextDeleteTool() {
|
|
@@ -19653,10 +19738,10 @@ function getDefaultBaseDirectory() {
|
|
|
19653
19738
|
if (platform2 === "win32") {
|
|
19654
19739
|
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
19655
19740
|
if (appData) {
|
|
19656
|
-
return
|
|
19741
|
+
return path2.join(appData, "oneringai", "agents");
|
|
19657
19742
|
}
|
|
19658
19743
|
}
|
|
19659
|
-
return
|
|
19744
|
+
return path2.join(os2.homedir(), ".oneringai", "agents");
|
|
19660
19745
|
}
|
|
19661
19746
|
function sanitizeAgentId(agentId) {
|
|
19662
19747
|
return agentId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
|
|
@@ -19671,9 +19756,9 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19671
19756
|
const sanitizedId = sanitizeAgentId(config.agentId);
|
|
19672
19757
|
const baseDir = config.baseDirectory ?? getDefaultBaseDirectory();
|
|
19673
19758
|
const filename = config.filename ?? "custom_instructions.json";
|
|
19674
|
-
this.directory =
|
|
19675
|
-
this.filePath =
|
|
19676
|
-
this.legacyFilePath =
|
|
19759
|
+
this.directory = path2.join(baseDir, sanitizedId);
|
|
19760
|
+
this.filePath = path2.join(this.directory, filename);
|
|
19761
|
+
this.legacyFilePath = path2.join(this.directory, "custom_instructions.md");
|
|
19677
19762
|
}
|
|
19678
19763
|
/**
|
|
19679
19764
|
* Load instruction entries from file.
|
|
@@ -19681,7 +19766,7 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19681
19766
|
*/
|
|
19682
19767
|
async load() {
|
|
19683
19768
|
try {
|
|
19684
|
-
const raw = await
|
|
19769
|
+
const raw = await fs16.promises.readFile(this.filePath, "utf-8");
|
|
19685
19770
|
const data = JSON.parse(raw);
|
|
19686
19771
|
if (data.version === 2 && Array.isArray(data.entries)) {
|
|
19687
19772
|
return data.entries.length > 0 ? data.entries : null;
|
|
@@ -19693,7 +19778,7 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19693
19778
|
}
|
|
19694
19779
|
}
|
|
19695
19780
|
try {
|
|
19696
|
-
const content = await
|
|
19781
|
+
const content = await fs16.promises.readFile(this.legacyFilePath, "utf-8");
|
|
19697
19782
|
const trimmed = content.trim();
|
|
19698
19783
|
if (!trimmed) return null;
|
|
19699
19784
|
const now = Date.now();
|
|
@@ -19723,11 +19808,11 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19723
19808
|
};
|
|
19724
19809
|
const tempPath = `${this.filePath}.tmp`;
|
|
19725
19810
|
try {
|
|
19726
|
-
await
|
|
19727
|
-
await
|
|
19811
|
+
await fs16.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
|
|
19812
|
+
await fs16.promises.rename(tempPath, this.filePath);
|
|
19728
19813
|
} catch (error) {
|
|
19729
19814
|
try {
|
|
19730
|
-
await
|
|
19815
|
+
await fs16.promises.unlink(tempPath);
|
|
19731
19816
|
} catch {
|
|
19732
19817
|
}
|
|
19733
19818
|
throw error;
|
|
@@ -19739,7 +19824,7 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19739
19824
|
*/
|
|
19740
19825
|
async delete() {
|
|
19741
19826
|
try {
|
|
19742
|
-
await
|
|
19827
|
+
await fs16.promises.unlink(this.filePath);
|
|
19743
19828
|
} catch (error) {
|
|
19744
19829
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
19745
19830
|
throw error;
|
|
@@ -19752,11 +19837,11 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19752
19837
|
*/
|
|
19753
19838
|
async exists() {
|
|
19754
19839
|
try {
|
|
19755
|
-
await
|
|
19840
|
+
await fs16.promises.access(this.filePath);
|
|
19756
19841
|
return true;
|
|
19757
19842
|
} catch {
|
|
19758
19843
|
try {
|
|
19759
|
-
await
|
|
19844
|
+
await fs16.promises.access(this.legacyFilePath);
|
|
19760
19845
|
return true;
|
|
19761
19846
|
} catch {
|
|
19762
19847
|
return false;
|
|
@@ -19780,7 +19865,7 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19780
19865
|
*/
|
|
19781
19866
|
async ensureDirectory() {
|
|
19782
19867
|
try {
|
|
19783
|
-
await
|
|
19868
|
+
await fs16.promises.mkdir(this.directory, { recursive: true });
|
|
19784
19869
|
} catch (error) {
|
|
19785
19870
|
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
19786
19871
|
throw error;
|
|
@@ -19792,7 +19877,7 @@ var FilePersistentInstructionsStorage = class {
|
|
|
19792
19877
|
*/
|
|
19793
19878
|
async removeLegacyFile() {
|
|
19794
19879
|
try {
|
|
19795
|
-
await
|
|
19880
|
+
await fs16.promises.unlink(this.legacyFilePath);
|
|
19796
19881
|
} catch (error) {
|
|
19797
19882
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
19798
19883
|
console.warn(`Failed to remove legacy instructions file: ${this.legacyFilePath}`);
|
|
@@ -20935,6 +21020,10 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
|
|
|
20935
21020
|
_sessionId = null;
|
|
20936
21021
|
/** Agent ID */
|
|
20937
21022
|
_agentId;
|
|
21023
|
+
/** User ID for multi-user scenarios */
|
|
21024
|
+
_userId;
|
|
21025
|
+
/** Allowed connector names (when agent is restricted to a subset) */
|
|
21026
|
+
_allowedConnectors;
|
|
20938
21027
|
/** Storage backend */
|
|
20939
21028
|
_storage;
|
|
20940
21029
|
/** Destroyed flag */
|
|
@@ -20971,15 +21060,20 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
|
|
|
20971
21060
|
};
|
|
20972
21061
|
this._systemPrompt = config.systemPrompt;
|
|
20973
21062
|
this._agentId = this._config.agentId;
|
|
21063
|
+
this._userId = config.userId;
|
|
21064
|
+
this._allowedConnectors = config.connectors;
|
|
20974
21065
|
this._storage = config.storage;
|
|
20975
21066
|
this._compactionStrategy = config.compactionStrategy ?? StrategyRegistry.create(this._config.strategy);
|
|
20976
|
-
this._tools = new ToolManager(
|
|
21067
|
+
this._tools = new ToolManager(
|
|
21068
|
+
config.toolExecutionTimeout ? { toolExecutionTimeout: config.toolExecutionTimeout } : void 0
|
|
21069
|
+
);
|
|
20977
21070
|
if (config.tools) {
|
|
20978
21071
|
for (const tool of config.tools) {
|
|
20979
21072
|
this._tools.register(tool);
|
|
20980
21073
|
}
|
|
20981
21074
|
}
|
|
20982
21075
|
this.initializePlugins(config.plugins);
|
|
21076
|
+
this.syncToolContext();
|
|
20983
21077
|
}
|
|
20984
21078
|
/**
|
|
20985
21079
|
* Initialize plugins based on feature flags.
|
|
@@ -21024,6 +21118,62 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
|
|
|
21024
21118
|
);
|
|
21025
21119
|
}
|
|
21026
21120
|
}
|
|
21121
|
+
/**
|
|
21122
|
+
* Sync identity fields and connector registry to ToolContext.
|
|
21123
|
+
* Merges with existing ToolContext to preserve other fields (memory, signal, taskId).
|
|
21124
|
+
*
|
|
21125
|
+
* Connector registry resolution order:
|
|
21126
|
+
* 1. If `connectors` (allowed names) is set → filtered view of global registry
|
|
21127
|
+
* 2. If access policy + userId → scoped view via Connector.scoped()
|
|
21128
|
+
* 3. Otherwise → full global registry
|
|
21129
|
+
*/
|
|
21130
|
+
syncToolContext() {
|
|
21131
|
+
const existing = this._tools.getToolContext();
|
|
21132
|
+
this._tools.setToolContext({
|
|
21133
|
+
...existing,
|
|
21134
|
+
agentId: this._agentId,
|
|
21135
|
+
userId: this._userId,
|
|
21136
|
+
connectorRegistry: this.buildConnectorRegistry()
|
|
21137
|
+
});
|
|
21138
|
+
}
|
|
21139
|
+
/**
|
|
21140
|
+
* Build the connector registry appropriate for this agent's config.
|
|
21141
|
+
*/
|
|
21142
|
+
buildConnectorRegistry() {
|
|
21143
|
+
if (this._allowedConnectors?.length) {
|
|
21144
|
+
const allowedSet = new Set(this._allowedConnectors);
|
|
21145
|
+
const base = this._userId && exports.Connector.getAccessPolicy() ? exports.Connector.scoped({ userId: this._userId }) : exports.Connector.asRegistry();
|
|
21146
|
+
return {
|
|
21147
|
+
get: (name) => {
|
|
21148
|
+
if (!allowedSet.has(name)) {
|
|
21149
|
+
const available = this._allowedConnectors.filter((n) => base.has(n)).join(", ") || "none";
|
|
21150
|
+
throw new Error(`Connector '${name}' not found. Available: ${available}`);
|
|
21151
|
+
}
|
|
21152
|
+
return base.get(name);
|
|
21153
|
+
},
|
|
21154
|
+
has: (name) => allowedSet.has(name) && base.has(name),
|
|
21155
|
+
list: () => base.list().filter((n) => allowedSet.has(n)),
|
|
21156
|
+
listAll: () => base.listAll().filter((c) => allowedSet.has(c.name)),
|
|
21157
|
+
size: () => base.listAll().filter((c) => allowedSet.has(c.name)).length,
|
|
21158
|
+
getDescriptionsForTools: () => {
|
|
21159
|
+
const connectors = base.listAll().filter((c) => allowedSet.has(c.name));
|
|
21160
|
+
if (connectors.length === 0) return "No connectors registered yet.";
|
|
21161
|
+
return connectors.map((c) => ` - "${c.name}": ${c.displayName} - ${c.config.description || "No description"}`).join("\n");
|
|
21162
|
+
},
|
|
21163
|
+
getInfo: () => {
|
|
21164
|
+
const info = {};
|
|
21165
|
+
for (const c of base.listAll().filter((c2) => allowedSet.has(c2.name))) {
|
|
21166
|
+
info[c.name] = { displayName: c.displayName, description: c.config.description || "", baseURL: c.baseURL };
|
|
21167
|
+
}
|
|
21168
|
+
return info;
|
|
21169
|
+
}
|
|
21170
|
+
};
|
|
21171
|
+
}
|
|
21172
|
+
if (this._userId && exports.Connector.getAccessPolicy()) {
|
|
21173
|
+
return exports.Connector.scoped({ userId: this._userId });
|
|
21174
|
+
}
|
|
21175
|
+
return exports.Connector.asRegistry();
|
|
21176
|
+
}
|
|
21027
21177
|
// ============================================================================
|
|
21028
21178
|
// Public Properties
|
|
21029
21179
|
// ============================================================================
|
|
@@ -21039,6 +21189,24 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
|
|
|
21039
21189
|
get agentId() {
|
|
21040
21190
|
return this._agentId;
|
|
21041
21191
|
}
|
|
21192
|
+
/** Get the current user ID */
|
|
21193
|
+
get userId() {
|
|
21194
|
+
return this._userId;
|
|
21195
|
+
}
|
|
21196
|
+
/** Set user ID. Automatically updates ToolContext for all tool executions. */
|
|
21197
|
+
set userId(value) {
|
|
21198
|
+
this._userId = value;
|
|
21199
|
+
this.syncToolContext();
|
|
21200
|
+
}
|
|
21201
|
+
/** Get the allowed connector names (undefined = all visible connectors) */
|
|
21202
|
+
get connectors() {
|
|
21203
|
+
return this._allowedConnectors;
|
|
21204
|
+
}
|
|
21205
|
+
/** Set allowed connector names. Updates ToolContext.connectorRegistry. */
|
|
21206
|
+
set connectors(value) {
|
|
21207
|
+
this._allowedConnectors = value;
|
|
21208
|
+
this.syncToolContext();
|
|
21209
|
+
}
|
|
21042
21210
|
/** Get/set system prompt */
|
|
21043
21211
|
get systemPrompt() {
|
|
21044
21212
|
return this._systemPrompt;
|
|
@@ -21952,6 +22120,7 @@ ${content}`);
|
|
|
21952
22120
|
metadata: {
|
|
21953
22121
|
savedAt: Date.now(),
|
|
21954
22122
|
agentId: this._agentId,
|
|
22123
|
+
userId: this._userId,
|
|
21955
22124
|
model: this._config.model
|
|
21956
22125
|
}
|
|
21957
22126
|
};
|
|
@@ -22709,7 +22878,7 @@ var OpenAITextProvider = class extends BaseTextProvider {
|
|
|
22709
22878
|
streamConverter;
|
|
22710
22879
|
constructor(config) {
|
|
22711
22880
|
super(config);
|
|
22712
|
-
this.client = new
|
|
22881
|
+
this.client = new OpenAI3__default.default({
|
|
22713
22882
|
apiKey: this.getApiKey(),
|
|
22714
22883
|
baseURL: this.getBaseURL(),
|
|
22715
22884
|
organization: config.organization,
|
|
@@ -24439,7 +24608,9 @@ var GoogleTextProvider = class extends BaseTextProvider {
|
|
|
24439
24608
|
constructor(config) {
|
|
24440
24609
|
super(config);
|
|
24441
24610
|
this.client = new genai.GoogleGenAI({
|
|
24442
|
-
apiKey: this.getApiKey()
|
|
24611
|
+
apiKey: this.getApiKey(),
|
|
24612
|
+
// Pass custom baseURL for proxy support (e.g. when routing through EW proxy)
|
|
24613
|
+
...config.baseURL ? { httpOptions: { baseUrl: config.baseURL } } : {}
|
|
24443
24614
|
});
|
|
24444
24615
|
this.converter = new GoogleConverter();
|
|
24445
24616
|
this.streamConverter = new GoogleStreamConverter();
|
|
@@ -24736,6 +24907,30 @@ var GenericOpenAIProvider = class extends OpenAITextProvider {
|
|
|
24736
24907
|
};
|
|
24737
24908
|
|
|
24738
24909
|
// src/core/createProvider.ts
|
|
24910
|
+
var VENDOR_DEFAULT_URLS = (() => {
|
|
24911
|
+
const map = /* @__PURE__ */ new Map();
|
|
24912
|
+
try {
|
|
24913
|
+
map.set(Vendor.OpenAI, new OpenAI3__default.default({ apiKey: "_" }).baseURL);
|
|
24914
|
+
} catch {
|
|
24915
|
+
}
|
|
24916
|
+
try {
|
|
24917
|
+
map.set(Vendor.Anthropic, new Anthropic__default.default({ apiKey: "_" }).baseURL);
|
|
24918
|
+
} catch {
|
|
24919
|
+
}
|
|
24920
|
+
map.set(Vendor.Google, "https://generativelanguage.googleapis.com");
|
|
24921
|
+
map.set(Vendor.GoogleVertex, "https://us-central1-aiplatform.googleapis.com");
|
|
24922
|
+
map.set(Vendor.Groq, "https://api.groq.com/openai/v1");
|
|
24923
|
+
map.set(Vendor.Together, "https://api.together.xyz/v1");
|
|
24924
|
+
map.set(Vendor.Perplexity, "https://api.perplexity.ai");
|
|
24925
|
+
map.set(Vendor.Grok, "https://api.x.ai/v1");
|
|
24926
|
+
map.set(Vendor.DeepSeek, "https://api.deepseek.com/v1");
|
|
24927
|
+
map.set(Vendor.Mistral, "https://api.mistral.ai/v1");
|
|
24928
|
+
map.set(Vendor.Ollama, "http://localhost:11434/v1");
|
|
24929
|
+
return map;
|
|
24930
|
+
})();
|
|
24931
|
+
function getVendorDefaultBaseURL(vendor) {
|
|
24932
|
+
return VENDOR_DEFAULT_URLS.get(vendor);
|
|
24933
|
+
}
|
|
24739
24934
|
function createProvider(connector) {
|
|
24740
24935
|
const injectedProvider = connector.getOptions().provider;
|
|
24741
24936
|
if (injectedProvider && typeof injectedProvider.generate === "function") {
|
|
@@ -24770,39 +24965,15 @@ function createProvider(connector) {
|
|
|
24770
24965
|
});
|
|
24771
24966
|
// OpenAI-compatible providers (use connector.name for unique identification)
|
|
24772
24967
|
case Vendor.Groq:
|
|
24773
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24774
|
-
...config,
|
|
24775
|
-
baseURL: config.baseURL || "https://api.groq.com/openai/v1"
|
|
24776
|
-
});
|
|
24777
24968
|
case Vendor.Together:
|
|
24778
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24779
|
-
...config,
|
|
24780
|
-
baseURL: config.baseURL || "https://api.together.xyz/v1"
|
|
24781
|
-
});
|
|
24782
24969
|
case Vendor.Perplexity:
|
|
24783
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24784
|
-
...config,
|
|
24785
|
-
baseURL: config.baseURL || "https://api.perplexity.ai"
|
|
24786
|
-
});
|
|
24787
24970
|
case Vendor.Grok:
|
|
24788
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24789
|
-
...config,
|
|
24790
|
-
baseURL: config.baseURL || "https://api.x.ai/v1"
|
|
24791
|
-
});
|
|
24792
24971
|
case Vendor.DeepSeek:
|
|
24793
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24794
|
-
...config,
|
|
24795
|
-
baseURL: config.baseURL || "https://api.deepseek.com/v1"
|
|
24796
|
-
});
|
|
24797
24972
|
case Vendor.Mistral:
|
|
24798
|
-
return new GenericOpenAIProvider(connector.name, {
|
|
24799
|
-
...config,
|
|
24800
|
-
baseURL: config.baseURL || "https://api.mistral.ai/v1"
|
|
24801
|
-
});
|
|
24802
24973
|
case Vendor.Ollama:
|
|
24803
24974
|
return new GenericOpenAIProvider(connector.name, {
|
|
24804
24975
|
...config,
|
|
24805
|
-
baseURL: config.baseURL ||
|
|
24976
|
+
baseURL: config.baseURL || getVendorDefaultBaseURL(vendor)
|
|
24806
24977
|
});
|
|
24807
24978
|
case Vendor.Custom:
|
|
24808
24979
|
if (!config.baseURL) {
|
|
@@ -24912,9 +25083,14 @@ var BaseAgent = class extends eventemitter3.EventEmitter {
|
|
|
24912
25083
|
const contextConfig = {
|
|
24913
25084
|
model: config.model,
|
|
24914
25085
|
agentId: config.name,
|
|
25086
|
+
userId: config.userId,
|
|
25087
|
+
connectors: config.connectors,
|
|
24915
25088
|
// Include storage and sessionId if session config is provided
|
|
24916
25089
|
storage: config.session?.storage,
|
|
25090
|
+
// Thread tool execution timeout to ToolManager
|
|
25091
|
+
toolExecutionTimeout: config.toolExecutionTimeout,
|
|
24917
25092
|
// Subclasses can add systemPrompt via their config
|
|
25093
|
+
// Note: context-level toolExecutionTimeout overrides agent-level if both set
|
|
24918
25094
|
...typeof config.context === "object" && config.context !== null ? config.context : {}
|
|
24919
25095
|
};
|
|
24920
25096
|
return AgentContextNextGen.create(contextConfig);
|
|
@@ -25065,6 +25241,30 @@ var BaseAgent = class extends eventemitter3.EventEmitter {
|
|
|
25065
25241
|
get context() {
|
|
25066
25242
|
return this._agentContext;
|
|
25067
25243
|
}
|
|
25244
|
+
/**
|
|
25245
|
+
* Get the current user ID. Delegates to AgentContextNextGen.
|
|
25246
|
+
*/
|
|
25247
|
+
get userId() {
|
|
25248
|
+
return this._agentContext.userId;
|
|
25249
|
+
}
|
|
25250
|
+
/**
|
|
25251
|
+
* Set user ID at runtime. Automatically updates ToolContext for all tool executions.
|
|
25252
|
+
*/
|
|
25253
|
+
set userId(value) {
|
|
25254
|
+
this._agentContext.userId = value;
|
|
25255
|
+
}
|
|
25256
|
+
/**
|
|
25257
|
+
* Get the allowed connector names (undefined = all visible connectors).
|
|
25258
|
+
*/
|
|
25259
|
+
get connectors() {
|
|
25260
|
+
return this._agentContext.connectors;
|
|
25261
|
+
}
|
|
25262
|
+
/**
|
|
25263
|
+
* Restrict this agent to a subset of connectors. Updates ToolContext.connectorRegistry.
|
|
25264
|
+
*/
|
|
25265
|
+
set connectors(value) {
|
|
25266
|
+
this._agentContext.connectors = value;
|
|
25267
|
+
}
|
|
25068
25268
|
/**
|
|
25069
25269
|
* Permission management. Returns ToolPermissionManager for approval control.
|
|
25070
25270
|
*/
|
|
@@ -25116,9 +25316,10 @@ var BaseAgent = class extends eventemitter3.EventEmitter {
|
|
|
25116
25316
|
* always sees up-to-date tool descriptions.
|
|
25117
25317
|
*/
|
|
25118
25318
|
getEnabledToolDefinitions() {
|
|
25319
|
+
const toolContext = this._agentContext.tools.getToolContext();
|
|
25119
25320
|
return this._agentContext.tools.getEnabled().map((tool) => {
|
|
25120
25321
|
if (tool.descriptionFactory) {
|
|
25121
|
-
const dynamicDescription = tool.descriptionFactory();
|
|
25322
|
+
const dynamicDescription = tool.descriptionFactory(toolContext);
|
|
25122
25323
|
return {
|
|
25123
25324
|
...tool.definition,
|
|
25124
25325
|
function: {
|
|
@@ -26164,6 +26365,7 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
26164
26365
|
* const agent = Agent.create({
|
|
26165
26366
|
* connector: 'openai', // or Connector instance
|
|
26166
26367
|
* model: 'gpt-4',
|
|
26368
|
+
* userId: 'user-123', // flows to all tool executions automatically
|
|
26167
26369
|
* instructions: 'You are a helpful assistant',
|
|
26168
26370
|
* tools: [myTool]
|
|
26169
26371
|
* });
|
|
@@ -27354,18 +27556,18 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27354
27556
|
(class {
|
|
27355
27557
|
static DEFAULT_PATHS = [
|
|
27356
27558
|
"./oneringai.config.json",
|
|
27357
|
-
|
|
27559
|
+
path2.join(os2.homedir(), ".oneringai", "config.json")
|
|
27358
27560
|
];
|
|
27359
27561
|
/**
|
|
27360
27562
|
* Load configuration from file
|
|
27361
27563
|
*/
|
|
27362
27564
|
static async load(path6) {
|
|
27363
|
-
const configPath = path6 ?
|
|
27565
|
+
const configPath = path6 ? path2.resolve(path6) : await this.findConfig();
|
|
27364
27566
|
if (!configPath) {
|
|
27365
27567
|
throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
|
|
27366
27568
|
}
|
|
27367
27569
|
try {
|
|
27368
|
-
const content = await
|
|
27570
|
+
const content = await fs16.promises.readFile(configPath, "utf-8");
|
|
27369
27571
|
let config = JSON.parse(content);
|
|
27370
27572
|
config = this.interpolateEnvVars(config);
|
|
27371
27573
|
this.validate(config);
|
|
@@ -27381,13 +27583,13 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27381
27583
|
* Load configuration synchronously
|
|
27382
27584
|
*/
|
|
27383
27585
|
static loadSync(path6) {
|
|
27384
|
-
const configPath = path6 ?
|
|
27586
|
+
const configPath = path6 ? path2.resolve(path6) : this.findConfigSync();
|
|
27385
27587
|
if (!configPath) {
|
|
27386
27588
|
throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
|
|
27387
27589
|
}
|
|
27388
27590
|
try {
|
|
27389
|
-
const
|
|
27390
|
-
const content =
|
|
27591
|
+
const fs17 = __require("fs");
|
|
27592
|
+
const content = fs17.readFileSync(configPath, "utf-8");
|
|
27391
27593
|
let config = JSON.parse(content);
|
|
27392
27594
|
config = this.interpolateEnvVars(config);
|
|
27393
27595
|
this.validate(config);
|
|
@@ -27405,8 +27607,8 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27405
27607
|
static async findConfig() {
|
|
27406
27608
|
for (const path6 of this.DEFAULT_PATHS) {
|
|
27407
27609
|
try {
|
|
27408
|
-
await
|
|
27409
|
-
return
|
|
27610
|
+
await fs16.promises.access(path2.resolve(path6));
|
|
27611
|
+
return path2.resolve(path6);
|
|
27410
27612
|
} catch {
|
|
27411
27613
|
}
|
|
27412
27614
|
}
|
|
@@ -27416,11 +27618,11 @@ var Agent = class _Agent extends BaseAgent {
|
|
|
27416
27618
|
* Find configuration file synchronously
|
|
27417
27619
|
*/
|
|
27418
27620
|
static findConfigSync() {
|
|
27419
|
-
const
|
|
27621
|
+
const fs17 = __require("fs");
|
|
27420
27622
|
for (const path6 of this.DEFAULT_PATHS) {
|
|
27421
27623
|
try {
|
|
27422
|
-
|
|
27423
|
-
return
|
|
27624
|
+
fs17.accessSync(path2.resolve(path6));
|
|
27625
|
+
return path2.resolve(path6);
|
|
27424
27626
|
} catch {
|
|
27425
27627
|
}
|
|
27426
27628
|
}
|
|
@@ -32977,8 +33179,8 @@ var MCPRegistry = class {
|
|
|
32977
33179
|
*/
|
|
32978
33180
|
static async loadFromConfigFile(path6) {
|
|
32979
33181
|
try {
|
|
32980
|
-
const configPath =
|
|
32981
|
-
const content = await
|
|
33182
|
+
const configPath = path2.resolve(path6);
|
|
33183
|
+
const content = await fs16.promises.readFile(configPath, "utf-8");
|
|
32982
33184
|
const config = JSON.parse(content);
|
|
32983
33185
|
if (!config.mcp) {
|
|
32984
33186
|
throw new MCPError("Configuration file does not contain MCP section");
|
|
@@ -33366,7 +33568,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
|
|
|
33366
33568
|
client;
|
|
33367
33569
|
constructor(config) {
|
|
33368
33570
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
33369
|
-
this.client = new
|
|
33571
|
+
this.client = new OpenAI3__default.default({
|
|
33370
33572
|
apiKey: config.auth.apiKey,
|
|
33371
33573
|
baseURL: config.baseURL,
|
|
33372
33574
|
organization: config.organization,
|
|
@@ -33449,7 +33651,7 @@ var OpenAITTSProvider = class extends BaseMediaProvider {
|
|
|
33449
33651
|
* Handle OpenAI API errors
|
|
33450
33652
|
*/
|
|
33451
33653
|
handleError(error) {
|
|
33452
|
-
if (error instanceof
|
|
33654
|
+
if (error instanceof OpenAI3__default.default.APIError) {
|
|
33453
33655
|
const status = error.status;
|
|
33454
33656
|
const message = error.message || "Unknown OpenAI API error";
|
|
33455
33657
|
if (status === 401) {
|
|
@@ -33481,7 +33683,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
|
|
|
33481
33683
|
client;
|
|
33482
33684
|
constructor(config) {
|
|
33483
33685
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
33484
|
-
this.client = new
|
|
33686
|
+
this.client = new OpenAI3__default.default({
|
|
33485
33687
|
apiKey: config.auth.apiKey,
|
|
33486
33688
|
baseURL: config.baseURL,
|
|
33487
33689
|
organization: config.organization,
|
|
@@ -33583,7 +33785,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
|
|
|
33583
33785
|
if (Buffer.isBuffer(audio)) {
|
|
33584
33786
|
return new File([new Uint8Array(audio)], "audio.wav", { type: "audio/wav" });
|
|
33585
33787
|
} else if (typeof audio === "string") {
|
|
33586
|
-
return
|
|
33788
|
+
return fs16__namespace.createReadStream(audio);
|
|
33587
33789
|
} else {
|
|
33588
33790
|
throw new Error("Invalid audio input: must be Buffer or file path");
|
|
33589
33791
|
}
|
|
@@ -33642,7 +33844,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
|
|
|
33642
33844
|
* Handle OpenAI API errors
|
|
33643
33845
|
*/
|
|
33644
33846
|
handleError(error) {
|
|
33645
|
-
if (error instanceof
|
|
33847
|
+
if (error instanceof OpenAI3__default.default.APIError) {
|
|
33646
33848
|
const status = error.status;
|
|
33647
33849
|
const message = error.message || "Unknown OpenAI API error";
|
|
33648
33850
|
if (status === 401) {
|
|
@@ -34136,7 +34338,7 @@ var TextToSpeech = class _TextToSpeech {
|
|
|
34136
34338
|
*/
|
|
34137
34339
|
async toFile(text, filePath, options) {
|
|
34138
34340
|
const response = await this.synthesize(text, options);
|
|
34139
|
-
await
|
|
34341
|
+
await fs15__namespace.writeFile(filePath, response.audio);
|
|
34140
34342
|
}
|
|
34141
34343
|
// ======================== Introspection Methods ========================
|
|
34142
34344
|
/**
|
|
@@ -34484,7 +34686,7 @@ var SpeechToText = class _SpeechToText {
|
|
|
34484
34686
|
* @param options - Optional transcription parameters
|
|
34485
34687
|
*/
|
|
34486
34688
|
async transcribeFile(filePath, options) {
|
|
34487
|
-
const audio = await
|
|
34689
|
+
const audio = await fs15__namespace.readFile(filePath);
|
|
34488
34690
|
return this.transcribe(audio, options);
|
|
34489
34691
|
}
|
|
34490
34692
|
/**
|
|
@@ -34648,7 +34850,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
|
|
|
34648
34850
|
client;
|
|
34649
34851
|
constructor(config) {
|
|
34650
34852
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
34651
|
-
this.client = new
|
|
34853
|
+
this.client = new OpenAI3__default.default({
|
|
34652
34854
|
apiKey: config.auth.apiKey,
|
|
34653
34855
|
baseURL: config.baseURL,
|
|
34654
34856
|
organization: config.organization,
|
|
@@ -34810,7 +35012,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
|
|
|
34810
35012
|
if (Buffer.isBuffer(image)) {
|
|
34811
35013
|
return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
|
|
34812
35014
|
}
|
|
34813
|
-
return
|
|
35015
|
+
return fs16__namespace.createReadStream(image);
|
|
34814
35016
|
}
|
|
34815
35017
|
/**
|
|
34816
35018
|
* Handle OpenAI API errors
|
|
@@ -34957,8 +35159,8 @@ var GoogleImageProvider = class extends BaseMediaProvider {
|
|
|
34957
35159
|
if (Buffer.isBuffer(image)) {
|
|
34958
35160
|
imageBytes = image.toString("base64");
|
|
34959
35161
|
} else {
|
|
34960
|
-
const
|
|
34961
|
-
const buffer =
|
|
35162
|
+
const fs17 = await import('fs');
|
|
35163
|
+
const buffer = fs17.readFileSync(image);
|
|
34962
35164
|
imageBytes = buffer.toString("base64");
|
|
34963
35165
|
}
|
|
34964
35166
|
return {
|
|
@@ -35008,7 +35210,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
|
|
|
35008
35210
|
client;
|
|
35009
35211
|
constructor(config) {
|
|
35010
35212
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
35011
|
-
this.client = new
|
|
35213
|
+
this.client = new OpenAI3__default.default({
|
|
35012
35214
|
apiKey: config.auth.apiKey,
|
|
35013
35215
|
baseURL: config.baseURL || GROK_API_BASE_URL,
|
|
35014
35216
|
timeout: config.timeout,
|
|
@@ -35119,7 +35321,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
|
|
|
35119
35321
|
if (Buffer.isBuffer(image)) {
|
|
35120
35322
|
return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
|
|
35121
35323
|
}
|
|
35122
|
-
return
|
|
35324
|
+
return fs16__namespace.createReadStream(image);
|
|
35123
35325
|
}
|
|
35124
35326
|
/**
|
|
35125
35327
|
* Handle API errors
|
|
@@ -36321,7 +36523,7 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
|
|
|
36321
36523
|
client;
|
|
36322
36524
|
constructor(config) {
|
|
36323
36525
|
super({ apiKey: config.auth.apiKey, ...config });
|
|
36324
|
-
this.client = new
|
|
36526
|
+
this.client = new OpenAI3__default.default({
|
|
36325
36527
|
apiKey: config.auth.apiKey,
|
|
36326
36528
|
baseURL: config.baseURL,
|
|
36327
36529
|
organization: config.organization,
|
|
@@ -36569,8 +36771,8 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
|
|
|
36569
36771
|
return new File([new Uint8Array(image)], "input.png", { type: "image/png" });
|
|
36570
36772
|
}
|
|
36571
36773
|
if (!image.startsWith("http")) {
|
|
36572
|
-
const
|
|
36573
|
-
const data =
|
|
36774
|
+
const fs17 = await import('fs');
|
|
36775
|
+
const data = fs17.readFileSync(image);
|
|
36574
36776
|
return new File([new Uint8Array(data)], "input.png", { type: "image/png" });
|
|
36575
36777
|
}
|
|
36576
36778
|
const response = await fetch(image);
|
|
@@ -36748,7 +36950,7 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
|
|
|
36748
36950
|
if (video.videoBytes) {
|
|
36749
36951
|
buffer = Buffer.from(video.videoBytes, "base64");
|
|
36750
36952
|
} else if (video.uri) {
|
|
36751
|
-
const
|
|
36953
|
+
const fs17 = await import('fs/promises');
|
|
36752
36954
|
const os3 = await import('os');
|
|
36753
36955
|
const path6 = await import('path');
|
|
36754
36956
|
const tempDir = os3.tmpdir();
|
|
@@ -36759,11 +36961,11 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
|
|
|
36759
36961
|
// Pass as GeneratedVideo
|
|
36760
36962
|
downloadPath: tempFile
|
|
36761
36963
|
});
|
|
36762
|
-
buffer = await
|
|
36763
|
-
await
|
|
36964
|
+
buffer = await fs17.readFile(tempFile);
|
|
36965
|
+
await fs17.unlink(tempFile).catch(() => {
|
|
36764
36966
|
});
|
|
36765
36967
|
} catch (downloadError) {
|
|
36766
|
-
await
|
|
36968
|
+
await fs17.unlink(tempFile).catch(() => {
|
|
36767
36969
|
});
|
|
36768
36970
|
throw new ProviderError(
|
|
36769
36971
|
"google",
|
|
@@ -36885,8 +37087,8 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
|
|
|
36885
37087
|
if (image.startsWith("http://") || image.startsWith("https://")) {
|
|
36886
37088
|
return { imageUri: image };
|
|
36887
37089
|
}
|
|
36888
|
-
const
|
|
36889
|
-
const data = await
|
|
37090
|
+
const fs17 = await import('fs/promises');
|
|
37091
|
+
const data = await fs17.readFile(image);
|
|
36890
37092
|
return {
|
|
36891
37093
|
imageBytes: data.toString("base64")
|
|
36892
37094
|
};
|
|
@@ -37193,8 +37395,8 @@ var GrokImagineProvider = class extends BaseMediaProvider {
|
|
|
37193
37395
|
if (image.startsWith("http") || image.startsWith("data:")) {
|
|
37194
37396
|
return image;
|
|
37195
37397
|
}
|
|
37196
|
-
const
|
|
37197
|
-
const data =
|
|
37398
|
+
const fs17 = await import('fs');
|
|
37399
|
+
const data = fs17.readFileSync(image);
|
|
37198
37400
|
const base64 = data.toString("base64");
|
|
37199
37401
|
const ext = image.split(".").pop()?.toLowerCase() || "png";
|
|
37200
37402
|
const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext}`;
|
|
@@ -40399,10 +40601,10 @@ function getDefaultBaseDirectory2() {
|
|
|
40399
40601
|
if (platform2 === "win32") {
|
|
40400
40602
|
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
40401
40603
|
if (appData) {
|
|
40402
|
-
return
|
|
40604
|
+
return path2.join(appData, "oneringai", "agents");
|
|
40403
40605
|
}
|
|
40404
40606
|
}
|
|
40405
|
-
return
|
|
40607
|
+
return path2.join(os2.homedir(), ".oneringai", "agents");
|
|
40406
40608
|
}
|
|
40407
40609
|
function sanitizeId(id) {
|
|
40408
40610
|
return id.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
|
|
@@ -40419,8 +40621,8 @@ var FileContextStorage = class {
|
|
|
40419
40621
|
const sanitizedAgentId = sanitizeId(config.agentId);
|
|
40420
40622
|
const baseDir = config.baseDirectory ?? getDefaultBaseDirectory2();
|
|
40421
40623
|
this.prettyPrint = config.prettyPrint ?? true;
|
|
40422
|
-
this.sessionsDirectory =
|
|
40423
|
-
this.indexPath =
|
|
40624
|
+
this.sessionsDirectory = path2.join(baseDir, sanitizedAgentId, "sessions");
|
|
40625
|
+
this.indexPath = path2.join(this.sessionsDirectory, "_index.json");
|
|
40424
40626
|
}
|
|
40425
40627
|
/**
|
|
40426
40628
|
* Save context state to a session file
|
|
@@ -40446,11 +40648,11 @@ var FileContextStorage = class {
|
|
|
40446
40648
|
const data = this.prettyPrint ? JSON.stringify(storedSession, null, 2) : JSON.stringify(storedSession);
|
|
40447
40649
|
const tempPath = `${filePath}.tmp`;
|
|
40448
40650
|
try {
|
|
40449
|
-
await
|
|
40450
|
-
await
|
|
40651
|
+
await fs16.promises.writeFile(tempPath, data, "utf-8");
|
|
40652
|
+
await fs16.promises.rename(tempPath, filePath);
|
|
40451
40653
|
} catch (error) {
|
|
40452
40654
|
try {
|
|
40453
|
-
await
|
|
40655
|
+
await fs16.promises.unlink(tempPath);
|
|
40454
40656
|
} catch {
|
|
40455
40657
|
}
|
|
40456
40658
|
throw error;
|
|
@@ -40471,7 +40673,7 @@ var FileContextStorage = class {
|
|
|
40471
40673
|
const sanitizedSessionId = sanitizeId(sessionId);
|
|
40472
40674
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40473
40675
|
try {
|
|
40474
|
-
await
|
|
40676
|
+
await fs16.promises.unlink(filePath);
|
|
40475
40677
|
} catch (error) {
|
|
40476
40678
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
40477
40679
|
throw error;
|
|
@@ -40486,7 +40688,7 @@ var FileContextStorage = class {
|
|
|
40486
40688
|
const sanitizedSessionId = sanitizeId(sessionId);
|
|
40487
40689
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40488
40690
|
try {
|
|
40489
|
-
await
|
|
40691
|
+
await fs16.promises.access(filePath);
|
|
40490
40692
|
return true;
|
|
40491
40693
|
} catch {
|
|
40492
40694
|
return false;
|
|
@@ -40551,7 +40753,7 @@ var FileContextStorage = class {
|
|
|
40551
40753
|
const sanitizedSessionId = sanitizeId(sessionId);
|
|
40552
40754
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40553
40755
|
const data = this.prettyPrint ? JSON.stringify(stored, null, 2) : JSON.stringify(stored);
|
|
40554
|
-
await
|
|
40756
|
+
await fs16.promises.writeFile(filePath, data, "utf-8");
|
|
40555
40757
|
await this.updateIndex(stored);
|
|
40556
40758
|
}
|
|
40557
40759
|
/**
|
|
@@ -40572,13 +40774,13 @@ var FileContextStorage = class {
|
|
|
40572
40774
|
*/
|
|
40573
40775
|
async rebuildIndex() {
|
|
40574
40776
|
await this.ensureDirectory();
|
|
40575
|
-
const files = await
|
|
40777
|
+
const files = await fs16.promises.readdir(this.sessionsDirectory);
|
|
40576
40778
|
const sessionFiles = files.filter((f) => f.endsWith(".json") && !f.startsWith("_"));
|
|
40577
40779
|
const entries = [];
|
|
40578
40780
|
for (const file of sessionFiles) {
|
|
40579
40781
|
try {
|
|
40580
|
-
const filePath =
|
|
40581
|
-
const data = await
|
|
40782
|
+
const filePath = path2.join(this.sessionsDirectory, file);
|
|
40783
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40582
40784
|
const stored = JSON.parse(data);
|
|
40583
40785
|
entries.push(this.storedToIndexEntry(stored));
|
|
40584
40786
|
} catch {
|
|
@@ -40596,11 +40798,11 @@ var FileContextStorage = class {
|
|
|
40596
40798
|
// Private Helpers
|
|
40597
40799
|
// ==========================================================================
|
|
40598
40800
|
getFilePath(sanitizedSessionId) {
|
|
40599
|
-
return
|
|
40801
|
+
return path2.join(this.sessionsDirectory, `${sanitizedSessionId}.json`);
|
|
40600
40802
|
}
|
|
40601
40803
|
async ensureDirectory() {
|
|
40602
40804
|
try {
|
|
40603
|
-
await
|
|
40805
|
+
await fs16.promises.mkdir(this.sessionsDirectory, { recursive: true });
|
|
40604
40806
|
} catch (error) {
|
|
40605
40807
|
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
40606
40808
|
throw error;
|
|
@@ -40610,7 +40812,7 @@ var FileContextStorage = class {
|
|
|
40610
40812
|
async loadRaw(sanitizedSessionId) {
|
|
40611
40813
|
const filePath = this.getFilePath(sanitizedSessionId);
|
|
40612
40814
|
try {
|
|
40613
|
-
const data = await
|
|
40815
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40614
40816
|
return JSON.parse(data);
|
|
40615
40817
|
} catch (error) {
|
|
40616
40818
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -40628,7 +40830,7 @@ var FileContextStorage = class {
|
|
|
40628
40830
|
return this.index;
|
|
40629
40831
|
}
|
|
40630
40832
|
try {
|
|
40631
|
-
const data = await
|
|
40833
|
+
const data = await fs16.promises.readFile(this.indexPath, "utf-8");
|
|
40632
40834
|
this.index = JSON.parse(data);
|
|
40633
40835
|
return this.index;
|
|
40634
40836
|
} catch (error) {
|
|
@@ -40649,7 +40851,7 @@ var FileContextStorage = class {
|
|
|
40649
40851
|
await this.ensureDirectory();
|
|
40650
40852
|
this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
40651
40853
|
const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
|
|
40652
|
-
await
|
|
40854
|
+
await fs16.promises.writeFile(this.indexPath, data, "utf-8");
|
|
40653
40855
|
}
|
|
40654
40856
|
async updateIndex(stored) {
|
|
40655
40857
|
const index = await this.loadIndex();
|
|
@@ -40687,10 +40889,10 @@ function getDefaultBaseDirectory3() {
|
|
|
40687
40889
|
if (platform2 === "win32") {
|
|
40688
40890
|
const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
|
|
40689
40891
|
if (appData) {
|
|
40690
|
-
return
|
|
40892
|
+
return path2.join(appData, "oneringai", "agents");
|
|
40691
40893
|
}
|
|
40692
40894
|
}
|
|
40693
|
-
return
|
|
40895
|
+
return path2.join(os2.homedir(), ".oneringai", "agents");
|
|
40694
40896
|
}
|
|
40695
40897
|
function sanitizeAgentId2(agentId) {
|
|
40696
40898
|
return agentId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
|
|
@@ -40703,15 +40905,15 @@ var FileAgentDefinitionStorage = class {
|
|
|
40703
40905
|
constructor(config = {}) {
|
|
40704
40906
|
this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory3();
|
|
40705
40907
|
this.prettyPrint = config.prettyPrint ?? true;
|
|
40706
|
-
this.indexPath =
|
|
40908
|
+
this.indexPath = path2.join(this.baseDirectory, "_agents_index.json");
|
|
40707
40909
|
}
|
|
40708
40910
|
/**
|
|
40709
40911
|
* Save an agent definition
|
|
40710
40912
|
*/
|
|
40711
40913
|
async save(definition) {
|
|
40712
40914
|
const sanitizedId = sanitizeAgentId2(definition.agentId);
|
|
40713
|
-
const agentDir =
|
|
40714
|
-
const filePath =
|
|
40915
|
+
const agentDir = path2.join(this.baseDirectory, sanitizedId);
|
|
40916
|
+
const filePath = path2.join(agentDir, "definition.json");
|
|
40715
40917
|
await this.ensureDirectory(agentDir);
|
|
40716
40918
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
40717
40919
|
if (!definition.createdAt) {
|
|
@@ -40723,11 +40925,11 @@ var FileAgentDefinitionStorage = class {
|
|
|
40723
40925
|
const data = this.prettyPrint ? JSON.stringify(definition, null, 2) : JSON.stringify(definition);
|
|
40724
40926
|
const tempPath = `${filePath}.tmp`;
|
|
40725
40927
|
try {
|
|
40726
|
-
await
|
|
40727
|
-
await
|
|
40928
|
+
await fs16.promises.writeFile(tempPath, data, "utf-8");
|
|
40929
|
+
await fs16.promises.rename(tempPath, filePath);
|
|
40728
40930
|
} catch (error) {
|
|
40729
40931
|
try {
|
|
40730
|
-
await
|
|
40932
|
+
await fs16.promises.unlink(tempPath);
|
|
40731
40933
|
} catch {
|
|
40732
40934
|
}
|
|
40733
40935
|
throw error;
|
|
@@ -40746,10 +40948,10 @@ var FileAgentDefinitionStorage = class {
|
|
|
40746
40948
|
*/
|
|
40747
40949
|
async delete(agentId) {
|
|
40748
40950
|
const sanitizedId = sanitizeAgentId2(agentId);
|
|
40749
|
-
const agentDir =
|
|
40750
|
-
const filePath =
|
|
40951
|
+
const agentDir = path2.join(this.baseDirectory, sanitizedId);
|
|
40952
|
+
const filePath = path2.join(agentDir, "definition.json");
|
|
40751
40953
|
try {
|
|
40752
|
-
await
|
|
40954
|
+
await fs16.promises.unlink(filePath);
|
|
40753
40955
|
} catch (error) {
|
|
40754
40956
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
|
|
40755
40957
|
throw error;
|
|
@@ -40762,9 +40964,9 @@ var FileAgentDefinitionStorage = class {
|
|
|
40762
40964
|
*/
|
|
40763
40965
|
async exists(agentId) {
|
|
40764
40966
|
const sanitizedId = sanitizeAgentId2(agentId);
|
|
40765
|
-
const filePath =
|
|
40967
|
+
const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
|
|
40766
40968
|
try {
|
|
40767
|
-
await
|
|
40969
|
+
await fs16.promises.access(filePath);
|
|
40768
40970
|
return true;
|
|
40769
40971
|
} catch {
|
|
40770
40972
|
return false;
|
|
@@ -40826,13 +41028,13 @@ var FileAgentDefinitionStorage = class {
|
|
|
40826
41028
|
*/
|
|
40827
41029
|
async rebuildIndex() {
|
|
40828
41030
|
await this.ensureDirectory(this.baseDirectory);
|
|
40829
|
-
const entries = await
|
|
41031
|
+
const entries = await fs16.promises.readdir(this.baseDirectory, { withFileTypes: true });
|
|
40830
41032
|
const agentDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith("_"));
|
|
40831
41033
|
const indexEntries = [];
|
|
40832
41034
|
for (const dir of agentDirs) {
|
|
40833
41035
|
try {
|
|
40834
|
-
const filePath =
|
|
40835
|
-
const data = await
|
|
41036
|
+
const filePath = path2.join(this.baseDirectory, dir.name, "definition.json");
|
|
41037
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40836
41038
|
const definition = JSON.parse(data);
|
|
40837
41039
|
indexEntries.push(this.definitionToIndexEntry(definition));
|
|
40838
41040
|
} catch {
|
|
@@ -40850,7 +41052,7 @@ var FileAgentDefinitionStorage = class {
|
|
|
40850
41052
|
// ==========================================================================
|
|
40851
41053
|
async ensureDirectory(dir) {
|
|
40852
41054
|
try {
|
|
40853
|
-
await
|
|
41055
|
+
await fs16.promises.mkdir(dir, { recursive: true });
|
|
40854
41056
|
} catch (error) {
|
|
40855
41057
|
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
40856
41058
|
throw error;
|
|
@@ -40858,9 +41060,9 @@ var FileAgentDefinitionStorage = class {
|
|
|
40858
41060
|
}
|
|
40859
41061
|
}
|
|
40860
41062
|
async loadRaw(sanitizedId) {
|
|
40861
|
-
const filePath =
|
|
41063
|
+
const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
|
|
40862
41064
|
try {
|
|
40863
|
-
const data = await
|
|
41065
|
+
const data = await fs16.promises.readFile(filePath, "utf-8");
|
|
40864
41066
|
return JSON.parse(data);
|
|
40865
41067
|
} catch (error) {
|
|
40866
41068
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -40878,7 +41080,7 @@ var FileAgentDefinitionStorage = class {
|
|
|
40878
41080
|
return this.index;
|
|
40879
41081
|
}
|
|
40880
41082
|
try {
|
|
40881
|
-
const data = await
|
|
41083
|
+
const data = await fs16.promises.readFile(this.indexPath, "utf-8");
|
|
40882
41084
|
this.index = JSON.parse(data);
|
|
40883
41085
|
return this.index;
|
|
40884
41086
|
} catch (error) {
|
|
@@ -40898,7 +41100,7 @@ var FileAgentDefinitionStorage = class {
|
|
|
40898
41100
|
await this.ensureDirectory(this.baseDirectory);
|
|
40899
41101
|
this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
40900
41102
|
const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
|
|
40901
|
-
await
|
|
41103
|
+
await fs16.promises.writeFile(this.indexPath, data, "utf-8");
|
|
40902
41104
|
}
|
|
40903
41105
|
async updateIndex(definition) {
|
|
40904
41106
|
const index = await this.loadIndex();
|
|
@@ -40931,6 +41133,126 @@ var FileAgentDefinitionStorage = class {
|
|
|
40931
41133
|
function createFileAgentDefinitionStorage(config) {
|
|
40932
41134
|
return new FileAgentDefinitionStorage(config);
|
|
40933
41135
|
}
|
|
41136
|
+
var MIME_TYPES = {
|
|
41137
|
+
png: "image/png",
|
|
41138
|
+
jpeg: "image/jpeg",
|
|
41139
|
+
jpg: "image/jpeg",
|
|
41140
|
+
webp: "image/webp",
|
|
41141
|
+
gif: "image/gif",
|
|
41142
|
+
mp4: "video/mp4",
|
|
41143
|
+
webm: "video/webm",
|
|
41144
|
+
mp3: "audio/mpeg",
|
|
41145
|
+
wav: "audio/wav",
|
|
41146
|
+
opus: "audio/opus",
|
|
41147
|
+
ogg: "audio/ogg",
|
|
41148
|
+
aac: "audio/aac",
|
|
41149
|
+
flac: "audio/flac",
|
|
41150
|
+
pcm: "audio/pcm"
|
|
41151
|
+
};
|
|
41152
|
+
var MEDIA_TYPE_PREFIXES = ["image", "video", "audio"];
|
|
41153
|
+
var FileMediaStorage = class {
|
|
41154
|
+
outputDir;
|
|
41155
|
+
initialized = false;
|
|
41156
|
+
constructor(config) {
|
|
41157
|
+
this.outputDir = config?.outputDir ?? path2__namespace.join(os2__namespace.tmpdir(), "oneringai-media");
|
|
41158
|
+
}
|
|
41159
|
+
async save(data, metadata) {
|
|
41160
|
+
const dir = metadata.userId ? path2__namespace.join(this.outputDir, metadata.userId) : this.outputDir;
|
|
41161
|
+
await fs15__namespace.mkdir(dir, { recursive: true });
|
|
41162
|
+
const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
|
|
41163
|
+
const filePath = path2__namespace.join(dir, filename);
|
|
41164
|
+
await fs15__namespace.writeFile(filePath, data);
|
|
41165
|
+
const format = metadata.format.toLowerCase();
|
|
41166
|
+
const mimeType = MIME_TYPES[format] ?? "application/octet-stream";
|
|
41167
|
+
return {
|
|
41168
|
+
location: filePath,
|
|
41169
|
+
mimeType,
|
|
41170
|
+
size: data.length
|
|
41171
|
+
};
|
|
41172
|
+
}
|
|
41173
|
+
async read(location) {
|
|
41174
|
+
try {
|
|
41175
|
+
return await fs15__namespace.readFile(location);
|
|
41176
|
+
} catch (err) {
|
|
41177
|
+
if (err.code === "ENOENT") {
|
|
41178
|
+
return null;
|
|
41179
|
+
}
|
|
41180
|
+
throw err;
|
|
41181
|
+
}
|
|
41182
|
+
}
|
|
41183
|
+
async delete(location) {
|
|
41184
|
+
try {
|
|
41185
|
+
await fs15__namespace.unlink(location);
|
|
41186
|
+
} catch (err) {
|
|
41187
|
+
if (err.code === "ENOENT") {
|
|
41188
|
+
return;
|
|
41189
|
+
}
|
|
41190
|
+
throw err;
|
|
41191
|
+
}
|
|
41192
|
+
}
|
|
41193
|
+
async exists(location) {
|
|
41194
|
+
try {
|
|
41195
|
+
await fs15__namespace.access(location);
|
|
41196
|
+
return true;
|
|
41197
|
+
} catch {
|
|
41198
|
+
return false;
|
|
41199
|
+
}
|
|
41200
|
+
}
|
|
41201
|
+
async list(options) {
|
|
41202
|
+
await this.ensureDir();
|
|
41203
|
+
let entries = [];
|
|
41204
|
+
const files = await fs15__namespace.readdir(this.outputDir);
|
|
41205
|
+
for (const file of files) {
|
|
41206
|
+
const filePath = path2__namespace.join(this.outputDir, file);
|
|
41207
|
+
try {
|
|
41208
|
+
const stat6 = await fs15__namespace.stat(filePath);
|
|
41209
|
+
if (!stat6.isFile()) continue;
|
|
41210
|
+
const ext = path2__namespace.extname(file).slice(1).toLowerCase();
|
|
41211
|
+
const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
41212
|
+
let type;
|
|
41213
|
+
for (const prefix of MEDIA_TYPE_PREFIXES) {
|
|
41214
|
+
if (file.startsWith(`${prefix}_`)) {
|
|
41215
|
+
type = prefix;
|
|
41216
|
+
break;
|
|
41217
|
+
}
|
|
41218
|
+
}
|
|
41219
|
+
entries.push({
|
|
41220
|
+
location: filePath,
|
|
41221
|
+
mimeType,
|
|
41222
|
+
size: stat6.size,
|
|
41223
|
+
type,
|
|
41224
|
+
createdAt: stat6.birthtime
|
|
41225
|
+
});
|
|
41226
|
+
} catch {
|
|
41227
|
+
}
|
|
41228
|
+
}
|
|
41229
|
+
if (options?.type) {
|
|
41230
|
+
entries = entries.filter((e) => e.type === options.type);
|
|
41231
|
+
}
|
|
41232
|
+
entries.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
41233
|
+
const offset = options?.offset ?? 0;
|
|
41234
|
+
const limit = options?.limit ?? entries.length;
|
|
41235
|
+
return entries.slice(offset, offset + limit);
|
|
41236
|
+
}
|
|
41237
|
+
getPath() {
|
|
41238
|
+
return this.outputDir;
|
|
41239
|
+
}
|
|
41240
|
+
generateFilename(metadata) {
|
|
41241
|
+
const timestamp = Date.now();
|
|
41242
|
+
const random2 = crypto2__namespace.randomBytes(4).toString("hex");
|
|
41243
|
+
const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
|
|
41244
|
+
return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
|
|
41245
|
+
}
|
|
41246
|
+
async ensureDir() {
|
|
41247
|
+
if (!this.initialized) {
|
|
41248
|
+
await fs15__namespace.mkdir(this.outputDir, { recursive: true });
|
|
41249
|
+
this.initialized = true;
|
|
41250
|
+
}
|
|
41251
|
+
}
|
|
41252
|
+
};
|
|
41253
|
+
function createFileMediaStorage(config) {
|
|
41254
|
+
return new FileMediaStorage(config);
|
|
41255
|
+
}
|
|
40934
41256
|
|
|
40935
41257
|
// src/capabilities/agents/StreamHelpers.ts
|
|
40936
41258
|
var StreamHelpers = class {
|
|
@@ -41621,6 +41943,32 @@ function filterProtectedHeaders(headers) {
|
|
|
41621
41943
|
}
|
|
41622
41944
|
return filtered;
|
|
41623
41945
|
}
|
|
41946
|
+
function normalizeBody(body) {
|
|
41947
|
+
if (typeof body === "string") {
|
|
41948
|
+
try {
|
|
41949
|
+
return JSON.parse(body);
|
|
41950
|
+
} catch {
|
|
41951
|
+
return body;
|
|
41952
|
+
}
|
|
41953
|
+
}
|
|
41954
|
+
return body;
|
|
41955
|
+
}
|
|
41956
|
+
function detectAPIError(data) {
|
|
41957
|
+
if (!data || typeof data !== "object") return null;
|
|
41958
|
+
const obj = data;
|
|
41959
|
+
if (obj.ok === false && typeof obj.error === "string") {
|
|
41960
|
+
return obj.error;
|
|
41961
|
+
}
|
|
41962
|
+
if (obj.success === false) {
|
|
41963
|
+
if (typeof obj.error === "string") return obj.error;
|
|
41964
|
+
if (typeof obj.message === "string") return obj.message;
|
|
41965
|
+
}
|
|
41966
|
+
if (obj.error && typeof obj.error === "object") {
|
|
41967
|
+
const err = obj.error;
|
|
41968
|
+
if (typeof err.message === "string") return err.message;
|
|
41969
|
+
}
|
|
41970
|
+
return null;
|
|
41971
|
+
}
|
|
41624
41972
|
var ConnectorTools = class {
|
|
41625
41973
|
/** Registry of service-specific tool factories */
|
|
41626
41974
|
static factories = /* @__PURE__ */ new Map();
|
|
@@ -41853,7 +42201,7 @@ var ConnectorTools = class {
|
|
|
41853
42201
|
static createGenericAPITool(connector, options) {
|
|
41854
42202
|
const toolName = options?.toolName ?? `${connector.name}_api`;
|
|
41855
42203
|
const userId = options?.userId;
|
|
41856
|
-
const description = options?.description ?? `Make an authenticated API call to ${connector.displayName}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}
|
|
42204
|
+
const description = options?.description ?? `Make an authenticated API call to ${connector.displayName}.` + (connector.baseURL ? ` Base URL: ${connector.baseURL}.` : " Provide full URL in endpoint.") + ' IMPORTANT: For POST/PUT/PATCH requests, pass data in the "body" parameter as a JSON object, NOT as query string parameters in the endpoint URL. The body is sent as application/json.';
|
|
41857
42205
|
return {
|
|
41858
42206
|
definition: {
|
|
41859
42207
|
type: "function",
|
|
@@ -41870,15 +42218,15 @@ var ConnectorTools = class {
|
|
|
41870
42218
|
},
|
|
41871
42219
|
endpoint: {
|
|
41872
42220
|
type: "string",
|
|
41873
|
-
description:
|
|
42221
|
+
description: 'API endpoint path (relative to base URL) or full URL. Do NOT put request data as query parameters here for POST/PUT/PATCH \u2014 use the "body" parameter instead.'
|
|
41874
42222
|
},
|
|
41875
42223
|
body: {
|
|
41876
42224
|
type: "object",
|
|
41877
|
-
description:
|
|
42225
|
+
description: 'JSON request body for POST/PUT/PATCH requests. MUST be a JSON object (NOT a string). Example: {"channel": "C123", "text": "hello"}. Do NOT stringify this \u2014 pass it as a raw JSON object. Do NOT use query string parameters for POST data.'
|
|
41878
42226
|
},
|
|
41879
42227
|
queryParams: {
|
|
41880
42228
|
type: "object",
|
|
41881
|
-
description:
|
|
42229
|
+
description: 'URL query parameters (for filtering/pagination on GET requests). Do NOT use for POST/PUT/PATCH data \u2014 use "body" instead.'
|
|
41882
42230
|
},
|
|
41883
42231
|
headers: {
|
|
41884
42232
|
type: "object",
|
|
@@ -41889,7 +42237,8 @@ var ConnectorTools = class {
|
|
|
41889
42237
|
}
|
|
41890
42238
|
}
|
|
41891
42239
|
},
|
|
41892
|
-
execute: async (args) => {
|
|
42240
|
+
execute: async (args, context) => {
|
|
42241
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
41893
42242
|
let url2 = args.endpoint;
|
|
41894
42243
|
if (args.queryParams && Object.keys(args.queryParams).length > 0) {
|
|
41895
42244
|
const params = new URLSearchParams();
|
|
@@ -41902,7 +42251,8 @@ var ConnectorTools = class {
|
|
|
41902
42251
|
let bodyStr;
|
|
41903
42252
|
if (args.body) {
|
|
41904
42253
|
try {
|
|
41905
|
-
|
|
42254
|
+
const normalized = normalizeBody(args.body);
|
|
42255
|
+
bodyStr = safeStringify2(normalized);
|
|
41906
42256
|
} catch (e) {
|
|
41907
42257
|
return {
|
|
41908
42258
|
success: false,
|
|
@@ -41921,7 +42271,7 @@ var ConnectorTools = class {
|
|
|
41921
42271
|
},
|
|
41922
42272
|
body: bodyStr
|
|
41923
42273
|
},
|
|
41924
|
-
|
|
42274
|
+
effectiveUserId
|
|
41925
42275
|
);
|
|
41926
42276
|
const text = await response.text();
|
|
41927
42277
|
let data;
|
|
@@ -41930,11 +42280,12 @@ var ConnectorTools = class {
|
|
|
41930
42280
|
} catch {
|
|
41931
42281
|
data = text;
|
|
41932
42282
|
}
|
|
42283
|
+
const apiError = detectAPIError(data);
|
|
41933
42284
|
return {
|
|
41934
|
-
success: response.ok,
|
|
42285
|
+
success: response.ok && !apiError,
|
|
41935
42286
|
status: response.status,
|
|
41936
|
-
data: response.ok ? data : void 0,
|
|
41937
|
-
error: response.ok ? void 0 : typeof data === "string" ? data : safeStringify2(data)
|
|
42287
|
+
data: response.ok && !apiError ? data : void 0,
|
|
42288
|
+
error: apiError ? apiError : response.ok ? void 0 : typeof data === "string" ? data : safeStringify2(data)
|
|
41938
42289
|
};
|
|
41939
42290
|
} catch (error) {
|
|
41940
42291
|
return {
|
|
@@ -41943,7 +42294,10 @@ var ConnectorTools = class {
|
|
|
41943
42294
|
};
|
|
41944
42295
|
}
|
|
41945
42296
|
},
|
|
41946
|
-
describeCall: (args) =>
|
|
42297
|
+
describeCall: (args) => {
|
|
42298
|
+
const bodyInfo = args.body ? ` body=${JSON.stringify(args.body).slice(0, 100)}` : "";
|
|
42299
|
+
return `${args.method} ${args.endpoint}${bodyInfo}`;
|
|
42300
|
+
},
|
|
41947
42301
|
permission: options?.permission ?? {
|
|
41948
42302
|
scope: "session",
|
|
41949
42303
|
riskLevel: "medium",
|
|
@@ -41978,8 +42332,8 @@ var FileStorage = class {
|
|
|
41978
42332
|
}
|
|
41979
42333
|
async ensureDirectory() {
|
|
41980
42334
|
try {
|
|
41981
|
-
await
|
|
41982
|
-
await
|
|
42335
|
+
await fs15__namespace.mkdir(this.directory, { recursive: true });
|
|
42336
|
+
await fs15__namespace.chmod(this.directory, 448);
|
|
41983
42337
|
} catch (error) {
|
|
41984
42338
|
}
|
|
41985
42339
|
}
|
|
@@ -41988,20 +42342,20 @@ var FileStorage = class {
|
|
|
41988
42342
|
*/
|
|
41989
42343
|
getFilePath(key) {
|
|
41990
42344
|
const hash = crypto2__namespace.createHash("sha256").update(key).digest("hex");
|
|
41991
|
-
return
|
|
42345
|
+
return path2__namespace.join(this.directory, `${hash}.token`);
|
|
41992
42346
|
}
|
|
41993
42347
|
async storeToken(key, token) {
|
|
41994
42348
|
await this.ensureDirectory();
|
|
41995
42349
|
const filePath = this.getFilePath(key);
|
|
41996
42350
|
const plaintext = JSON.stringify(token);
|
|
41997
42351
|
const encrypted = encrypt(plaintext, this.encryptionKey);
|
|
41998
|
-
await
|
|
41999
|
-
await
|
|
42352
|
+
await fs15__namespace.writeFile(filePath, encrypted, "utf8");
|
|
42353
|
+
await fs15__namespace.chmod(filePath, 384);
|
|
42000
42354
|
}
|
|
42001
42355
|
async getToken(key) {
|
|
42002
42356
|
const filePath = this.getFilePath(key);
|
|
42003
42357
|
try {
|
|
42004
|
-
const encrypted = await
|
|
42358
|
+
const encrypted = await fs15__namespace.readFile(filePath, "utf8");
|
|
42005
42359
|
const decrypted = decrypt(encrypted, this.encryptionKey);
|
|
42006
42360
|
return JSON.parse(decrypted);
|
|
42007
42361
|
} catch (error) {
|
|
@@ -42010,7 +42364,7 @@ var FileStorage = class {
|
|
|
42010
42364
|
}
|
|
42011
42365
|
console.error("Failed to read/decrypt token file:", error);
|
|
42012
42366
|
try {
|
|
42013
|
-
await
|
|
42367
|
+
await fs15__namespace.unlink(filePath);
|
|
42014
42368
|
} catch {
|
|
42015
42369
|
}
|
|
42016
42370
|
return null;
|
|
@@ -42019,7 +42373,7 @@ var FileStorage = class {
|
|
|
42019
42373
|
async deleteToken(key) {
|
|
42020
42374
|
const filePath = this.getFilePath(key);
|
|
42021
42375
|
try {
|
|
42022
|
-
await
|
|
42376
|
+
await fs15__namespace.unlink(filePath);
|
|
42023
42377
|
} catch (error) {
|
|
42024
42378
|
if (error.code !== "ENOENT") {
|
|
42025
42379
|
throw error;
|
|
@@ -42029,7 +42383,7 @@ var FileStorage = class {
|
|
|
42029
42383
|
async hasToken(key) {
|
|
42030
42384
|
const filePath = this.getFilePath(key);
|
|
42031
42385
|
try {
|
|
42032
|
-
await
|
|
42386
|
+
await fs15__namespace.access(filePath);
|
|
42033
42387
|
return true;
|
|
42034
42388
|
} catch {
|
|
42035
42389
|
return false;
|
|
@@ -42040,7 +42394,7 @@ var FileStorage = class {
|
|
|
42040
42394
|
*/
|
|
42041
42395
|
async listTokens() {
|
|
42042
42396
|
try {
|
|
42043
|
-
const files = await
|
|
42397
|
+
const files = await fs15__namespace.readdir(this.directory);
|
|
42044
42398
|
return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
|
|
42045
42399
|
} catch {
|
|
42046
42400
|
return [];
|
|
@@ -42051,10 +42405,10 @@ var FileStorage = class {
|
|
|
42051
42405
|
*/
|
|
42052
42406
|
async clearAll() {
|
|
42053
42407
|
try {
|
|
42054
|
-
const files = await
|
|
42408
|
+
const files = await fs15__namespace.readdir(this.directory);
|
|
42055
42409
|
const tokenFiles = files.filter((f) => f.endsWith(".token"));
|
|
42056
42410
|
await Promise.all(
|
|
42057
|
-
tokenFiles.map((f) =>
|
|
42411
|
+
tokenFiles.map((f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
|
|
42058
42412
|
}))
|
|
42059
42413
|
);
|
|
42060
42414
|
} catch {
|
|
@@ -42322,22 +42676,26 @@ var ConnectorConfigStore = class {
|
|
|
42322
42676
|
* Encrypt secrets in ConnectorAuth based on auth type
|
|
42323
42677
|
*/
|
|
42324
42678
|
encryptAuthSecrets(auth2) {
|
|
42679
|
+
const encryptedExtra = this.encryptExtra(auth2.extra);
|
|
42325
42680
|
switch (auth2.type) {
|
|
42326
42681
|
case "api_key":
|
|
42327
42682
|
return {
|
|
42328
42683
|
...auth2,
|
|
42329
|
-
apiKey: this.encryptValue(auth2.apiKey)
|
|
42684
|
+
apiKey: this.encryptValue(auth2.apiKey),
|
|
42685
|
+
...encryptedExtra ? { extra: encryptedExtra } : {}
|
|
42330
42686
|
};
|
|
42331
42687
|
case "oauth":
|
|
42332
42688
|
return {
|
|
42333
42689
|
...auth2,
|
|
42334
42690
|
clientSecret: auth2.clientSecret ? this.encryptValue(auth2.clientSecret) : void 0,
|
|
42335
|
-
privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0
|
|
42691
|
+
privateKey: auth2.privateKey ? this.encryptValue(auth2.privateKey) : void 0,
|
|
42692
|
+
...encryptedExtra ? { extra: encryptedExtra } : {}
|
|
42336
42693
|
};
|
|
42337
42694
|
case "jwt":
|
|
42338
42695
|
return {
|
|
42339
42696
|
...auth2,
|
|
42340
|
-
privateKey: this.encryptValue(auth2.privateKey)
|
|
42697
|
+
privateKey: this.encryptValue(auth2.privateKey),
|
|
42698
|
+
...encryptedExtra ? { extra: encryptedExtra } : {}
|
|
42341
42699
|
};
|
|
42342
42700
|
default:
|
|
42343
42701
|
return auth2;
|
|
@@ -42347,27 +42705,53 @@ var ConnectorConfigStore = class {
|
|
|
42347
42705
|
* Decrypt secrets in ConnectorAuth based on auth type
|
|
42348
42706
|
*/
|
|
42349
42707
|
decryptAuthSecrets(auth2) {
|
|
42708
|
+
const decryptedExtra = this.decryptExtra(auth2.extra);
|
|
42350
42709
|
switch (auth2.type) {
|
|
42351
42710
|
case "api_key":
|
|
42352
42711
|
return {
|
|
42353
42712
|
...auth2,
|
|
42354
|
-
apiKey: this.decryptValue(auth2.apiKey)
|
|
42713
|
+
apiKey: this.decryptValue(auth2.apiKey),
|
|
42714
|
+
...decryptedExtra ? { extra: decryptedExtra } : {}
|
|
42355
42715
|
};
|
|
42356
42716
|
case "oauth":
|
|
42357
42717
|
return {
|
|
42358
42718
|
...auth2,
|
|
42359
42719
|
clientSecret: auth2.clientSecret ? this.decryptValue(auth2.clientSecret) : void 0,
|
|
42360
|
-
privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0
|
|
42720
|
+
privateKey: auth2.privateKey ? this.decryptValue(auth2.privateKey) : void 0,
|
|
42721
|
+
...decryptedExtra ? { extra: decryptedExtra } : {}
|
|
42361
42722
|
};
|
|
42362
42723
|
case "jwt":
|
|
42363
42724
|
return {
|
|
42364
42725
|
...auth2,
|
|
42365
|
-
privateKey: this.decryptValue(auth2.privateKey)
|
|
42726
|
+
privateKey: this.decryptValue(auth2.privateKey),
|
|
42727
|
+
...decryptedExtra ? { extra: decryptedExtra } : {}
|
|
42366
42728
|
};
|
|
42367
42729
|
default:
|
|
42368
42730
|
return auth2;
|
|
42369
42731
|
}
|
|
42370
42732
|
}
|
|
42733
|
+
/**
|
|
42734
|
+
* Encrypt all values in an extra Record (vendor-specific credentials)
|
|
42735
|
+
*/
|
|
42736
|
+
encryptExtra(extra) {
|
|
42737
|
+
if (!extra || Object.keys(extra).length === 0) return void 0;
|
|
42738
|
+
const result = {};
|
|
42739
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
42740
|
+
result[key] = this.encryptValue(value);
|
|
42741
|
+
}
|
|
42742
|
+
return result;
|
|
42743
|
+
}
|
|
42744
|
+
/**
|
|
42745
|
+
* Decrypt all values in an extra Record (vendor-specific credentials)
|
|
42746
|
+
*/
|
|
42747
|
+
decryptExtra(extra) {
|
|
42748
|
+
if (!extra || Object.keys(extra).length === 0) return void 0;
|
|
42749
|
+
const result = {};
|
|
42750
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
42751
|
+
result[key] = this.decryptValue(value);
|
|
42752
|
+
}
|
|
42753
|
+
return result;
|
|
42754
|
+
}
|
|
42371
42755
|
/**
|
|
42372
42756
|
* Encrypt a single value if not already encrypted
|
|
42373
42757
|
*/
|
|
@@ -42445,20 +42829,20 @@ var FileConnectorStorage = class {
|
|
|
42445
42829
|
throw new Error("FileConnectorStorage requires a directory path");
|
|
42446
42830
|
}
|
|
42447
42831
|
this.directory = config.directory;
|
|
42448
|
-
this.indexPath =
|
|
42832
|
+
this.indexPath = path2__namespace.join(this.directory, "_index.json");
|
|
42449
42833
|
}
|
|
42450
42834
|
async save(name, stored) {
|
|
42451
42835
|
await this.ensureDirectory();
|
|
42452
42836
|
const filePath = this.getFilePath(name);
|
|
42453
42837
|
const json = JSON.stringify(stored, null, 2);
|
|
42454
|
-
await
|
|
42455
|
-
await
|
|
42838
|
+
await fs15__namespace.writeFile(filePath, json, "utf8");
|
|
42839
|
+
await fs15__namespace.chmod(filePath, 384);
|
|
42456
42840
|
await this.updateIndex(name, "add");
|
|
42457
42841
|
}
|
|
42458
42842
|
async get(name) {
|
|
42459
42843
|
const filePath = this.getFilePath(name);
|
|
42460
42844
|
try {
|
|
42461
|
-
const json = await
|
|
42845
|
+
const json = await fs15__namespace.readFile(filePath, "utf8");
|
|
42462
42846
|
return JSON.parse(json);
|
|
42463
42847
|
} catch (error) {
|
|
42464
42848
|
const err = error;
|
|
@@ -42471,7 +42855,7 @@ var FileConnectorStorage = class {
|
|
|
42471
42855
|
async delete(name) {
|
|
42472
42856
|
const filePath = this.getFilePath(name);
|
|
42473
42857
|
try {
|
|
42474
|
-
await
|
|
42858
|
+
await fs15__namespace.unlink(filePath);
|
|
42475
42859
|
await this.updateIndex(name, "remove");
|
|
42476
42860
|
return true;
|
|
42477
42861
|
} catch (error) {
|
|
@@ -42485,7 +42869,7 @@ var FileConnectorStorage = class {
|
|
|
42485
42869
|
async has(name) {
|
|
42486
42870
|
const filePath = this.getFilePath(name);
|
|
42487
42871
|
try {
|
|
42488
|
-
await
|
|
42872
|
+
await fs15__namespace.access(filePath);
|
|
42489
42873
|
return true;
|
|
42490
42874
|
} catch {
|
|
42491
42875
|
return false;
|
|
@@ -42511,13 +42895,13 @@ var FileConnectorStorage = class {
|
|
|
42511
42895
|
*/
|
|
42512
42896
|
async clear() {
|
|
42513
42897
|
try {
|
|
42514
|
-
const files = await
|
|
42898
|
+
const files = await fs15__namespace.readdir(this.directory);
|
|
42515
42899
|
const connectorFiles = files.filter(
|
|
42516
42900
|
(f) => f.endsWith(".connector.json") || f === "_index.json"
|
|
42517
42901
|
);
|
|
42518
42902
|
await Promise.all(
|
|
42519
42903
|
connectorFiles.map(
|
|
42520
|
-
(f) =>
|
|
42904
|
+
(f) => fs15__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
|
|
42521
42905
|
})
|
|
42522
42906
|
)
|
|
42523
42907
|
);
|
|
@@ -42530,7 +42914,7 @@ var FileConnectorStorage = class {
|
|
|
42530
42914
|
*/
|
|
42531
42915
|
getFilePath(name) {
|
|
42532
42916
|
const hash = this.hashName(name);
|
|
42533
|
-
return
|
|
42917
|
+
return path2__namespace.join(this.directory, `${hash}.connector.json`);
|
|
42534
42918
|
}
|
|
42535
42919
|
/**
|
|
42536
42920
|
* Hash connector name to prevent enumeration
|
|
@@ -42544,8 +42928,8 @@ var FileConnectorStorage = class {
|
|
|
42544
42928
|
async ensureDirectory() {
|
|
42545
42929
|
if (this.initialized) return;
|
|
42546
42930
|
try {
|
|
42547
|
-
await
|
|
42548
|
-
await
|
|
42931
|
+
await fs15__namespace.mkdir(this.directory, { recursive: true });
|
|
42932
|
+
await fs15__namespace.chmod(this.directory, 448);
|
|
42549
42933
|
this.initialized = true;
|
|
42550
42934
|
} catch {
|
|
42551
42935
|
this.initialized = true;
|
|
@@ -42556,7 +42940,7 @@ var FileConnectorStorage = class {
|
|
|
42556
42940
|
*/
|
|
42557
42941
|
async loadIndex() {
|
|
42558
42942
|
try {
|
|
42559
|
-
const json = await
|
|
42943
|
+
const json = await fs15__namespace.readFile(this.indexPath, "utf8");
|
|
42560
42944
|
return JSON.parse(json);
|
|
42561
42945
|
} catch {
|
|
42562
42946
|
return { connectors: {} };
|
|
@@ -42574,8 +42958,8 @@ var FileConnectorStorage = class {
|
|
|
42574
42958
|
delete index.connectors[hash];
|
|
42575
42959
|
}
|
|
42576
42960
|
const json = JSON.stringify(index, null, 2);
|
|
42577
|
-
await
|
|
42578
|
-
await
|
|
42961
|
+
await fs15__namespace.writeFile(this.indexPath, json, "utf8");
|
|
42962
|
+
await fs15__namespace.chmod(this.indexPath, 384);
|
|
42579
42963
|
}
|
|
42580
42964
|
};
|
|
42581
42965
|
|
|
@@ -42620,11 +43004,19 @@ function buildAuthConfig(authTemplate, credentials) {
|
|
|
42620
43004
|
if (!credentials.apiKey) {
|
|
42621
43005
|
throw new Error("API key is required for api_key auth");
|
|
42622
43006
|
}
|
|
43007
|
+
const standardApiKeyFields = /* @__PURE__ */ new Set(["apiKey", "headerName", "headerPrefix"]);
|
|
43008
|
+
const extra = {};
|
|
43009
|
+
for (const field of authTemplate.optionalFields ?? []) {
|
|
43010
|
+
if (!standardApiKeyFields.has(field) && credentials[field]) {
|
|
43011
|
+
extra[field] = credentials[field];
|
|
43012
|
+
}
|
|
43013
|
+
}
|
|
42623
43014
|
return {
|
|
42624
43015
|
type: "api_key",
|
|
42625
43016
|
apiKey: credentials.apiKey,
|
|
42626
43017
|
headerName: defaults.headerName ?? "Authorization",
|
|
42627
|
-
headerPrefix: defaults.headerPrefix ?? "Bearer"
|
|
43018
|
+
headerPrefix: defaults.headerPrefix ?? "Bearer",
|
|
43019
|
+
...Object.keys(extra).length > 0 ? { extra } : {}
|
|
42628
43020
|
};
|
|
42629
43021
|
}
|
|
42630
43022
|
if (!authTemplate.flow) {
|
|
@@ -42894,8 +43286,9 @@ var slackTemplate = {
|
|
|
42894
43286
|
id: "bot-token",
|
|
42895
43287
|
name: "Bot Token",
|
|
42896
43288
|
type: "api_key",
|
|
42897
|
-
description: "Internal workspace bot - get from OAuth & Permissions page of your Slack app",
|
|
43289
|
+
description: "Internal workspace bot - get from OAuth & Permissions page of your Slack app. For Socket Mode bots, also provide appToken and signingSecret in extra fields.",
|
|
42898
43290
|
requiredFields: ["apiKey"],
|
|
43291
|
+
optionalFields: ["appToken", "signingSecret"],
|
|
42899
43292
|
defaults: {
|
|
42900
43293
|
type: "api_key",
|
|
42901
43294
|
headerName: "Authorization",
|
|
@@ -44733,14 +45126,14 @@ function createMessageWithImages(text, imageUrls, role = "user" /* USER */) {
|
|
|
44733
45126
|
var execAsync = util.promisify(child_process.exec);
|
|
44734
45127
|
function cleanupTempFile(filePath) {
|
|
44735
45128
|
try {
|
|
44736
|
-
if (
|
|
44737
|
-
|
|
45129
|
+
if (fs16__namespace.existsSync(filePath)) {
|
|
45130
|
+
fs16__namespace.unlinkSync(filePath);
|
|
44738
45131
|
}
|
|
44739
45132
|
} catch {
|
|
44740
45133
|
}
|
|
44741
45134
|
}
|
|
44742
45135
|
async function readClipboardImage() {
|
|
44743
|
-
const platform2 =
|
|
45136
|
+
const platform2 = os2__namespace.platform();
|
|
44744
45137
|
try {
|
|
44745
45138
|
switch (platform2) {
|
|
44746
45139
|
case "darwin":
|
|
@@ -44763,7 +45156,7 @@ async function readClipboardImage() {
|
|
|
44763
45156
|
}
|
|
44764
45157
|
}
|
|
44765
45158
|
async function readClipboardImageMac() {
|
|
44766
|
-
const tempFile =
|
|
45159
|
+
const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
|
|
44767
45160
|
try {
|
|
44768
45161
|
try {
|
|
44769
45162
|
await execAsync(`pngpaste "${tempFile}"`);
|
|
@@ -44785,7 +45178,7 @@ async function readClipboardImageMac() {
|
|
|
44785
45178
|
end try
|
|
44786
45179
|
`;
|
|
44787
45180
|
const { stdout } = await execAsync(`osascript -e '${script}'`);
|
|
44788
|
-
if (stdout.includes("success") ||
|
|
45181
|
+
if (stdout.includes("success") || fs16__namespace.existsSync(tempFile)) {
|
|
44789
45182
|
return await convertFileToDataUri(tempFile);
|
|
44790
45183
|
}
|
|
44791
45184
|
return {
|
|
@@ -44798,18 +45191,18 @@ async function readClipboardImageMac() {
|
|
|
44798
45191
|
}
|
|
44799
45192
|
}
|
|
44800
45193
|
async function readClipboardImageLinux() {
|
|
44801
|
-
const tempFile =
|
|
45194
|
+
const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
|
|
44802
45195
|
try {
|
|
44803
45196
|
try {
|
|
44804
45197
|
await execAsync(`xclip -selection clipboard -t image/png -o > "${tempFile}"`);
|
|
44805
|
-
if (
|
|
45198
|
+
if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
|
|
44806
45199
|
return await convertFileToDataUri(tempFile);
|
|
44807
45200
|
}
|
|
44808
45201
|
} catch {
|
|
44809
45202
|
}
|
|
44810
45203
|
try {
|
|
44811
45204
|
await execAsync(`wl-paste -t image/png > "${tempFile}"`);
|
|
44812
|
-
if (
|
|
45205
|
+
if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
|
|
44813
45206
|
return await convertFileToDataUri(tempFile);
|
|
44814
45207
|
}
|
|
44815
45208
|
} catch {
|
|
@@ -44823,7 +45216,7 @@ async function readClipboardImageLinux() {
|
|
|
44823
45216
|
}
|
|
44824
45217
|
}
|
|
44825
45218
|
async function readClipboardImageWindows() {
|
|
44826
|
-
const tempFile =
|
|
45219
|
+
const tempFile = path2__namespace.join(os2__namespace.tmpdir(), `clipboard-${Date.now()}.png`);
|
|
44827
45220
|
try {
|
|
44828
45221
|
const psScript = `
|
|
44829
45222
|
Add-Type -AssemblyName System.Windows.Forms;
|
|
@@ -44836,7 +45229,7 @@ async function readClipboardImageWindows() {
|
|
|
44836
45229
|
}
|
|
44837
45230
|
`;
|
|
44838
45231
|
await execAsync(`powershell -Command "${psScript}"`);
|
|
44839
|
-
if (
|
|
45232
|
+
if (fs16__namespace.existsSync(tempFile) && fs16__namespace.statSync(tempFile).size > 0) {
|
|
44840
45233
|
return await convertFileToDataUri(tempFile);
|
|
44841
45234
|
}
|
|
44842
45235
|
return {
|
|
@@ -44849,7 +45242,7 @@ async function readClipboardImageWindows() {
|
|
|
44849
45242
|
}
|
|
44850
45243
|
async function convertFileToDataUri(filePath) {
|
|
44851
45244
|
try {
|
|
44852
|
-
const imageBuffer =
|
|
45245
|
+
const imageBuffer = fs16__namespace.readFileSync(filePath);
|
|
44853
45246
|
const base64Image = imageBuffer.toString("base64");
|
|
44854
45247
|
const magic = imageBuffer.slice(0, 4).toString("hex");
|
|
44855
45248
|
let mimeType = "image/png";
|
|
@@ -44876,7 +45269,7 @@ async function convertFileToDataUri(filePath) {
|
|
|
44876
45269
|
}
|
|
44877
45270
|
}
|
|
44878
45271
|
async function hasClipboardImage() {
|
|
44879
|
-
const platform2 =
|
|
45272
|
+
const platform2 = os2__namespace.platform();
|
|
44880
45273
|
try {
|
|
44881
45274
|
switch (platform2) {
|
|
44882
45275
|
case "darwin":
|
|
@@ -45094,20 +45487,29 @@ __export(tools_exports, {
|
|
|
45094
45487
|
ConnectorTools: () => ConnectorTools,
|
|
45095
45488
|
DEFAULT_FILESYSTEM_CONFIG: () => DEFAULT_FILESYSTEM_CONFIG,
|
|
45096
45489
|
DEFAULT_SHELL_CONFIG: () => DEFAULT_SHELL_CONFIG,
|
|
45097
|
-
FileMediaOutputHandler: () =>
|
|
45490
|
+
FileMediaOutputHandler: () => FileMediaStorage,
|
|
45098
45491
|
ToolRegistry: () => ToolRegistry,
|
|
45099
45492
|
bash: () => bash,
|
|
45100
45493
|
createBashTool: () => createBashTool,
|
|
45494
|
+
createCreatePRTool: () => createCreatePRTool,
|
|
45101
45495
|
createEditFileTool: () => createEditFileTool,
|
|
45102
45496
|
createExecuteJavaScriptTool: () => createExecuteJavaScriptTool,
|
|
45497
|
+
createGetPRTool: () => createGetPRTool,
|
|
45498
|
+
createGitHubReadFileTool: () => createGitHubReadFileTool,
|
|
45103
45499
|
createGlobTool: () => createGlobTool,
|
|
45104
45500
|
createGrepTool: () => createGrepTool,
|
|
45105
45501
|
createImageGenerationTool: () => createImageGenerationTool,
|
|
45106
45502
|
createListDirectoryTool: () => createListDirectoryTool,
|
|
45503
|
+
createPRCommentsTool: () => createPRCommentsTool,
|
|
45504
|
+
createPRFilesTool: () => createPRFilesTool,
|
|
45107
45505
|
createReadFileTool: () => createReadFileTool,
|
|
45506
|
+
createSearchCodeTool: () => createSearchCodeTool,
|
|
45507
|
+
createSearchFilesTool: () => createSearchFilesTool,
|
|
45108
45508
|
createSpeechToTextTool: () => createSpeechToTextTool,
|
|
45109
45509
|
createTextToSpeechTool: () => createTextToSpeechTool,
|
|
45110
45510
|
createVideoTools: () => createVideoTools,
|
|
45511
|
+
createWebScrapeTool: () => createWebScrapeTool,
|
|
45512
|
+
createWebSearchTool: () => createWebSearchTool,
|
|
45111
45513
|
createWriteFileTool: () => createWriteFileTool,
|
|
45112
45514
|
developerTools: () => developerTools,
|
|
45113
45515
|
editFile: () => editFile,
|
|
@@ -45116,6 +45518,7 @@ __export(tools_exports, {
|
|
|
45116
45518
|
getAllBuiltInTools: () => getAllBuiltInTools,
|
|
45117
45519
|
getBackgroundOutput: () => getBackgroundOutput,
|
|
45118
45520
|
getMediaOutputHandler: () => getMediaOutputHandler,
|
|
45521
|
+
getMediaStorage: () => getMediaStorage,
|
|
45119
45522
|
getToolByName: () => getToolByName,
|
|
45120
45523
|
getToolCategories: () => getToolCategories,
|
|
45121
45524
|
getToolRegistry: () => getToolRegistry,
|
|
@@ -45128,15 +45531,15 @@ __export(tools_exports, {
|
|
|
45128
45531
|
jsonManipulator: () => jsonManipulator,
|
|
45129
45532
|
killBackgroundProcess: () => killBackgroundProcess,
|
|
45130
45533
|
listDirectory: () => listDirectory,
|
|
45131
|
-
|
|
45534
|
+
parseRepository: () => parseRepository,
|
|
45535
|
+
readFile: () => readFile5,
|
|
45536
|
+
resolveRepository: () => resolveRepository,
|
|
45132
45537
|
setMediaOutputHandler: () => setMediaOutputHandler,
|
|
45538
|
+
setMediaStorage: () => setMediaStorage,
|
|
45133
45539
|
toolRegistry: () => toolRegistry,
|
|
45134
45540
|
validatePath: () => validatePath,
|
|
45135
45541
|
webFetch: () => webFetch,
|
|
45136
|
-
|
|
45137
|
-
webScrape: () => webScrape,
|
|
45138
|
-
webSearch: () => webSearch,
|
|
45139
|
-
writeFile: () => writeFile4
|
|
45542
|
+
writeFile: () => writeFile5
|
|
45140
45543
|
});
|
|
45141
45544
|
var DEFAULT_FILESYSTEM_CONFIG = {
|
|
45142
45545
|
workingDirectory: process.cwd(),
|
|
@@ -45195,15 +45598,15 @@ function validatePath(inputPath, config = {}) {
|
|
|
45195
45598
|
const blockedDirs = config.blockedDirectories || DEFAULT_FILESYSTEM_CONFIG.blockedDirectories;
|
|
45196
45599
|
let expandedPath = inputPath;
|
|
45197
45600
|
if (inputPath.startsWith("~/")) {
|
|
45198
|
-
expandedPath =
|
|
45601
|
+
expandedPath = path2.resolve(os2.homedir(), inputPath.slice(2));
|
|
45199
45602
|
} else if (inputPath === "~") {
|
|
45200
|
-
expandedPath =
|
|
45603
|
+
expandedPath = os2.homedir();
|
|
45201
45604
|
}
|
|
45202
45605
|
let resolvedPath;
|
|
45203
|
-
if (
|
|
45204
|
-
resolvedPath =
|
|
45606
|
+
if (path2.isAbsolute(expandedPath)) {
|
|
45607
|
+
resolvedPath = path2.normalize(expandedPath);
|
|
45205
45608
|
} else {
|
|
45206
|
-
resolvedPath =
|
|
45609
|
+
resolvedPath = path2.resolve(workingDir, expandedPath);
|
|
45207
45610
|
}
|
|
45208
45611
|
const pathSegments = resolvedPath.split("/").filter(Boolean);
|
|
45209
45612
|
for (const blocked of blockedDirs) {
|
|
@@ -45216,7 +45619,7 @@ function validatePath(inputPath, config = {}) {
|
|
|
45216
45619
|
};
|
|
45217
45620
|
}
|
|
45218
45621
|
} else {
|
|
45219
|
-
const blockedPath =
|
|
45622
|
+
const blockedPath = path2.isAbsolute(blocked) ? blocked : path2.resolve(workingDir, blocked);
|
|
45220
45623
|
if (resolvedPath.startsWith(blockedPath + "/") || resolvedPath === blockedPath) {
|
|
45221
45624
|
return {
|
|
45222
45625
|
valid: false,
|
|
@@ -45229,7 +45632,7 @@ function validatePath(inputPath, config = {}) {
|
|
|
45229
45632
|
if (allowedDirs.length > 0) {
|
|
45230
45633
|
let isAllowed = false;
|
|
45231
45634
|
for (const allowed of allowedDirs) {
|
|
45232
|
-
const allowedPath =
|
|
45635
|
+
const allowedPath = path2.isAbsolute(allowed) ? allowed : path2.resolve(workingDir, allowed);
|
|
45233
45636
|
if (resolvedPath.startsWith(allowedPath + "/") || resolvedPath === allowedPath) {
|
|
45234
45637
|
isAllowed = true;
|
|
45235
45638
|
break;
|
|
@@ -45247,9 +45650,9 @@ function validatePath(inputPath, config = {}) {
|
|
|
45247
45650
|
}
|
|
45248
45651
|
function expandTilde(inputPath) {
|
|
45249
45652
|
if (inputPath.startsWith("~/")) {
|
|
45250
|
-
return
|
|
45653
|
+
return path2.resolve(os2.homedir(), inputPath.slice(2));
|
|
45251
45654
|
} else if (inputPath === "~") {
|
|
45252
|
-
return
|
|
45655
|
+
return os2.homedir();
|
|
45253
45656
|
}
|
|
45254
45657
|
return inputPath;
|
|
45255
45658
|
}
|
|
@@ -45324,7 +45727,7 @@ EXAMPLES:
|
|
|
45324
45727
|
};
|
|
45325
45728
|
}
|
|
45326
45729
|
const resolvedPath = validation.resolvedPath;
|
|
45327
|
-
if (!
|
|
45730
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
45328
45731
|
return {
|
|
45329
45732
|
success: false,
|
|
45330
45733
|
error: `File not found: ${file_path}`,
|
|
@@ -45332,7 +45735,7 @@ EXAMPLES:
|
|
|
45332
45735
|
};
|
|
45333
45736
|
}
|
|
45334
45737
|
try {
|
|
45335
|
-
const stats = await
|
|
45738
|
+
const stats = await fs15.stat(resolvedPath);
|
|
45336
45739
|
if (!stats.isFile()) {
|
|
45337
45740
|
return {
|
|
45338
45741
|
success: false,
|
|
@@ -45348,7 +45751,7 @@ EXAMPLES:
|
|
|
45348
45751
|
size: stats.size
|
|
45349
45752
|
};
|
|
45350
45753
|
}
|
|
45351
|
-
const content = await
|
|
45754
|
+
const content = await fs15.readFile(resolvedPath, "utf-8");
|
|
45352
45755
|
const allLines = content.split("\n");
|
|
45353
45756
|
const totalLines = allLines.length;
|
|
45354
45757
|
const startIndex = Math.max(0, offset - 1);
|
|
@@ -45389,7 +45792,7 @@ EXAMPLES:
|
|
|
45389
45792
|
}
|
|
45390
45793
|
};
|
|
45391
45794
|
}
|
|
45392
|
-
var
|
|
45795
|
+
var readFile5 = createReadFileTool();
|
|
45393
45796
|
function createWriteFileTool(config = {}) {
|
|
45394
45797
|
const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
|
|
45395
45798
|
return {
|
|
@@ -45453,13 +45856,13 @@ EXAMPLES:
|
|
|
45453
45856
|
};
|
|
45454
45857
|
}
|
|
45455
45858
|
const resolvedPath = validation.resolvedPath;
|
|
45456
|
-
const fileExists =
|
|
45859
|
+
const fileExists = fs16.existsSync(resolvedPath);
|
|
45457
45860
|
try {
|
|
45458
|
-
const parentDir =
|
|
45459
|
-
if (!
|
|
45460
|
-
await
|
|
45861
|
+
const parentDir = path2.dirname(resolvedPath);
|
|
45862
|
+
if (!fs16.existsSync(parentDir)) {
|
|
45863
|
+
await fs15.mkdir(parentDir, { recursive: true });
|
|
45461
45864
|
}
|
|
45462
|
-
await
|
|
45865
|
+
await fs15.writeFile(resolvedPath, content, "utf-8");
|
|
45463
45866
|
return {
|
|
45464
45867
|
success: true,
|
|
45465
45868
|
path: file_path,
|
|
@@ -45476,7 +45879,7 @@ EXAMPLES:
|
|
|
45476
45879
|
}
|
|
45477
45880
|
};
|
|
45478
45881
|
}
|
|
45479
|
-
var
|
|
45882
|
+
var writeFile5 = createWriteFileTool();
|
|
45480
45883
|
function createEditFileTool(config = {}) {
|
|
45481
45884
|
const mergedConfig = { ...DEFAULT_FILESYSTEM_CONFIG, ...config };
|
|
45482
45885
|
return {
|
|
@@ -45562,7 +45965,7 @@ EXAMPLES:
|
|
|
45562
45965
|
};
|
|
45563
45966
|
}
|
|
45564
45967
|
const resolvedPath = validation.resolvedPath;
|
|
45565
|
-
if (!
|
|
45968
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
45566
45969
|
return {
|
|
45567
45970
|
success: false,
|
|
45568
45971
|
error: `File not found: ${file_path}`,
|
|
@@ -45570,7 +45973,7 @@ EXAMPLES:
|
|
|
45570
45973
|
};
|
|
45571
45974
|
}
|
|
45572
45975
|
try {
|
|
45573
|
-
const content = await
|
|
45976
|
+
const content = await fs15.readFile(resolvedPath, "utf-8");
|
|
45574
45977
|
let occurrences = 0;
|
|
45575
45978
|
let searchIndex = 0;
|
|
45576
45979
|
while (true) {
|
|
@@ -45609,7 +46012,7 @@ EXAMPLES:
|
|
|
45609
46012
|
} else {
|
|
45610
46013
|
newContent = content.replace(old_string, new_string);
|
|
45611
46014
|
}
|
|
45612
|
-
await
|
|
46015
|
+
await fs15.writeFile(resolvedPath, newContent, "utf-8");
|
|
45613
46016
|
const diffPreview = generateDiffPreview(old_string, new_string);
|
|
45614
46017
|
return {
|
|
45615
46018
|
success: true,
|
|
@@ -45665,11 +46068,11 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
|
|
|
45665
46068
|
return results;
|
|
45666
46069
|
}
|
|
45667
46070
|
try {
|
|
45668
|
-
const entries = await
|
|
46071
|
+
const entries = await fs15.readdir(dir, { withFileTypes: true });
|
|
45669
46072
|
for (const entry of entries) {
|
|
45670
46073
|
if (results.length >= config.maxResults) break;
|
|
45671
|
-
const fullPath =
|
|
45672
|
-
const relativePath =
|
|
46074
|
+
const fullPath = path2.join(dir, entry.name);
|
|
46075
|
+
const relativePath = path2.relative(baseDir, fullPath);
|
|
45673
46076
|
if (entry.isDirectory()) {
|
|
45674
46077
|
const isBlocked = config.blockedDirectories.some(
|
|
45675
46078
|
(blocked) => entry.name === blocked || relativePath.includes(`/${blocked}/`) || relativePath.startsWith(`${blocked}/`)
|
|
@@ -45679,7 +46082,7 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
|
|
|
45679
46082
|
} else if (entry.isFile()) {
|
|
45680
46083
|
if (matchGlobPattern(pattern, relativePath)) {
|
|
45681
46084
|
try {
|
|
45682
|
-
const stats = await
|
|
46085
|
+
const stats = await fs15.stat(fullPath);
|
|
45683
46086
|
results.push({
|
|
45684
46087
|
path: relativePath,
|
|
45685
46088
|
mtime: stats.mtimeMs
|
|
@@ -45761,7 +46164,7 @@ WHEN TO USE:
|
|
|
45761
46164
|
};
|
|
45762
46165
|
}
|
|
45763
46166
|
const resolvedDir = validation.resolvedPath;
|
|
45764
|
-
if (!
|
|
46167
|
+
if (!fs16.existsSync(resolvedDir)) {
|
|
45765
46168
|
return {
|
|
45766
46169
|
success: false,
|
|
45767
46170
|
error: `Directory not found: ${searchDir}`
|
|
@@ -45816,9 +46219,9 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
|
|
|
45816
46219
|
return files;
|
|
45817
46220
|
}
|
|
45818
46221
|
try {
|
|
45819
|
-
const entries = await
|
|
46222
|
+
const entries = await fs15.readdir(dir, { withFileTypes: true });
|
|
45820
46223
|
for (const entry of entries) {
|
|
45821
|
-
const fullPath =
|
|
46224
|
+
const fullPath = path2.join(dir, entry.name);
|
|
45822
46225
|
if (entry.isDirectory()) {
|
|
45823
46226
|
const isBlocked = config.blockedDirectories.some(
|
|
45824
46227
|
(blocked) => entry.name === blocked
|
|
@@ -45830,7 +46233,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
|
|
|
45830
46233
|
if (fileType) {
|
|
45831
46234
|
const extensions = FILE_TYPE_MAP[fileType.toLowerCase()];
|
|
45832
46235
|
if (extensions) {
|
|
45833
|
-
const ext =
|
|
46236
|
+
const ext = path2.extname(entry.name).toLowerCase();
|
|
45834
46237
|
if (!extensions.includes(ext)) continue;
|
|
45835
46238
|
}
|
|
45836
46239
|
}
|
|
@@ -45849,7 +46252,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
|
|
|
45849
46252
|
async function searchFile(filePath, regex, contextBefore, contextAfter) {
|
|
45850
46253
|
const matches = [];
|
|
45851
46254
|
try {
|
|
45852
|
-
const content = await
|
|
46255
|
+
const content = await fs15.readFile(filePath, "utf-8");
|
|
45853
46256
|
const lines = content.split("\n");
|
|
45854
46257
|
for (let i = 0; i < lines.length; i++) {
|
|
45855
46258
|
const line = lines[i] ?? "";
|
|
@@ -45990,7 +46393,7 @@ WHEN TO USE:
|
|
|
45990
46393
|
};
|
|
45991
46394
|
}
|
|
45992
46395
|
const resolvedPath = validation.resolvedPath;
|
|
45993
|
-
if (!
|
|
46396
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
45994
46397
|
return {
|
|
45995
46398
|
success: false,
|
|
45996
46399
|
error: `Path not found: ${searchPath}`
|
|
@@ -46006,7 +46409,7 @@ WHEN TO USE:
|
|
|
46006
46409
|
};
|
|
46007
46410
|
}
|
|
46008
46411
|
try {
|
|
46009
|
-
const stats = await
|
|
46412
|
+
const stats = await fs15.stat(resolvedPath);
|
|
46010
46413
|
let filesToSearch;
|
|
46011
46414
|
if (stats.isFile()) {
|
|
46012
46415
|
filesToSearch = [resolvedPath];
|
|
@@ -46032,7 +46435,7 @@ WHEN TO USE:
|
|
|
46032
46435
|
);
|
|
46033
46436
|
if (matches.length > 0) {
|
|
46034
46437
|
filesMatched++;
|
|
46035
|
-
const relativePath =
|
|
46438
|
+
const relativePath = path2.relative(resolvedPath, file) || file;
|
|
46036
46439
|
for (const match of matches) {
|
|
46037
46440
|
match.file = relativePath;
|
|
46038
46441
|
}
|
|
@@ -46094,11 +46497,11 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
|
|
|
46094
46497
|
return entries;
|
|
46095
46498
|
}
|
|
46096
46499
|
try {
|
|
46097
|
-
const dirEntries = await
|
|
46500
|
+
const dirEntries = await fs15.readdir(dir, { withFileTypes: true });
|
|
46098
46501
|
for (const entry of dirEntries) {
|
|
46099
46502
|
if (entries.length >= config.maxResults) break;
|
|
46100
|
-
const fullPath =
|
|
46101
|
-
const relativePath =
|
|
46503
|
+
const fullPath = path2.join(dir, entry.name);
|
|
46504
|
+
const relativePath = path2.relative(baseDir, fullPath);
|
|
46102
46505
|
if (entry.isDirectory() && config.blockedDirectories.includes(entry.name)) {
|
|
46103
46506
|
continue;
|
|
46104
46507
|
}
|
|
@@ -46112,7 +46515,7 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
|
|
|
46112
46515
|
}
|
|
46113
46516
|
if (filter === "directories" && !isDir) continue;
|
|
46114
46517
|
try {
|
|
46115
|
-
const stats = await
|
|
46518
|
+
const stats = await fs15.stat(fullPath);
|
|
46116
46519
|
const dirEntry = {
|
|
46117
46520
|
name: entry.name,
|
|
46118
46521
|
path: relativePath,
|
|
@@ -46208,14 +46611,14 @@ EXAMPLES:
|
|
|
46208
46611
|
};
|
|
46209
46612
|
}
|
|
46210
46613
|
const resolvedPath = validation.resolvedPath;
|
|
46211
|
-
if (!
|
|
46614
|
+
if (!fs16.existsSync(resolvedPath)) {
|
|
46212
46615
|
return {
|
|
46213
46616
|
success: false,
|
|
46214
46617
|
error: `Directory not found: ${path6}`
|
|
46215
46618
|
};
|
|
46216
46619
|
}
|
|
46217
46620
|
try {
|
|
46218
|
-
const stats = await
|
|
46621
|
+
const stats = await fs15.stat(resolvedPath);
|
|
46219
46622
|
if (!stats.isDirectory()) {
|
|
46220
46623
|
return {
|
|
46221
46624
|
success: false,
|
|
@@ -46403,7 +46806,8 @@ EXAMPLES:
|
|
|
46403
46806
|
shell: mergedConfig.shell,
|
|
46404
46807
|
cwd: mergedConfig.workingDirectory,
|
|
46405
46808
|
env,
|
|
46406
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
46809
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
46810
|
+
detached: true
|
|
46407
46811
|
});
|
|
46408
46812
|
if (run_in_background && mergedConfig.allowBackground) {
|
|
46409
46813
|
const bgId = generateBackgroundId();
|
|
@@ -46430,14 +46834,27 @@ EXAMPLES:
|
|
|
46430
46834
|
let stdout = "";
|
|
46431
46835
|
let stderr = "";
|
|
46432
46836
|
let killed = false;
|
|
46837
|
+
const killProcessGroup = (signal) => {
|
|
46838
|
+
try {
|
|
46839
|
+
if (childProcess.pid) {
|
|
46840
|
+
process.kill(-childProcess.pid, signal);
|
|
46841
|
+
}
|
|
46842
|
+
} catch {
|
|
46843
|
+
try {
|
|
46844
|
+
childProcess.kill(signal);
|
|
46845
|
+
} catch {
|
|
46846
|
+
}
|
|
46847
|
+
}
|
|
46848
|
+
};
|
|
46849
|
+
const GRACEFUL_KILL_WAIT_MS = 3e3;
|
|
46433
46850
|
const timeoutId = setTimeout(() => {
|
|
46434
46851
|
killed = true;
|
|
46435
|
-
|
|
46852
|
+
killProcessGroup("SIGTERM");
|
|
46436
46853
|
setTimeout(() => {
|
|
46437
46854
|
if (!childProcess.killed) {
|
|
46438
|
-
|
|
46855
|
+
killProcessGroup("SIGKILL");
|
|
46439
46856
|
}
|
|
46440
|
-
},
|
|
46857
|
+
}, GRACEFUL_KILL_WAIT_MS);
|
|
46441
46858
|
}, effectiveTimeout);
|
|
46442
46859
|
childProcess.stdout.on("data", (data) => {
|
|
46443
46860
|
stdout += data.toString();
|
|
@@ -46451,8 +46868,28 @@ EXAMPLES:
|
|
|
46451
46868
|
stderr = stderr.slice(-mergedConfig.maxOutputSize);
|
|
46452
46869
|
}
|
|
46453
46870
|
});
|
|
46454
|
-
|
|
46871
|
+
let resolved = false;
|
|
46872
|
+
const safeResolve = (result) => {
|
|
46873
|
+
if (resolved) return;
|
|
46874
|
+
resolved = true;
|
|
46455
46875
|
clearTimeout(timeoutId);
|
|
46876
|
+
clearTimeout(hardTimeoutId);
|
|
46877
|
+
resolve4(result);
|
|
46878
|
+
};
|
|
46879
|
+
const HARD_TIMEOUT_GRACE_MS = 5e3;
|
|
46880
|
+
const hardTimeoutId = setTimeout(() => {
|
|
46881
|
+
if (!resolved) {
|
|
46882
|
+
killProcessGroup("SIGKILL");
|
|
46883
|
+
safeResolve({
|
|
46884
|
+
success: false,
|
|
46885
|
+
stdout,
|
|
46886
|
+
stderr,
|
|
46887
|
+
duration: Date.now() - startTime,
|
|
46888
|
+
error: `Command timed out after ${effectiveTimeout}ms (hard timeout: process group did not exit)`
|
|
46889
|
+
});
|
|
46890
|
+
}
|
|
46891
|
+
}, effectiveTimeout + GRACEFUL_KILL_WAIT_MS + HARD_TIMEOUT_GRACE_MS);
|
|
46892
|
+
childProcess.on("close", (code, signal) => {
|
|
46456
46893
|
const duration = Date.now() - startTime;
|
|
46457
46894
|
let truncated = false;
|
|
46458
46895
|
if (stdout.length > mergedConfig.maxOutputSize) {
|
|
@@ -46464,7 +46901,7 @@ EXAMPLES:
|
|
|
46464
46901
|
truncated = true;
|
|
46465
46902
|
}
|
|
46466
46903
|
if (killed) {
|
|
46467
|
-
|
|
46904
|
+
safeResolve({
|
|
46468
46905
|
success: false,
|
|
46469
46906
|
stdout,
|
|
46470
46907
|
stderr,
|
|
@@ -46475,7 +46912,7 @@ EXAMPLES:
|
|
|
46475
46912
|
error: `Command timed out after ${effectiveTimeout}ms`
|
|
46476
46913
|
});
|
|
46477
46914
|
} else {
|
|
46478
|
-
|
|
46915
|
+
safeResolve({
|
|
46479
46916
|
success: code === 0,
|
|
46480
46917
|
stdout,
|
|
46481
46918
|
stderr,
|
|
@@ -46488,8 +46925,7 @@ EXAMPLES:
|
|
|
46488
46925
|
}
|
|
46489
46926
|
});
|
|
46490
46927
|
childProcess.on("error", (error) => {
|
|
46491
|
-
|
|
46492
|
-
resolve4({
|
|
46928
|
+
safeResolve({
|
|
46493
46929
|
success: false,
|
|
46494
46930
|
error: `Failed to execute command: ${error.message}`,
|
|
46495
46931
|
duration: Date.now() - startTime
|
|
@@ -46825,6 +47261,111 @@ The tool returns a result object with:
|
|
|
46825
47261
|
}
|
|
46826
47262
|
};
|
|
46827
47263
|
|
|
47264
|
+
// src/tools/web/createWebSearchTool.ts
|
|
47265
|
+
init_Logger();
|
|
47266
|
+
var searchLogger = exports.logger.child({ component: "webSearch" });
|
|
47267
|
+
function createWebSearchTool(connector) {
|
|
47268
|
+
return {
|
|
47269
|
+
definition: {
|
|
47270
|
+
type: "function",
|
|
47271
|
+
function: {
|
|
47272
|
+
name: "web_search",
|
|
47273
|
+
description: `Search the web and get relevant results with snippets.
|
|
47274
|
+
|
|
47275
|
+
RETURNS:
|
|
47276
|
+
An array of search results, each containing:
|
|
47277
|
+
- title: Page title
|
|
47278
|
+
- url: Direct URL to the page
|
|
47279
|
+
- snippet: Short description/excerpt from the page
|
|
47280
|
+
- position: Search ranking position (1, 2, 3...)
|
|
47281
|
+
|
|
47282
|
+
USE CASES:
|
|
47283
|
+
- Find current information on any topic
|
|
47284
|
+
- Research multiple sources
|
|
47285
|
+
- Discover relevant websites
|
|
47286
|
+
- Find URLs to fetch with web_fetch tool
|
|
47287
|
+
|
|
47288
|
+
WORKFLOW PATTERN:
|
|
47289
|
+
1. Use web_search to find relevant URLs
|
|
47290
|
+
2. Use web_fetch to get full content from top results
|
|
47291
|
+
3. Process and summarize the information
|
|
47292
|
+
|
|
47293
|
+
EXAMPLE:
|
|
47294
|
+
{
|
|
47295
|
+
"query": "latest AI developments 2026",
|
|
47296
|
+
"numResults": 5
|
|
47297
|
+
}`,
|
|
47298
|
+
parameters: {
|
|
47299
|
+
type: "object",
|
|
47300
|
+
properties: {
|
|
47301
|
+
query: {
|
|
47302
|
+
type: "string",
|
|
47303
|
+
description: "The search query string. Be specific for better results."
|
|
47304
|
+
},
|
|
47305
|
+
numResults: {
|
|
47306
|
+
type: "number",
|
|
47307
|
+
description: "Number of results to return (default: 10, max: 100)."
|
|
47308
|
+
},
|
|
47309
|
+
country: {
|
|
47310
|
+
type: "string",
|
|
47311
|
+
description: 'Country/region code for localized results (e.g., "us", "gb", "de")'
|
|
47312
|
+
},
|
|
47313
|
+
language: {
|
|
47314
|
+
type: "string",
|
|
47315
|
+
description: 'Language code for results (e.g., "en", "fr", "de")'
|
|
47316
|
+
}
|
|
47317
|
+
},
|
|
47318
|
+
required: ["query"]
|
|
47319
|
+
}
|
|
47320
|
+
},
|
|
47321
|
+
blocking: true,
|
|
47322
|
+
timeout: 15e3
|
|
47323
|
+
},
|
|
47324
|
+
execute: async (args) => {
|
|
47325
|
+
const numResults = args.numResults || 10;
|
|
47326
|
+
searchLogger.debug({ connectorName: connector.name }, "Executing search with connector");
|
|
47327
|
+
try {
|
|
47328
|
+
const searchProvider = SearchProvider.create({ connector: connector.name });
|
|
47329
|
+
const response = await searchProvider.search(args.query, {
|
|
47330
|
+
numResults,
|
|
47331
|
+
country: args.country,
|
|
47332
|
+
language: args.language
|
|
47333
|
+
});
|
|
47334
|
+
if (response.success) {
|
|
47335
|
+
searchLogger.debug({
|
|
47336
|
+
provider: response.provider,
|
|
47337
|
+
count: response.count
|
|
47338
|
+
}, "Search completed successfully");
|
|
47339
|
+
} else {
|
|
47340
|
+
searchLogger.warn({
|
|
47341
|
+
provider: response.provider,
|
|
47342
|
+
error: response.error
|
|
47343
|
+
}, "Search failed");
|
|
47344
|
+
}
|
|
47345
|
+
return {
|
|
47346
|
+
success: response.success,
|
|
47347
|
+
query: response.query,
|
|
47348
|
+
provider: response.provider,
|
|
47349
|
+
results: response.results,
|
|
47350
|
+
count: response.count,
|
|
47351
|
+
error: response.error
|
|
47352
|
+
};
|
|
47353
|
+
} catch (error) {
|
|
47354
|
+
searchLogger.error({ error: error.message, connectorName: connector.name }, "Search threw exception");
|
|
47355
|
+
return {
|
|
47356
|
+
success: false,
|
|
47357
|
+
query: args.query,
|
|
47358
|
+
provider: connector.name,
|
|
47359
|
+
results: [],
|
|
47360
|
+
count: 0,
|
|
47361
|
+
error: error.message || "Unknown error"
|
|
47362
|
+
};
|
|
47363
|
+
}
|
|
47364
|
+
},
|
|
47365
|
+
describeCall: (args) => `"${args.query}"${args.numResults ? ` (${args.numResults} results)` : ""}`
|
|
47366
|
+
};
|
|
47367
|
+
}
|
|
47368
|
+
|
|
46828
47369
|
// src/tools/web/contentDetector.ts
|
|
46829
47370
|
function detectContentQuality(html, text, $) {
|
|
46830
47371
|
const issues = [];
|
|
@@ -46899,7 +47440,7 @@ function detectContentQuality(html, text, $) {
|
|
|
46899
47440
|
}
|
|
46900
47441
|
let suggestion;
|
|
46901
47442
|
if (requiresJS && score < 50) {
|
|
46902
|
-
suggestion = "Content quality is low. This appears to be a JavaScript-rendered site. Use
|
|
47443
|
+
suggestion = "Content quality is low. This appears to be a JavaScript-rendered site. Use a scraping service connector for better results.";
|
|
46903
47444
|
} else if (score < 30) {
|
|
46904
47445
|
suggestion = "Content extraction failed or page has errors. Check the URL and try again.";
|
|
46905
47446
|
}
|
|
@@ -47008,7 +47549,7 @@ The tool analyzes the fetched content and returns a quality score (0-100):
|
|
|
47008
47549
|
- 50-79: Moderate quality, some content extracted
|
|
47009
47550
|
- 0-49: Low quality, likely needs JavaScript or has errors
|
|
47010
47551
|
|
|
47011
|
-
If the quality score is low or requiresJS is true,
|
|
47552
|
+
If the quality score is low or requiresJS is true, consider using a scraping service connector for better results.
|
|
47012
47553
|
|
|
47013
47554
|
RETURNS:
|
|
47014
47555
|
{
|
|
@@ -47172,460 +47713,109 @@ With custom user agent:
|
|
|
47172
47713
|
}
|
|
47173
47714
|
};
|
|
47174
47715
|
|
|
47175
|
-
// src/tools/web/
|
|
47176
|
-
|
|
47177
|
-
var
|
|
47178
|
-
|
|
47179
|
-
|
|
47180
|
-
|
|
47181
|
-
|
|
47182
|
-
|
|
47183
|
-
|
|
47184
|
-
|
|
47185
|
-
}
|
|
47186
|
-
return puppeteerModule;
|
|
47187
|
-
}
|
|
47188
|
-
async function getBrowser() {
|
|
47189
|
-
if (!browserInstance) {
|
|
47190
|
-
const puppeteer = await loadPuppeteer();
|
|
47191
|
-
browserInstance = await puppeteer.launch({
|
|
47192
|
-
headless: true,
|
|
47193
|
-
args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"]
|
|
47194
|
-
});
|
|
47195
|
-
process.on("exit", async () => {
|
|
47196
|
-
if (browserInstance) {
|
|
47197
|
-
await browserInstance.close();
|
|
47198
|
-
}
|
|
47199
|
-
});
|
|
47200
|
-
}
|
|
47201
|
-
return browserInstance;
|
|
47202
|
-
}
|
|
47203
|
-
var webFetchJS = {
|
|
47204
|
-
definition: {
|
|
47205
|
-
type: "function",
|
|
47206
|
-
function: {
|
|
47207
|
-
name: "web_fetch_js",
|
|
47208
|
-
description: `Fetch and extract content from JavaScript-rendered websites using a headless browser (Puppeteer).
|
|
47209
|
-
|
|
47210
|
-
USE THIS TOOL WHEN:
|
|
47211
|
-
- The web_fetch tool returned a low quality score (<50)
|
|
47212
|
-
- The web_fetch tool suggested using JavaScript rendering
|
|
47213
|
-
- You know the website is built with React/Vue/Angular/Next.js
|
|
47214
|
-
- Content loads dynamically via JavaScript
|
|
47215
|
-
- The page requires interaction (though this tool doesn't support interaction yet)
|
|
47216
|
-
|
|
47217
|
-
HOW IT WORKS:
|
|
47218
|
-
- Launches a headless Chrome browser
|
|
47219
|
-
- Navigates to the URL
|
|
47220
|
-
- Waits for JavaScript to execute and content to load
|
|
47221
|
-
- Extracts the rendered HTML and text content
|
|
47222
|
-
- Optionally captures a screenshot
|
|
47223
|
-
|
|
47224
|
-
CAPABILITIES:
|
|
47225
|
-
- Executes all JavaScript on the page
|
|
47226
|
-
- Waits for network to be idle (all resources loaded)
|
|
47227
|
-
- Can wait for specific CSS selectors to appear
|
|
47228
|
-
- Handles React, Vue, Angular, Next.js, and other SPAs
|
|
47229
|
-
- Returns content after full JavaScript execution
|
|
47230
|
-
|
|
47231
|
-
LIMITATIONS:
|
|
47232
|
-
- Slower than web_fetch (typically 3-10 seconds vs <1 second)
|
|
47233
|
-
- Uses more system resources (runs a full browser)
|
|
47234
|
-
- May still fail on sites with aggressive bot detection
|
|
47235
|
-
- Requires puppeteer to be installed (npm install puppeteer)
|
|
47236
|
-
|
|
47237
|
-
PERFORMANCE:
|
|
47238
|
-
- First call: Slower (launches browser ~1-2s)
|
|
47239
|
-
- Subsequent calls: Faster (reuses browser instance)
|
|
47240
|
-
|
|
47241
|
-
RETURNS:
|
|
47242
|
-
{
|
|
47243
|
-
success: boolean,
|
|
47244
|
-
url: string,
|
|
47245
|
-
title: string,
|
|
47246
|
-
content: string, // Clean markdown (converted via Readability + Turndown)
|
|
47247
|
-
screenshot: string, // Base64 PNG screenshot (if requested)
|
|
47248
|
-
loadTime: number, // Time taken in milliseconds
|
|
47249
|
-
excerpt: string, // Short summary excerpt (if extracted)
|
|
47250
|
-
byline: string, // Author info (if extracted)
|
|
47251
|
-
wasTruncated: boolean, // True if content was truncated
|
|
47252
|
-
error: string // Error message if failed
|
|
47253
|
-
}
|
|
47254
|
-
|
|
47255
|
-
EXAMPLES:
|
|
47256
|
-
Basic usage:
|
|
47257
|
-
{
|
|
47258
|
-
url: "https://react-app.com/page"
|
|
47259
|
-
}
|
|
47260
|
-
|
|
47261
|
-
Wait for specific content:
|
|
47262
|
-
{
|
|
47263
|
-
url: "https://app.com/dashboard",
|
|
47264
|
-
waitForSelector: "#main-content", // Wait for this element
|
|
47265
|
-
timeout: 20000
|
|
47716
|
+
// src/tools/web/createWebScrapeTool.ts
|
|
47717
|
+
init_Logger();
|
|
47718
|
+
var scrapeLogger = exports.logger.child({ component: "webScrape" });
|
|
47719
|
+
var DEFAULT_MIN_QUALITY = 50;
|
|
47720
|
+
function stripBase64DataUris(content) {
|
|
47721
|
+
if (!content) return content;
|
|
47722
|
+
let cleaned = content.replace(/!\[[^\]]*\]\(data:[^)]+\)/g, "[image removed]");
|
|
47723
|
+
cleaned = cleaned.replace(/url\(['"]?data:[^)]+['"]?\)/gi, "url([data-uri-removed])");
|
|
47724
|
+
cleaned = cleaned.replace(/data:(?:image|font|application)\/[^;]+;base64,[A-Za-z0-9+/=]{100,}/g, "[base64-data-removed]");
|
|
47725
|
+
return cleaned;
|
|
47266
47726
|
}
|
|
47267
|
-
|
|
47268
|
-
|
|
47269
|
-
|
|
47270
|
-
|
|
47271
|
-
takeScreenshot: true
|
|
47272
|
-
}`,
|
|
47273
|
-
parameters: {
|
|
47274
|
-
type: "object",
|
|
47275
|
-
properties: {
|
|
47276
|
-
url: {
|
|
47277
|
-
type: "string",
|
|
47278
|
-
description: "The URL to fetch. Must start with http:// or https://"
|
|
47279
|
-
},
|
|
47280
|
-
waitForSelector: {
|
|
47281
|
-
type: "string",
|
|
47282
|
-
description: 'Optional CSS selector to wait for before extracting content. Example: "#main-content" or ".article-body"'
|
|
47283
|
-
},
|
|
47284
|
-
timeout: {
|
|
47285
|
-
type: "number",
|
|
47286
|
-
description: "Max wait time in milliseconds (default: 15000)"
|
|
47287
|
-
},
|
|
47288
|
-
takeScreenshot: {
|
|
47289
|
-
type: "boolean",
|
|
47290
|
-
description: "Whether to capture a screenshot of the page (default: false). Screenshot returned as base64 PNG."
|
|
47291
|
-
}
|
|
47292
|
-
},
|
|
47293
|
-
required: ["url"]
|
|
47294
|
-
}
|
|
47295
|
-
},
|
|
47296
|
-
blocking: true,
|
|
47297
|
-
timeout: 3e4
|
|
47298
|
-
// Allow extra time for browser operations
|
|
47299
|
-
},
|
|
47300
|
-
execute: async (args) => {
|
|
47301
|
-
let page = null;
|
|
47727
|
+
function createWebScrapeTool(connector) {
|
|
47728
|
+
async function tryNative(args, startTime, attemptedMethods) {
|
|
47729
|
+
attemptedMethods.push("native");
|
|
47730
|
+
scrapeLogger.debug({ url: args.url }, "Trying native fetch");
|
|
47302
47731
|
try {
|
|
47303
|
-
const
|
|
47304
|
-
|
|
47305
|
-
|
|
47306
|
-
await page.setUserAgent(
|
|
47307
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
47308
|
-
);
|
|
47309
|
-
const startTime = Date.now();
|
|
47310
|
-
await page.goto(args.url, {
|
|
47311
|
-
waitUntil: "networkidle2",
|
|
47312
|
-
// Wait until network is mostly idle
|
|
47313
|
-
timeout: args.timeout || 15e3
|
|
47732
|
+
const result = await webFetch.execute({
|
|
47733
|
+
url: args.url,
|
|
47734
|
+
timeout: args.timeout || 1e4
|
|
47314
47735
|
});
|
|
47315
|
-
|
|
47316
|
-
await page.waitForSelector(args.waitForSelector, {
|
|
47317
|
-
timeout: args.timeout || 15e3
|
|
47318
|
-
});
|
|
47319
|
-
}
|
|
47320
|
-
const html = await page.content();
|
|
47321
|
-
const browserTitle = await page.title();
|
|
47322
|
-
const loadTime = Date.now() - startTime;
|
|
47323
|
-
let screenshot;
|
|
47324
|
-
if (args.takeScreenshot) {
|
|
47325
|
-
const buffer = await page.screenshot({
|
|
47326
|
-
type: "png",
|
|
47327
|
-
fullPage: false
|
|
47328
|
-
// Just viewport
|
|
47329
|
-
});
|
|
47330
|
-
screenshot = buffer.toString("base64");
|
|
47331
|
-
}
|
|
47332
|
-
await page.close();
|
|
47333
|
-
const mdResult = await htmlToMarkdown(html, args.url);
|
|
47334
|
-
const title = browserTitle || mdResult.title || "Untitled";
|
|
47736
|
+
const cleanContent = stripBase64DataUris(result.content);
|
|
47335
47737
|
return {
|
|
47336
|
-
success:
|
|
47738
|
+
success: result.success,
|
|
47337
47739
|
url: args.url,
|
|
47338
|
-
|
|
47339
|
-
|
|
47340
|
-
|
|
47341
|
-
|
|
47342
|
-
|
|
47343
|
-
|
|
47344
|
-
|
|
47345
|
-
|
|
47740
|
+
finalUrl: args.url,
|
|
47741
|
+
method: "native",
|
|
47742
|
+
title: result.title,
|
|
47743
|
+
content: cleanContent,
|
|
47744
|
+
qualityScore: result.qualityScore,
|
|
47745
|
+
durationMs: Date.now() - startTime,
|
|
47746
|
+
attemptedMethods,
|
|
47747
|
+
error: result.error
|
|
47346
47748
|
};
|
|
47347
47749
|
} catch (error) {
|
|
47348
|
-
if (page) {
|
|
47349
|
-
try {
|
|
47350
|
-
await page.close();
|
|
47351
|
-
} catch {
|
|
47352
|
-
}
|
|
47353
|
-
}
|
|
47354
|
-
if (error.message === "Puppeteer not installed") {
|
|
47355
|
-
return {
|
|
47356
|
-
success: false,
|
|
47357
|
-
url: args.url,
|
|
47358
|
-
title: "",
|
|
47359
|
-
content: "",
|
|
47360
|
-
loadTime: 0,
|
|
47361
|
-
error: "Puppeteer is not installed",
|
|
47362
|
-
suggestion: "Install Puppeteer with: npm install puppeteer (note: downloads ~50MB Chrome binary)"
|
|
47363
|
-
};
|
|
47364
|
-
}
|
|
47365
47750
|
return {
|
|
47366
47751
|
success: false,
|
|
47367
47752
|
url: args.url,
|
|
47753
|
+
method: "native",
|
|
47368
47754
|
title: "",
|
|
47369
47755
|
content: "",
|
|
47370
|
-
|
|
47756
|
+
durationMs: Date.now() - startTime,
|
|
47757
|
+
attemptedMethods,
|
|
47371
47758
|
error: error.message
|
|
47372
47759
|
};
|
|
47373
47760
|
}
|
|
47374
47761
|
}
|
|
47375
|
-
|
|
47376
|
-
|
|
47377
|
-
|
|
47378
|
-
|
|
47379
|
-
|
|
47380
|
-
|
|
47381
|
-
|
|
47382
|
-
|
|
47383
|
-
|
|
47384
|
-
|
|
47385
|
-
|
|
47386
|
-
|
|
47387
|
-
|
|
47388
|
-
|
|
47389
|
-
|
|
47390
|
-
|
|
47391
|
-
|
|
47392
|
-
|
|
47393
|
-
|
|
47394
|
-
|
|
47395
|
-
|
|
47396
|
-
|
|
47397
|
-
|
|
47398
|
-
|
|
47399
|
-
|
|
47400
|
-
|
|
47401
|
-
|
|
47402
|
-
|
|
47403
|
-
|
|
47404
|
-
|
|
47405
|
-
|
|
47406
|
-
|
|
47407
|
-
|
|
47408
|
-
|
|
47409
|
-
|
|
47410
|
-
|
|
47411
|
-
|
|
47412
|
-
|
|
47413
|
-
|
|
47414
|
-
|
|
47415
|
-
|
|
47416
|
-
|
|
47417
|
-
|
|
47418
|
-
|
|
47419
|
-
|
|
47420
|
-
const data = await response.json();
|
|
47421
|
-
if (!data.web?.results || !Array.isArray(data.web.results)) {
|
|
47422
|
-
throw new Error("Invalid response from Brave API");
|
|
47423
|
-
}
|
|
47424
|
-
return data.web.results.slice(0, numResults).map((result, index) => ({
|
|
47425
|
-
title: result.title || "Untitled",
|
|
47426
|
-
url: result.url || "",
|
|
47427
|
-
snippet: result.description || "",
|
|
47428
|
-
position: index + 1
|
|
47429
|
-
}));
|
|
47430
|
-
}
|
|
47431
|
-
|
|
47432
|
-
// src/tools/web/searchProviders/tavily.ts
|
|
47433
|
-
async function searchWithTavily(query, numResults, apiKey) {
|
|
47434
|
-
const response = await fetch("https://api.tavily.com/search", {
|
|
47435
|
-
method: "POST",
|
|
47436
|
-
headers: {
|
|
47437
|
-
"Content-Type": "application/json"
|
|
47438
|
-
},
|
|
47439
|
-
body: JSON.stringify({
|
|
47440
|
-
api_key: apiKey,
|
|
47441
|
-
query,
|
|
47442
|
-
max_results: numResults,
|
|
47443
|
-
search_depth: "basic",
|
|
47444
|
-
// 'basic' or 'advanced'
|
|
47445
|
-
include_answer: false,
|
|
47446
|
-
include_raw_content: false
|
|
47447
|
-
})
|
|
47448
|
-
});
|
|
47449
|
-
if (!response.ok) {
|
|
47450
|
-
throw new Error(`Tavily API error: ${response.status} ${response.statusText}`);
|
|
47451
|
-
}
|
|
47452
|
-
const data = await response.json();
|
|
47453
|
-
if (!data.results || !Array.isArray(data.results)) {
|
|
47454
|
-
throw new Error("Invalid response from Tavily API");
|
|
47455
|
-
}
|
|
47456
|
-
return data.results.slice(0, numResults).map((result, index) => ({
|
|
47457
|
-
title: result.title || "Untitled",
|
|
47458
|
-
url: result.url || "",
|
|
47459
|
-
snippet: result.content || "",
|
|
47460
|
-
position: index + 1
|
|
47461
|
-
}));
|
|
47462
|
-
}
|
|
47463
|
-
|
|
47464
|
-
// src/tools/web/webSearch.ts
|
|
47465
|
-
var searchLogger = exports.logger.child({ component: "webSearch" });
|
|
47466
|
-
var SEARCH_SERVICE_TYPES = ["serper", "brave-search", "tavily", "rapidapi-search"];
|
|
47467
|
-
var webSearch = {
|
|
47468
|
-
definition: {
|
|
47469
|
-
type: "function",
|
|
47470
|
-
function: {
|
|
47471
|
-
name: "web_search",
|
|
47472
|
-
description: `Search the web and get relevant results with snippets.
|
|
47473
|
-
|
|
47474
|
-
RETURNS:
|
|
47475
|
-
An array of search results, each containing:
|
|
47476
|
-
- title: Page title
|
|
47477
|
-
- url: Direct URL to the page
|
|
47478
|
-
- snippet: Short description/excerpt from the page
|
|
47479
|
-
- position: Search ranking position (1, 2, 3...)
|
|
47480
|
-
|
|
47481
|
-
USE CASES:
|
|
47482
|
-
- Find current information on any topic
|
|
47483
|
-
- Research multiple sources
|
|
47484
|
-
- Discover relevant websites
|
|
47485
|
-
- Find URLs to fetch with web_fetch tool
|
|
47486
|
-
|
|
47487
|
-
WORKFLOW PATTERN:
|
|
47488
|
-
1. Use web_search to find relevant URLs
|
|
47489
|
-
2. Use web_fetch to get full content from top results
|
|
47490
|
-
3. Process and summarize the information
|
|
47491
|
-
|
|
47492
|
-
EXAMPLE:
|
|
47493
|
-
{
|
|
47494
|
-
"query": "latest AI developments 2026",
|
|
47495
|
-
"numResults": 5
|
|
47496
|
-
}`,
|
|
47497
|
-
parameters: {
|
|
47498
|
-
type: "object",
|
|
47499
|
-
properties: {
|
|
47500
|
-
query: {
|
|
47501
|
-
type: "string",
|
|
47502
|
-
description: "The search query string. Be specific for better results."
|
|
47503
|
-
},
|
|
47504
|
-
numResults: {
|
|
47505
|
-
type: "number",
|
|
47506
|
-
description: "Number of results to return (default: 10, max: 100)."
|
|
47507
|
-
},
|
|
47508
|
-
country: {
|
|
47509
|
-
type: "string",
|
|
47510
|
-
description: 'Country/region code for localized results (e.g., "us", "gb", "de")'
|
|
47511
|
-
},
|
|
47512
|
-
language: {
|
|
47513
|
-
type: "string",
|
|
47514
|
-
description: 'Language code for results (e.g., "en", "fr", "de")'
|
|
47515
|
-
}
|
|
47516
|
-
},
|
|
47517
|
-
required: ["query"]
|
|
47518
|
-
}
|
|
47519
|
-
},
|
|
47520
|
-
blocking: true,
|
|
47521
|
-
timeout: 15e3
|
|
47522
|
-
},
|
|
47523
|
-
execute: async (args) => {
|
|
47524
|
-
const numResults = args.numResults || 10;
|
|
47525
|
-
const connector = findConnectorByServiceTypes(SEARCH_SERVICE_TYPES);
|
|
47526
|
-
if (connector) {
|
|
47527
|
-
return await executeWithConnector(connector.name, args, numResults);
|
|
47528
|
-
}
|
|
47529
|
-
return await executeWithEnvVar(args, numResults);
|
|
47530
|
-
},
|
|
47531
|
-
describeCall: (args) => `"${args.query}"${args.numResults ? ` (${args.numResults} results)` : ""}`
|
|
47532
|
-
};
|
|
47533
|
-
async function executeWithConnector(connectorName, args, numResults) {
|
|
47534
|
-
searchLogger.debug({ connectorName }, "Executing search with connector");
|
|
47535
|
-
try {
|
|
47536
|
-
const searchProvider = SearchProvider.create({ connector: connectorName });
|
|
47537
|
-
const response = await searchProvider.search(args.query, {
|
|
47538
|
-
numResults,
|
|
47539
|
-
country: args.country,
|
|
47540
|
-
language: args.language
|
|
47541
|
-
});
|
|
47542
|
-
if (response.success) {
|
|
47543
|
-
searchLogger.debug({
|
|
47544
|
-
provider: response.provider,
|
|
47545
|
-
count: response.count
|
|
47546
|
-
}, "Search completed successfully");
|
|
47547
|
-
} else {
|
|
47548
|
-
searchLogger.warn({
|
|
47549
|
-
provider: response.provider,
|
|
47550
|
-
error: response.error
|
|
47551
|
-
}, "Search failed");
|
|
47552
|
-
}
|
|
47553
|
-
return {
|
|
47554
|
-
success: response.success,
|
|
47555
|
-
query: response.query,
|
|
47556
|
-
provider: response.provider,
|
|
47557
|
-
results: response.results,
|
|
47558
|
-
count: response.count,
|
|
47559
|
-
error: response.error
|
|
47560
|
-
};
|
|
47561
|
-
} catch (error) {
|
|
47562
|
-
searchLogger.error({ error: error.message, connectorName }, "Search threw exception");
|
|
47563
|
-
return {
|
|
47564
|
-
success: false,
|
|
47565
|
-
query: args.query,
|
|
47566
|
-
provider: connectorName,
|
|
47567
|
-
results: [],
|
|
47568
|
-
count: 0,
|
|
47569
|
-
error: error.message || "Unknown error"
|
|
47570
|
-
};
|
|
47571
|
-
}
|
|
47572
|
-
}
|
|
47573
|
-
async function executeWithEnvVar(args, numResults) {
|
|
47574
|
-
const providers = [
|
|
47575
|
-
{ name: "serper", key: process.env.SERPER_API_KEY, fn: searchWithSerper },
|
|
47576
|
-
{ name: "brave", key: process.env.BRAVE_API_KEY, fn: searchWithBrave },
|
|
47577
|
-
{ name: "tavily", key: process.env.TAVILY_API_KEY, fn: searchWithTavily }
|
|
47578
|
-
];
|
|
47579
|
-
for (const provider of providers) {
|
|
47580
|
-
if (provider.key) {
|
|
47581
|
-
searchLogger.debug({ provider: provider.name }, "Using environment variable fallback");
|
|
47582
|
-
try {
|
|
47583
|
-
const results = await provider.fn(args.query, numResults, provider.key);
|
|
47584
|
-
return {
|
|
47585
|
-
success: true,
|
|
47586
|
-
query: args.query,
|
|
47587
|
-
provider: provider.name,
|
|
47588
|
-
results,
|
|
47589
|
-
count: results.length
|
|
47590
|
-
};
|
|
47591
|
-
} catch (error) {
|
|
47592
|
-
searchLogger.warn({ provider: provider.name, error: error.message }, "Provider failed, trying next");
|
|
47593
|
-
}
|
|
47762
|
+
async function tryAPI(args, startTime, attemptedMethods) {
|
|
47763
|
+
attemptedMethods.push(`api:${connector.name}`);
|
|
47764
|
+
scrapeLogger.debug({ url: args.url, connectorName: connector.name }, "Trying external API");
|
|
47765
|
+
try {
|
|
47766
|
+
const provider = ScrapeProvider.create({ connector: connector.name });
|
|
47767
|
+
const options = {
|
|
47768
|
+
timeout: args.timeout,
|
|
47769
|
+
waitForSelector: args.waitForSelector,
|
|
47770
|
+
includeHtml: args.includeHtml,
|
|
47771
|
+
includeMarkdown: args.includeMarkdown,
|
|
47772
|
+
includeLinks: args.includeLinks
|
|
47773
|
+
};
|
|
47774
|
+
const result = await provider.scrape(args.url, options);
|
|
47775
|
+
const rawContent = result.result?.content || "";
|
|
47776
|
+
const rawMarkdown = result.result?.markdown;
|
|
47777
|
+
const cleanContent = stripBase64DataUris(rawContent);
|
|
47778
|
+
const cleanMarkdown = rawMarkdown ? stripBase64DataUris(rawMarkdown) : void 0;
|
|
47779
|
+
const isDuplicate = !!cleanMarkdown && cleanContent === cleanMarkdown;
|
|
47780
|
+
return {
|
|
47781
|
+
success: result.success,
|
|
47782
|
+
url: args.url,
|
|
47783
|
+
finalUrl: result.finalUrl,
|
|
47784
|
+
method: result.provider,
|
|
47785
|
+
title: result.result?.title || "",
|
|
47786
|
+
content: cleanContent,
|
|
47787
|
+
html: result.result?.html,
|
|
47788
|
+
markdown: isDuplicate ? void 0 : cleanMarkdown,
|
|
47789
|
+
metadata: result.result?.metadata,
|
|
47790
|
+
links: result.result?.links,
|
|
47791
|
+
qualityScore: result.success ? 90 : 0,
|
|
47792
|
+
durationMs: Date.now() - startTime,
|
|
47793
|
+
attemptedMethods,
|
|
47794
|
+
error: result.error
|
|
47795
|
+
};
|
|
47796
|
+
} catch (error) {
|
|
47797
|
+
return {
|
|
47798
|
+
success: false,
|
|
47799
|
+
url: args.url,
|
|
47800
|
+
method: "api",
|
|
47801
|
+
title: "",
|
|
47802
|
+
content: "",
|
|
47803
|
+
durationMs: Date.now() - startTime,
|
|
47804
|
+
attemptedMethods,
|
|
47805
|
+
error: error.message
|
|
47806
|
+
};
|
|
47594
47807
|
}
|
|
47595
47808
|
}
|
|
47596
47809
|
return {
|
|
47597
|
-
|
|
47598
|
-
|
|
47599
|
-
|
|
47600
|
-
|
|
47601
|
-
|
|
47602
|
-
error: "No search provider configured. Set up a search connector (serper, brave-search, tavily) or set SERPER_API_KEY, BRAVE_API_KEY, or TAVILY_API_KEY environment variable."
|
|
47603
|
-
};
|
|
47604
|
-
}
|
|
47605
|
-
|
|
47606
|
-
// src/tools/web/webScrape.ts
|
|
47607
|
-
init_Logger();
|
|
47608
|
-
var scrapeLogger = exports.logger.child({ component: "webScrape" });
|
|
47609
|
-
function stripBase64DataUris(content) {
|
|
47610
|
-
if (!content) return content;
|
|
47611
|
-
let cleaned = content.replace(/!\[[^\]]*\]\(data:[^)]+\)/g, "[image removed]");
|
|
47612
|
-
cleaned = cleaned.replace(/url\(['"]?data:[^)]+['"]?\)/gi, "url([data-uri-removed])");
|
|
47613
|
-
cleaned = cleaned.replace(/data:(?:image|font|application)\/[^;]+;base64,[A-Za-z0-9+/=]{100,}/g, "[base64-data-removed]");
|
|
47614
|
-
return cleaned;
|
|
47615
|
-
}
|
|
47616
|
-
var SCRAPE_SERVICE_TYPES = ["zenrows", "jina-reader", "firecrawl", "scrapingbee"];
|
|
47617
|
-
var DEFAULT_MIN_QUALITY = 50;
|
|
47618
|
-
var webScrape = {
|
|
47619
|
-
definition: {
|
|
47620
|
-
type: "function",
|
|
47621
|
-
function: {
|
|
47622
|
-
name: "web_scrape",
|
|
47623
|
-
description: `Scrape any URL with automatic fallback - guaranteed to work on most sites.
|
|
47810
|
+
definition: {
|
|
47811
|
+
type: "function",
|
|
47812
|
+
function: {
|
|
47813
|
+
name: "web_scrape",
|
|
47814
|
+
description: `Scrape any URL with automatic fallback - guaranteed to work on most sites.
|
|
47624
47815
|
|
|
47625
47816
|
Automatically tries multiple methods in sequence:
|
|
47626
47817
|
1. Native fetch - Fast (~1s), works for blogs/docs/articles
|
|
47627
|
-
2.
|
|
47628
|
-
3. External API - Handles bot protection, CAPTCHAs (if configured)
|
|
47818
|
+
2. External API - Handles bot protection, CAPTCHAs, SPAs (if configured)
|
|
47629
47819
|
|
|
47630
47820
|
RETURNS:
|
|
47631
47821
|
{
|
|
@@ -47660,46 +47850,64 @@ For JS-heavy sites:
|
|
|
47660
47850
|
"url": "https://spa-app.com",
|
|
47661
47851
|
"waitForSelector": ".main-content"
|
|
47662
47852
|
}`,
|
|
47663
|
-
|
|
47664
|
-
|
|
47665
|
-
|
|
47666
|
-
|
|
47667
|
-
|
|
47668
|
-
|
|
47669
|
-
|
|
47670
|
-
|
|
47671
|
-
|
|
47672
|
-
|
|
47673
|
-
|
|
47674
|
-
|
|
47675
|
-
|
|
47676
|
-
|
|
47677
|
-
|
|
47678
|
-
|
|
47679
|
-
|
|
47680
|
-
|
|
47681
|
-
|
|
47682
|
-
|
|
47683
|
-
|
|
47684
|
-
|
|
47853
|
+
parameters: {
|
|
47854
|
+
type: "object",
|
|
47855
|
+
properties: {
|
|
47856
|
+
url: {
|
|
47857
|
+
type: "string",
|
|
47858
|
+
description: "URL to scrape. Must start with http:// or https://"
|
|
47859
|
+
},
|
|
47860
|
+
timeout: {
|
|
47861
|
+
type: "number",
|
|
47862
|
+
description: "Timeout in milliseconds (default: 30000)"
|
|
47863
|
+
},
|
|
47864
|
+
includeHtml: {
|
|
47865
|
+
type: "boolean",
|
|
47866
|
+
description: "Include raw HTML in response (default: false)"
|
|
47867
|
+
},
|
|
47868
|
+
includeMarkdown: {
|
|
47869
|
+
type: "boolean",
|
|
47870
|
+
description: "Include markdown conversion (default: false)"
|
|
47871
|
+
},
|
|
47872
|
+
includeLinks: {
|
|
47873
|
+
type: "boolean",
|
|
47874
|
+
description: "Extract and include links (default: false)"
|
|
47875
|
+
},
|
|
47876
|
+
waitForSelector: {
|
|
47877
|
+
type: "string",
|
|
47878
|
+
description: "CSS selector to wait for before scraping (for JS-heavy sites)"
|
|
47879
|
+
}
|
|
47685
47880
|
},
|
|
47686
|
-
|
|
47687
|
-
|
|
47688
|
-
|
|
47689
|
-
|
|
47690
|
-
|
|
47691
|
-
required: ["url"]
|
|
47692
|
-
}
|
|
47881
|
+
required: ["url"]
|
|
47882
|
+
}
|
|
47883
|
+
},
|
|
47884
|
+
blocking: true,
|
|
47885
|
+
timeout: 6e4
|
|
47693
47886
|
},
|
|
47694
|
-
|
|
47695
|
-
|
|
47696
|
-
|
|
47697
|
-
|
|
47698
|
-
|
|
47699
|
-
|
|
47700
|
-
|
|
47701
|
-
|
|
47702
|
-
|
|
47887
|
+
execute: async (args) => {
|
|
47888
|
+
const startTime = Date.now();
|
|
47889
|
+
const attemptedMethods = [];
|
|
47890
|
+
try {
|
|
47891
|
+
new URL(args.url);
|
|
47892
|
+
} catch {
|
|
47893
|
+
return {
|
|
47894
|
+
success: false,
|
|
47895
|
+
url: args.url,
|
|
47896
|
+
method: "none",
|
|
47897
|
+
title: "",
|
|
47898
|
+
content: "",
|
|
47899
|
+
durationMs: Date.now() - startTime,
|
|
47900
|
+
attemptedMethods: [],
|
|
47901
|
+
error: "Invalid URL format"
|
|
47902
|
+
};
|
|
47903
|
+
}
|
|
47904
|
+
const native = await tryNative(args, startTime, attemptedMethods);
|
|
47905
|
+
if (native.success && (native.qualityScore ?? 0) >= DEFAULT_MIN_QUALITY) {
|
|
47906
|
+
return native;
|
|
47907
|
+
}
|
|
47908
|
+
const api = await tryAPI(args, startTime, attemptedMethods);
|
|
47909
|
+
if (api.success) return api;
|
|
47910
|
+
if (native.success) return native;
|
|
47703
47911
|
return {
|
|
47704
47912
|
success: false,
|
|
47705
47913
|
url: args.url,
|
|
@@ -47707,230 +47915,119 @@ For JS-heavy sites:
|
|
|
47707
47915
|
title: "",
|
|
47708
47916
|
content: "",
|
|
47709
47917
|
durationMs: Date.now() - startTime,
|
|
47710
|
-
attemptedMethods
|
|
47711
|
-
error: "
|
|
47918
|
+
attemptedMethods,
|
|
47919
|
+
error: "All scraping methods failed. Site may have bot protection."
|
|
47712
47920
|
};
|
|
47713
|
-
}
|
|
47714
|
-
|
|
47715
|
-
|
|
47716
|
-
return native;
|
|
47717
|
-
}
|
|
47718
|
-
const js = await tryJS(args, startTime, attemptedMethods);
|
|
47719
|
-
if (js.success && (js.qualityScore ?? 0) >= DEFAULT_MIN_QUALITY) {
|
|
47720
|
-
return js;
|
|
47721
|
-
}
|
|
47722
|
-
const connector = findConnectorByServiceTypes(SCRAPE_SERVICE_TYPES);
|
|
47723
|
-
if (connector) {
|
|
47724
|
-
const api = await tryAPI(connector.name, args, startTime, attemptedMethods);
|
|
47725
|
-
if (api.success) return api;
|
|
47726
|
-
}
|
|
47727
|
-
if (js.success) return js;
|
|
47728
|
-
if (native.success) return native;
|
|
47729
|
-
return {
|
|
47730
|
-
success: false,
|
|
47731
|
-
url: args.url,
|
|
47732
|
-
method: "none",
|
|
47733
|
-
title: "",
|
|
47734
|
-
content: "",
|
|
47735
|
-
durationMs: Date.now() - startTime,
|
|
47736
|
-
attemptedMethods,
|
|
47737
|
-
error: "All scraping methods failed. Site may have bot protection."
|
|
47738
|
-
};
|
|
47739
|
-
},
|
|
47740
|
-
describeCall: (args) => args.url
|
|
47741
|
-
};
|
|
47742
|
-
async function tryNative(args, startTime, attemptedMethods) {
|
|
47743
|
-
attemptedMethods.push("native");
|
|
47744
|
-
scrapeLogger.debug({ url: args.url }, "Trying native fetch");
|
|
47745
|
-
try {
|
|
47746
|
-
const result = await webFetch.execute({
|
|
47747
|
-
url: args.url,
|
|
47748
|
-
timeout: args.timeout || 1e4
|
|
47749
|
-
});
|
|
47750
|
-
const cleanContent = stripBase64DataUris(result.content);
|
|
47751
|
-
return {
|
|
47752
|
-
success: result.success,
|
|
47753
|
-
url: args.url,
|
|
47754
|
-
finalUrl: args.url,
|
|
47755
|
-
method: "native",
|
|
47756
|
-
title: result.title,
|
|
47757
|
-
content: cleanContent,
|
|
47758
|
-
// Note: raw HTML not available with native method (returns markdown instead)
|
|
47759
|
-
markdown: args.includeMarkdown ? cleanContent : void 0,
|
|
47760
|
-
qualityScore: result.qualityScore,
|
|
47761
|
-
durationMs: Date.now() - startTime,
|
|
47762
|
-
attemptedMethods,
|
|
47763
|
-
error: result.error
|
|
47764
|
-
};
|
|
47765
|
-
} catch (error) {
|
|
47766
|
-
return {
|
|
47767
|
-
success: false,
|
|
47768
|
-
url: args.url,
|
|
47769
|
-
method: "native",
|
|
47770
|
-
title: "",
|
|
47771
|
-
content: "",
|
|
47772
|
-
durationMs: Date.now() - startTime,
|
|
47773
|
-
attemptedMethods,
|
|
47774
|
-
error: error.message
|
|
47775
|
-
};
|
|
47776
|
-
}
|
|
47921
|
+
},
|
|
47922
|
+
describeCall: (args) => args.url
|
|
47923
|
+
};
|
|
47777
47924
|
}
|
|
47778
|
-
|
|
47779
|
-
|
|
47780
|
-
|
|
47781
|
-
|
|
47782
|
-
|
|
47783
|
-
|
|
47784
|
-
|
|
47785
|
-
|
|
47786
|
-
|
|
47787
|
-
const cleanContent = stripBase64DataUris(result.content);
|
|
47788
|
-
return {
|
|
47789
|
-
success: result.success,
|
|
47790
|
-
url: args.url,
|
|
47791
|
-
finalUrl: args.url,
|
|
47792
|
-
method: "js",
|
|
47793
|
-
title: result.title,
|
|
47794
|
-
content: cleanContent,
|
|
47795
|
-
// Note: raw HTML not available with JS method (returns markdown instead)
|
|
47796
|
-
markdown: args.includeMarkdown ? cleanContent : void 0,
|
|
47797
|
-
qualityScore: result.success ? 80 : 0,
|
|
47798
|
-
durationMs: Date.now() - startTime,
|
|
47799
|
-
attemptedMethods,
|
|
47800
|
-
error: result.error
|
|
47801
|
-
};
|
|
47802
|
-
} catch (error) {
|
|
47803
|
-
return {
|
|
47804
|
-
success: false,
|
|
47805
|
-
url: args.url,
|
|
47806
|
-
method: "js",
|
|
47807
|
-
title: "",
|
|
47808
|
-
content: "",
|
|
47809
|
-
durationMs: Date.now() - startTime,
|
|
47810
|
-
attemptedMethods,
|
|
47811
|
-
error: error.message
|
|
47812
|
-
};
|
|
47925
|
+
|
|
47926
|
+
// src/tools/web/register.ts
|
|
47927
|
+
var SEARCH_SERVICE_TYPES = ["serper", "brave-search", "tavily", "rapidapi-search"];
|
|
47928
|
+
var SCRAPE_SERVICE_TYPES = ["zenrows", "jina-reader", "firecrawl", "scrapingbee"];
|
|
47929
|
+
function registerWebTools() {
|
|
47930
|
+
for (const st of SEARCH_SERVICE_TYPES) {
|
|
47931
|
+
ConnectorTools.registerService(st, (connector) => [
|
|
47932
|
+
createWebSearchTool(connector)
|
|
47933
|
+
]);
|
|
47813
47934
|
}
|
|
47814
|
-
|
|
47815
|
-
|
|
47816
|
-
|
|
47817
|
-
|
|
47818
|
-
try {
|
|
47819
|
-
const provider = ScrapeProvider.create({ connector: connectorName });
|
|
47820
|
-
const options = {
|
|
47821
|
-
timeout: args.timeout,
|
|
47822
|
-
waitForSelector: args.waitForSelector,
|
|
47823
|
-
includeHtml: args.includeHtml,
|
|
47824
|
-
includeMarkdown: args.includeMarkdown,
|
|
47825
|
-
includeLinks: args.includeLinks
|
|
47826
|
-
};
|
|
47827
|
-
const result = await provider.scrape(args.url, options);
|
|
47828
|
-
const cleanContent = stripBase64DataUris(result.result?.content || "");
|
|
47829
|
-
const cleanMarkdown = result.result?.markdown ? stripBase64DataUris(result.result.markdown) : void 0;
|
|
47830
|
-
return {
|
|
47831
|
-
success: result.success,
|
|
47832
|
-
url: args.url,
|
|
47833
|
-
finalUrl: result.finalUrl,
|
|
47834
|
-
method: result.provider,
|
|
47835
|
-
title: result.result?.title || "",
|
|
47836
|
-
content: cleanContent,
|
|
47837
|
-
html: result.result?.html,
|
|
47838
|
-
// Keep raw HTML as-is (only used if explicitly requested)
|
|
47839
|
-
markdown: cleanMarkdown,
|
|
47840
|
-
metadata: result.result?.metadata,
|
|
47841
|
-
links: result.result?.links,
|
|
47842
|
-
qualityScore: result.success ? 90 : 0,
|
|
47843
|
-
durationMs: Date.now() - startTime,
|
|
47844
|
-
attemptedMethods,
|
|
47845
|
-
error: result.error
|
|
47846
|
-
};
|
|
47847
|
-
} catch (error) {
|
|
47848
|
-
return {
|
|
47849
|
-
success: false,
|
|
47850
|
-
url: args.url,
|
|
47851
|
-
method: "api",
|
|
47852
|
-
title: "",
|
|
47853
|
-
content: "",
|
|
47854
|
-
durationMs: Date.now() - startTime,
|
|
47855
|
-
attemptedMethods,
|
|
47856
|
-
error: error.message
|
|
47857
|
-
};
|
|
47935
|
+
for (const st of SCRAPE_SERVICE_TYPES) {
|
|
47936
|
+
ConnectorTools.registerService(st, (connector) => [
|
|
47937
|
+
createWebScrapeTool(connector)
|
|
47938
|
+
]);
|
|
47858
47939
|
}
|
|
47859
47940
|
}
|
|
47860
47941
|
|
|
47942
|
+
// src/tools/web/index.ts
|
|
47943
|
+
registerWebTools();
|
|
47944
|
+
|
|
47861
47945
|
// src/tools/code/executeJavaScript.ts
|
|
47862
47946
|
init_Connector();
|
|
47863
|
-
|
|
47864
|
-
|
|
47865
|
-
|
|
47866
|
-
|
|
47867
|
-
|
|
47868
|
-
|
|
47869
|
-
|
|
47870
|
-
|
|
47871
|
-
}).join("\n
|
|
47872
|
-
return `
|
|
47873
|
-
|
|
47874
|
-
|
|
47875
|
-
|
|
47876
|
-
|
|
47877
|
-
|
|
47878
|
-
|
|
47947
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
47948
|
+
var DEFAULT_MAX_TIMEOUT = 3e4;
|
|
47949
|
+
function formatConnectorEntry(c) {
|
|
47950
|
+
const parts = [];
|
|
47951
|
+
const serviceOrVendor = c.serviceType ?? c.vendor ?? void 0;
|
|
47952
|
+
if (serviceOrVendor) parts.push(`Service: ${serviceOrVendor}`);
|
|
47953
|
+
if (c.config.description) parts.push(c.config.description);
|
|
47954
|
+
if (c.baseURL) parts.push(`URL: ${c.baseURL}`);
|
|
47955
|
+
const details = parts.map((p) => ` ${p}`).join("\n");
|
|
47956
|
+
return ` \u2022 "${c.name}" (${c.displayName})
|
|
47957
|
+
${details}`;
|
|
47958
|
+
}
|
|
47959
|
+
function generateDescription(context, maxTimeout) {
|
|
47960
|
+
const registry = context?.connectorRegistry ?? exports.Connector.asRegistry();
|
|
47961
|
+
const connectors = registry.listAll();
|
|
47962
|
+
const connectorList = connectors.length > 0 ? connectors.map(formatConnectorEntry).join("\n\n") : " No connectors registered.";
|
|
47963
|
+
const timeoutSec = Math.round(maxTimeout / 1e3);
|
|
47964
|
+
return `Execute JavaScript code in a secure sandbox with authenticated API access to external services.
|
|
47965
|
+
|
|
47966
|
+
Use this tool when you need to:
|
|
47967
|
+
- Call external APIs (GitHub, Slack, Stripe, etc.) using registered connectors
|
|
47968
|
+
- Process, transform, or compute data that requires programmatic logic
|
|
47969
|
+
- Chain multiple API calls or perform complex data manipulation
|
|
47970
|
+
- Do anything that plain text generation cannot accomplish
|
|
47971
|
+
|
|
47972
|
+
SANDBOX API:
|
|
47973
|
+
|
|
47974
|
+
1. authenticatedFetch(url, options, connectorName)
|
|
47975
|
+
Makes authenticated HTTP requests using the connector's credentials.
|
|
47976
|
+
The current user's identity (userId) is automatically included \u2014 no need to pass it.
|
|
47977
|
+
Auth headers are added automatically \u2014 DO NOT set Authorization header manually.
|
|
47879
47978
|
|
|
47880
47979
|
Parameters:
|
|
47881
|
-
\u2022 url: Full URL or relative
|
|
47980
|
+
\u2022 url: Full URL or path relative to the connector's base URL
|
|
47882
47981
|
- Full: "https://api.github.com/user/repos"
|
|
47883
|
-
- Relative: "/user/repos" (
|
|
47884
|
-
\u2022 options: Standard fetch options { method,
|
|
47885
|
-
|
|
47886
|
-
\u2022
|
|
47982
|
+
- Relative: "/user/repos" (resolved against connector's base URL)
|
|
47983
|
+
\u2022 options: Standard fetch options { method, headers, body }
|
|
47984
|
+
- For POST/PUT: set body to JSON.stringify(data) and headers to { 'Content-Type': 'application/json' }
|
|
47985
|
+
\u2022 connectorName: Name of a registered connector (see list below)
|
|
47887
47986
|
|
|
47888
47987
|
Returns: Promise<Response>
|
|
47889
|
-
\u2022 response.ok
|
|
47890
|
-
\u2022 response.status
|
|
47891
|
-
\u2022 response.json()
|
|
47892
|
-
\u2022 response.text()
|
|
47988
|
+
\u2022 response.ok \u2014 true if status 200-299
|
|
47989
|
+
\u2022 response.status \u2014 HTTP status code
|
|
47990
|
+
\u2022 await response.json() \u2014 parse JSON body
|
|
47991
|
+
\u2022 await response.text() \u2014 get text body
|
|
47893
47992
|
|
|
47894
|
-
|
|
47895
|
-
\u2022 Bearer tokens (GitHub, Slack, Stripe)
|
|
47896
|
-
\u2022 Bot tokens (Discord)
|
|
47897
|
-
\u2022 Basic auth (Twilio, Zendesk)
|
|
47898
|
-
\u2022 Custom headers (Shopify uses X-Shopify-Access-Token)
|
|
47993
|
+
2. fetch(url, options) \u2014 Standard fetch without authentication
|
|
47899
47994
|
|
|
47900
|
-
|
|
47901
|
-
|
|
47902
|
-
4. fetch(url, options) - Standard fetch (no auth)
|
|
47995
|
+
3. connectors.list() \u2014 Array of available connector names
|
|
47996
|
+
4. connectors.get(name) \u2014 Connector info: { displayName, description, baseURL, serviceType }
|
|
47903
47997
|
|
|
47904
|
-
|
|
47905
|
-
\u2022 input
|
|
47906
|
-
\u2022 output
|
|
47998
|
+
VARIABLES:
|
|
47999
|
+
\u2022 input \u2014 data passed via the "input" parameter (default: {})
|
|
48000
|
+
\u2022 output \u2014 SET THIS to return your result to the caller
|
|
47907
48001
|
|
|
47908
|
-
|
|
48002
|
+
GLOBALS: console.log/error/warn, JSON, Math, Date, Buffer, Promise, Array, Object, String, Number, Boolean, setTimeout, setInterval, URL, URLSearchParams, RegExp, Map, Set, Error, TextEncoder, TextDecoder
|
|
47909
48003
|
|
|
47910
48004
|
REGISTERED CONNECTORS:
|
|
47911
48005
|
${connectorList}
|
|
47912
48006
|
|
|
47913
|
-
|
|
47914
|
-
(async () => {
|
|
47915
|
-
const response = await authenticatedFetch(
|
|
47916
|
-
'/user/repos',
|
|
47917
|
-
{ method: 'GET' },
|
|
47918
|
-
'github'
|
|
47919
|
-
);
|
|
48007
|
+
EXAMPLES:
|
|
47920
48008
|
|
|
47921
|
-
|
|
47922
|
-
|
|
47923
|
-
|
|
48009
|
+
// GET request
|
|
48010
|
+
const resp = await authenticatedFetch('/user/repos', { method: 'GET' }, 'github');
|
|
48011
|
+
const repos = await resp.json();
|
|
48012
|
+
output = repos.map(r => r.full_name);
|
|
47924
48013
|
|
|
47925
|
-
|
|
47926
|
-
|
|
48014
|
+
// POST request with JSON body
|
|
48015
|
+
const resp = await authenticatedFetch('/chat.postMessage', {
|
|
48016
|
+
method: 'POST',
|
|
48017
|
+
headers: { 'Content-Type': 'application/json' },
|
|
48018
|
+
body: JSON.stringify({ channel: '#general', text: 'Hello!' })
|
|
48019
|
+
}, 'slack');
|
|
48020
|
+
output = await resp.json();
|
|
47927
48021
|
|
|
47928
|
-
|
|
47929
|
-
|
|
48022
|
+
// Data processing (no API needed)
|
|
48023
|
+
const items = input.data;
|
|
48024
|
+
output = items.filter(i => i.score > 0.8).sort((a, b) => b.score - a.score);
|
|
47930
48025
|
|
|
47931
|
-
|
|
48026
|
+
LIMITS: ${timeoutSec}s max timeout, no file system access, no require/import.`;
|
|
47932
48027
|
}
|
|
47933
|
-
function createExecuteJavaScriptTool() {
|
|
48028
|
+
function createExecuteJavaScriptTool(options) {
|
|
48029
|
+
const maxTimeout = options?.maxTimeout ?? DEFAULT_MAX_TIMEOUT;
|
|
48030
|
+
const defaultTimeout = options?.defaultTimeout ?? DEFAULT_TIMEOUT;
|
|
47934
48031
|
return {
|
|
47935
48032
|
definition: {
|
|
47936
48033
|
type: "function",
|
|
@@ -47943,32 +48040,40 @@ function createExecuteJavaScriptTool() {
|
|
|
47943
48040
|
properties: {
|
|
47944
48041
|
code: {
|
|
47945
48042
|
type: "string",
|
|
47946
|
-
description: 'JavaScript code to execute.
|
|
48043
|
+
description: 'JavaScript code to execute. Set the "output" variable with your result. Code is auto-wrapped in async IIFE \u2014 you can use await directly. For explicit async control, wrap in (async () => { ... })().'
|
|
47947
48044
|
},
|
|
47948
48045
|
input: {
|
|
47949
|
-
description: 'Optional
|
|
48046
|
+
description: 'Optional data available as the "input" variable in your code. Can be any JSON value.'
|
|
47950
48047
|
},
|
|
47951
48048
|
timeout: {
|
|
47952
48049
|
type: "number",
|
|
47953
|
-
description:
|
|
48050
|
+
description: `Execution timeout in milliseconds. Default: ${defaultTimeout}ms, max: ${maxTimeout}ms. Increase for slow API calls or multiple sequential requests.`
|
|
47954
48051
|
}
|
|
47955
48052
|
},
|
|
47956
48053
|
required: ["code"]
|
|
47957
48054
|
}
|
|
47958
48055
|
},
|
|
47959
48056
|
blocking: true,
|
|
47960
|
-
timeout:
|
|
47961
|
-
// Tool timeout
|
|
48057
|
+
timeout: maxTimeout + 5e3
|
|
48058
|
+
// Tool-level timeout slightly above max code timeout
|
|
47962
48059
|
},
|
|
47963
|
-
// Dynamic description
|
|
47964
|
-
//
|
|
47965
|
-
descriptionFactory: generateDescription,
|
|
47966
|
-
execute: async (args) => {
|
|
48060
|
+
// Dynamic description — regenerated each time tool definitions are sent to LLM.
|
|
48061
|
+
// Receives ToolContext so connector list is scoped to current userId.
|
|
48062
|
+
descriptionFactory: (context) => generateDescription(context, maxTimeout),
|
|
48063
|
+
execute: async (args, context) => {
|
|
47967
48064
|
const logs = [];
|
|
47968
48065
|
const startTime = Date.now();
|
|
47969
48066
|
try {
|
|
47970
|
-
const timeout = Math.min(args.timeout ||
|
|
47971
|
-
const
|
|
48067
|
+
const timeout = Math.min(Math.max(args.timeout || defaultTimeout, 0), maxTimeout);
|
|
48068
|
+
const registry = context?.connectorRegistry ?? exports.Connector.asRegistry();
|
|
48069
|
+
const result = await executeInVM(
|
|
48070
|
+
args.code,
|
|
48071
|
+
args.input,
|
|
48072
|
+
timeout,
|
|
48073
|
+
logs,
|
|
48074
|
+
context?.userId,
|
|
48075
|
+
registry
|
|
48076
|
+
);
|
|
47972
48077
|
return {
|
|
47973
48078
|
success: true,
|
|
47974
48079
|
result,
|
|
@@ -47988,31 +48093,36 @@ function createExecuteJavaScriptTool() {
|
|
|
47988
48093
|
};
|
|
47989
48094
|
}
|
|
47990
48095
|
var executeJavaScript = createExecuteJavaScriptTool();
|
|
47991
|
-
async function executeInVM(code, input, timeout, logs) {
|
|
48096
|
+
async function executeInVM(code, input, timeout, logs, userId, registry) {
|
|
47992
48097
|
const sandbox = {
|
|
47993
48098
|
// Input/output
|
|
47994
|
-
input: input
|
|
48099
|
+
input: input ?? {},
|
|
47995
48100
|
output: null,
|
|
47996
|
-
// Console (captured)
|
|
48101
|
+
// Console (captured) — stringify objects for readable logs
|
|
47997
48102
|
console: {
|
|
47998
|
-
log: (...args) => logs.push(args.map((a) => String(a)).join(" ")),
|
|
47999
|
-
error: (...args) => logs.push("ERROR: " + args.map((a) => String(a)).join(" ")),
|
|
48000
|
-
warn: (...args) => logs.push("WARN: " + args.map((a) => String(a)).join(" "))
|
|
48103
|
+
log: (...args) => logs.push(args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")),
|
|
48104
|
+
error: (...args) => logs.push("ERROR: " + args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")),
|
|
48105
|
+
warn: (...args) => logs.push("WARN: " + args.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" "))
|
|
48106
|
+
},
|
|
48107
|
+
// Authenticated fetch — userId auto-injected from ToolContext.
|
|
48108
|
+
// Only connectors visible in the scoped registry are accessible.
|
|
48109
|
+
authenticatedFetch: (url2, options, connectorName) => {
|
|
48110
|
+
registry.get(connectorName);
|
|
48111
|
+
return authenticatedFetch(url2, options, connectorName, userId);
|
|
48001
48112
|
},
|
|
48002
|
-
//
|
|
48003
|
-
authenticatedFetch,
|
|
48004
|
-
// Standard fetch
|
|
48113
|
+
// Standard fetch (no auth)
|
|
48005
48114
|
fetch: globalThis.fetch,
|
|
48006
|
-
// Connector info
|
|
48115
|
+
// Connector info (userId-scoped)
|
|
48007
48116
|
connectors: {
|
|
48008
|
-
list: () =>
|
|
48117
|
+
list: () => registry.list(),
|
|
48009
48118
|
get: (name) => {
|
|
48010
48119
|
try {
|
|
48011
|
-
const connector =
|
|
48120
|
+
const connector = registry.get(name);
|
|
48012
48121
|
return {
|
|
48013
48122
|
displayName: connector.displayName,
|
|
48014
48123
|
description: connector.config.description || "",
|
|
48015
|
-
baseURL: connector.baseURL
|
|
48124
|
+
baseURL: connector.baseURL,
|
|
48125
|
+
serviceType: connector.serviceType
|
|
48016
48126
|
};
|
|
48017
48127
|
} catch {
|
|
48018
48128
|
return null;
|
|
@@ -48029,14 +48139,22 @@ async function executeInVM(code, input, timeout, logs) {
|
|
|
48029
48139
|
clearTimeout,
|
|
48030
48140
|
clearInterval,
|
|
48031
48141
|
Promise,
|
|
48032
|
-
//
|
|
48142
|
+
// Built-in types
|
|
48033
48143
|
Array,
|
|
48034
48144
|
Object,
|
|
48035
48145
|
String,
|
|
48036
48146
|
Number,
|
|
48037
|
-
Boolean
|
|
48147
|
+
Boolean,
|
|
48148
|
+
RegExp,
|
|
48149
|
+
Map,
|
|
48150
|
+
Set,
|
|
48151
|
+
Error,
|
|
48152
|
+
URL,
|
|
48153
|
+
URLSearchParams,
|
|
48154
|
+
TextEncoder,
|
|
48155
|
+
TextDecoder
|
|
48038
48156
|
};
|
|
48039
|
-
const
|
|
48157
|
+
const vmContext = vm__namespace.createContext(sandbox);
|
|
48040
48158
|
const wrappedCode = code.trim().startsWith("(async") ? code : `
|
|
48041
48159
|
(async () => {
|
|
48042
48160
|
${code}
|
|
@@ -48044,75 +48162,32 @@ async function executeInVM(code, input, timeout, logs) {
|
|
|
48044
48162
|
})()
|
|
48045
48163
|
`;
|
|
48046
48164
|
const script = new vm__namespace.Script(wrappedCode);
|
|
48047
|
-
const resultPromise = script.runInContext(
|
|
48165
|
+
const resultPromise = script.runInContext(vmContext, {
|
|
48048
48166
|
timeout,
|
|
48049
48167
|
displayErrors: true
|
|
48050
48168
|
});
|
|
48051
48169
|
const result = await resultPromise;
|
|
48052
48170
|
return result !== void 0 ? result : sandbox.output;
|
|
48053
48171
|
}
|
|
48054
|
-
var MIME_TYPES = {
|
|
48055
|
-
png: "image/png",
|
|
48056
|
-
jpeg: "image/jpeg",
|
|
48057
|
-
jpg: "image/jpeg",
|
|
48058
|
-
webp: "image/webp",
|
|
48059
|
-
gif: "image/gif",
|
|
48060
|
-
mp4: "video/mp4",
|
|
48061
|
-
webm: "video/webm",
|
|
48062
|
-
mp3: "audio/mpeg",
|
|
48063
|
-
wav: "audio/wav",
|
|
48064
|
-
opus: "audio/opus",
|
|
48065
|
-
ogg: "audio/ogg",
|
|
48066
|
-
aac: "audio/aac",
|
|
48067
|
-
flac: "audio/flac",
|
|
48068
|
-
pcm: "audio/pcm"
|
|
48069
|
-
};
|
|
48070
|
-
var FileMediaOutputHandler = class {
|
|
48071
|
-
outputDir;
|
|
48072
|
-
initialized = false;
|
|
48073
|
-
constructor(outputDir) {
|
|
48074
|
-
this.outputDir = outputDir ?? path3__namespace.join(os__namespace.tmpdir(), "oneringai-media");
|
|
48075
|
-
}
|
|
48076
|
-
async save(data, metadata) {
|
|
48077
|
-
if (!this.initialized) {
|
|
48078
|
-
await fs14__namespace.mkdir(this.outputDir, { recursive: true });
|
|
48079
|
-
this.initialized = true;
|
|
48080
|
-
}
|
|
48081
|
-
const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
|
|
48082
|
-
const filePath = path3__namespace.join(this.outputDir, filename);
|
|
48083
|
-
await fs14__namespace.writeFile(filePath, data);
|
|
48084
|
-
const format = metadata.format.toLowerCase();
|
|
48085
|
-
const mimeType = MIME_TYPES[format] ?? `application/octet-stream`;
|
|
48086
|
-
return {
|
|
48087
|
-
location: filePath,
|
|
48088
|
-
mimeType,
|
|
48089
|
-
size: data.length
|
|
48090
|
-
};
|
|
48091
|
-
}
|
|
48092
|
-
generateFilename(metadata) {
|
|
48093
|
-
const timestamp = Date.now();
|
|
48094
|
-
const random2 = crypto2__namespace.randomBytes(4).toString("hex");
|
|
48095
|
-
const indexSuffix = metadata.index != null ? `_${metadata.index}` : "";
|
|
48096
|
-
return `${metadata.type}_${timestamp}_${random2}${indexSuffix}.${metadata.format}`;
|
|
48097
|
-
}
|
|
48098
|
-
};
|
|
48099
48172
|
|
|
48100
48173
|
// src/tools/multimedia/config.ts
|
|
48101
|
-
var
|
|
48102
|
-
function
|
|
48103
|
-
if (!
|
|
48104
|
-
|
|
48174
|
+
var _storage = null;
|
|
48175
|
+
function getMediaStorage() {
|
|
48176
|
+
if (!_storage) {
|
|
48177
|
+
_storage = new FileMediaStorage();
|
|
48105
48178
|
}
|
|
48106
|
-
return
|
|
48179
|
+
return _storage;
|
|
48107
48180
|
}
|
|
48108
|
-
function
|
|
48109
|
-
|
|
48181
|
+
function setMediaStorage(storage) {
|
|
48182
|
+
_storage = storage;
|
|
48110
48183
|
}
|
|
48184
|
+
var getMediaOutputHandler = getMediaStorage;
|
|
48185
|
+
var setMediaOutputHandler = setMediaStorage;
|
|
48111
48186
|
|
|
48112
48187
|
// src/tools/multimedia/imageGeneration.ts
|
|
48113
|
-
function createImageGenerationTool(connector,
|
|
48188
|
+
function createImageGenerationTool(connector, storage, userId) {
|
|
48114
48189
|
const vendor = connector.vendor;
|
|
48115
|
-
const handler =
|
|
48190
|
+
const handler = storage ?? getMediaStorage();
|
|
48116
48191
|
const vendorModels = vendor ? getImageModelsByVendor(vendor) : [];
|
|
48117
48192
|
const modelNames = vendorModels.map((m) => m.name);
|
|
48118
48193
|
const properties = {
|
|
@@ -48185,8 +48260,9 @@ function createImageGenerationTool(connector, outputHandler) {
|
|
|
48185
48260
|
}
|
|
48186
48261
|
}
|
|
48187
48262
|
},
|
|
48188
|
-
execute: async (args) => {
|
|
48263
|
+
execute: async (args, context) => {
|
|
48189
48264
|
try {
|
|
48265
|
+
const effectiveUserId = userId ?? context?.userId;
|
|
48190
48266
|
const imageGen = ImageGeneration.create({ connector });
|
|
48191
48267
|
const response = await imageGen.generate({
|
|
48192
48268
|
prompt: args.prompt,
|
|
@@ -48217,7 +48293,8 @@ function createImageGenerationTool(connector, outputHandler) {
|
|
|
48217
48293
|
format,
|
|
48218
48294
|
model: modelName,
|
|
48219
48295
|
vendor: vendor || "unknown",
|
|
48220
|
-
index: response.data.length > 1 ? i : void 0
|
|
48296
|
+
index: response.data.length > 1 ? i : void 0,
|
|
48297
|
+
userId: effectiveUserId
|
|
48221
48298
|
});
|
|
48222
48299
|
images.push({
|
|
48223
48300
|
location: result.location,
|
|
@@ -48244,9 +48321,9 @@ function createImageGenerationTool(connector, outputHandler) {
|
|
|
48244
48321
|
|
|
48245
48322
|
// src/tools/multimedia/videoGeneration.ts
|
|
48246
48323
|
var videoGenInstances = /* @__PURE__ */ new Map();
|
|
48247
|
-
function createVideoTools(connector,
|
|
48324
|
+
function createVideoTools(connector, storage, userId) {
|
|
48248
48325
|
const vendor = connector.vendor;
|
|
48249
|
-
const handler =
|
|
48326
|
+
const handler = storage ?? getMediaStorage();
|
|
48250
48327
|
const vendorModels = vendor ? getVideoModelsByVendor(vendor) : [];
|
|
48251
48328
|
const modelNames = vendorModels.map((m) => m.name);
|
|
48252
48329
|
const generateProperties = {
|
|
@@ -48310,7 +48387,7 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48310
48387
|
}
|
|
48311
48388
|
}
|
|
48312
48389
|
},
|
|
48313
|
-
execute: async (args) => {
|
|
48390
|
+
execute: async (args, _context) => {
|
|
48314
48391
|
try {
|
|
48315
48392
|
const videoGen = VideoGeneration.create({ connector });
|
|
48316
48393
|
const response = await videoGen.generate({
|
|
@@ -48359,8 +48436,9 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48359
48436
|
}
|
|
48360
48437
|
}
|
|
48361
48438
|
},
|
|
48362
|
-
execute: async (args) => {
|
|
48439
|
+
execute: async (args, context) => {
|
|
48363
48440
|
try {
|
|
48441
|
+
const effectiveUserId = userId ?? context?.userId;
|
|
48364
48442
|
let videoGen = videoGenInstances.get(args.jobId);
|
|
48365
48443
|
if (!videoGen) {
|
|
48366
48444
|
videoGen = VideoGeneration.create({ connector });
|
|
@@ -48386,7 +48464,8 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48386
48464
|
type: "video",
|
|
48387
48465
|
format,
|
|
48388
48466
|
model: modelName,
|
|
48389
|
-
vendor: vendor || "unknown"
|
|
48467
|
+
vendor: vendor || "unknown",
|
|
48468
|
+
userId: effectiveUserId
|
|
48390
48469
|
});
|
|
48391
48470
|
videoGenInstances.delete(args.jobId);
|
|
48392
48471
|
return {
|
|
@@ -48434,9 +48513,9 @@ function createVideoTools(connector, outputHandler) {
|
|
|
48434
48513
|
}
|
|
48435
48514
|
|
|
48436
48515
|
// src/tools/multimedia/textToSpeech.ts
|
|
48437
|
-
function createTextToSpeechTool(connector,
|
|
48516
|
+
function createTextToSpeechTool(connector, storage, userId) {
|
|
48438
48517
|
const vendor = connector.vendor;
|
|
48439
|
-
const handler =
|
|
48518
|
+
const handler = storage ?? getMediaStorage();
|
|
48440
48519
|
const vendorModels = vendor ? getTTSModelsByVendor(vendor) : [];
|
|
48441
48520
|
const modelNames = vendorModels.map((m) => m.name);
|
|
48442
48521
|
const properties = {
|
|
@@ -48497,8 +48576,9 @@ function createTextToSpeechTool(connector, outputHandler) {
|
|
|
48497
48576
|
}
|
|
48498
48577
|
}
|
|
48499
48578
|
},
|
|
48500
|
-
execute: async (args) => {
|
|
48579
|
+
execute: async (args, context) => {
|
|
48501
48580
|
try {
|
|
48581
|
+
const effectiveUserId = userId ?? context?.userId;
|
|
48502
48582
|
const tts = TextToSpeech.create({
|
|
48503
48583
|
connector,
|
|
48504
48584
|
model: args.model,
|
|
@@ -48512,7 +48592,8 @@ function createTextToSpeechTool(connector, outputHandler) {
|
|
|
48512
48592
|
type: "audio",
|
|
48513
48593
|
format,
|
|
48514
48594
|
model: args.model || modelNames[0] || "unknown",
|
|
48515
|
-
vendor: vendor || "unknown"
|
|
48595
|
+
vendor: vendor || "unknown",
|
|
48596
|
+
userId: effectiveUserId
|
|
48516
48597
|
});
|
|
48517
48598
|
return {
|
|
48518
48599
|
success: true,
|
|
@@ -48535,14 +48616,17 @@ function createTextToSpeechTool(connector, outputHandler) {
|
|
|
48535
48616
|
}
|
|
48536
48617
|
};
|
|
48537
48618
|
}
|
|
48538
|
-
|
|
48619
|
+
|
|
48620
|
+
// src/tools/multimedia/speechToText.ts
|
|
48621
|
+
function createSpeechToTextTool(connector, storage) {
|
|
48539
48622
|
const vendor = connector.vendor;
|
|
48623
|
+
const handler = storage ?? getMediaStorage();
|
|
48540
48624
|
const vendorModels = vendor ? getSTTModelsByVendor(vendor) : [];
|
|
48541
48625
|
const modelNames = vendorModels.map((m) => m.name);
|
|
48542
48626
|
const properties = {
|
|
48543
|
-
|
|
48627
|
+
audioSource: {
|
|
48544
48628
|
type: "string",
|
|
48545
|
-
description: "Path
|
|
48629
|
+
description: "Path or location of the audio file to transcribe (file path, storage location, etc.)"
|
|
48546
48630
|
}
|
|
48547
48631
|
};
|
|
48548
48632
|
if (modelNames.length > 0) {
|
|
@@ -48570,13 +48654,19 @@ function createSpeechToTextTool(connector) {
|
|
|
48570
48654
|
parameters: {
|
|
48571
48655
|
type: "object",
|
|
48572
48656
|
properties,
|
|
48573
|
-
required: ["
|
|
48657
|
+
required: ["audioSource"]
|
|
48574
48658
|
}
|
|
48575
48659
|
}
|
|
48576
48660
|
},
|
|
48577
|
-
execute: async (args) => {
|
|
48661
|
+
execute: async (args, _context) => {
|
|
48578
48662
|
try {
|
|
48579
|
-
const audioBuffer = await
|
|
48663
|
+
const audioBuffer = await handler.read(args.audioSource);
|
|
48664
|
+
if (!audioBuffer) {
|
|
48665
|
+
return {
|
|
48666
|
+
success: false,
|
|
48667
|
+
error: `Audio not found at: ${args.audioSource}`
|
|
48668
|
+
};
|
|
48669
|
+
}
|
|
48580
48670
|
const stt = SpeechToText.create({
|
|
48581
48671
|
connector,
|
|
48582
48672
|
model: args.model,
|
|
@@ -48598,7 +48688,7 @@ function createSpeechToTextTool(connector) {
|
|
|
48598
48688
|
};
|
|
48599
48689
|
}
|
|
48600
48690
|
},
|
|
48601
|
-
describeCall: (args) => args.
|
|
48691
|
+
describeCall: (args) => args.audioSource,
|
|
48602
48692
|
permission: {
|
|
48603
48693
|
scope: "session",
|
|
48604
48694
|
riskLevel: "low",
|
|
@@ -48613,21 +48703,22 @@ var VENDOR_CAPABILITIES = {
|
|
|
48613
48703
|
[Vendor.Google]: ["image", "video", "tts"],
|
|
48614
48704
|
[Vendor.Grok]: ["image", "video"]
|
|
48615
48705
|
};
|
|
48616
|
-
function registerMultimediaTools() {
|
|
48706
|
+
function registerMultimediaTools(storage) {
|
|
48617
48707
|
for (const [vendor, capabilities] of Object.entries(VENDOR_CAPABILITIES)) {
|
|
48618
|
-
ConnectorTools.registerService(vendor, (connector,
|
|
48708
|
+
ConnectorTools.registerService(vendor, (connector, userId) => {
|
|
48709
|
+
const handler = getMediaStorage();
|
|
48619
48710
|
const tools = [];
|
|
48620
48711
|
if (capabilities.includes("image")) {
|
|
48621
|
-
tools.push(createImageGenerationTool(connector));
|
|
48712
|
+
tools.push(createImageGenerationTool(connector, handler, userId));
|
|
48622
48713
|
}
|
|
48623
48714
|
if (capabilities.includes("video")) {
|
|
48624
|
-
tools.push(...createVideoTools(connector));
|
|
48715
|
+
tools.push(...createVideoTools(connector, handler, userId));
|
|
48625
48716
|
}
|
|
48626
48717
|
if (capabilities.includes("tts")) {
|
|
48627
|
-
tools.push(createTextToSpeechTool(connector));
|
|
48718
|
+
tools.push(createTextToSpeechTool(connector, handler, userId));
|
|
48628
48719
|
}
|
|
48629
48720
|
if (capabilities.includes("stt")) {
|
|
48630
|
-
tools.push(createSpeechToTextTool(connector));
|
|
48721
|
+
tools.push(createSpeechToTextTool(connector, handler));
|
|
48631
48722
|
}
|
|
48632
48723
|
return tools;
|
|
48633
48724
|
});
|
|
@@ -48637,6 +48728,858 @@ function registerMultimediaTools() {
|
|
|
48637
48728
|
// src/tools/multimedia/index.ts
|
|
48638
48729
|
registerMultimediaTools();
|
|
48639
48730
|
|
|
48731
|
+
// src/tools/github/types.ts
|
|
48732
|
+
function parseRepository(input) {
|
|
48733
|
+
if (!input || input.trim().length === 0) {
|
|
48734
|
+
throw new Error("Repository cannot be empty");
|
|
48735
|
+
}
|
|
48736
|
+
const trimmed = input.trim();
|
|
48737
|
+
try {
|
|
48738
|
+
const url2 = new URL(trimmed);
|
|
48739
|
+
if (url2.hostname === "github.com" || url2.hostname === "www.github.com") {
|
|
48740
|
+
const segments = url2.pathname.split("/").filter(Boolean);
|
|
48741
|
+
if (segments.length >= 2) {
|
|
48742
|
+
return { owner: segments[0], repo: segments[1].replace(/\.git$/, "") };
|
|
48743
|
+
}
|
|
48744
|
+
}
|
|
48745
|
+
} catch {
|
|
48746
|
+
}
|
|
48747
|
+
const parts = trimmed.split("/");
|
|
48748
|
+
if (parts.length === 2 && parts[0].length > 0 && parts[1].length > 0) {
|
|
48749
|
+
return { owner: parts[0], repo: parts[1] };
|
|
48750
|
+
}
|
|
48751
|
+
throw new Error(
|
|
48752
|
+
`Invalid repository format: "${input}". Expected "owner/repo" or "https://github.com/owner/repo"`
|
|
48753
|
+
);
|
|
48754
|
+
}
|
|
48755
|
+
function resolveRepository(repository, connector) {
|
|
48756
|
+
const repoStr = repository ?? connector.getOptions().defaultRepository;
|
|
48757
|
+
if (!repoStr) {
|
|
48758
|
+
return {
|
|
48759
|
+
success: false,
|
|
48760
|
+
error: 'No repository specified. Provide a "repository" parameter (e.g., "owner/repo") or configure defaultRepository on the connector.'
|
|
48761
|
+
};
|
|
48762
|
+
}
|
|
48763
|
+
try {
|
|
48764
|
+
return { success: true, repo: parseRepository(repoStr) };
|
|
48765
|
+
} catch (err) {
|
|
48766
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
48767
|
+
}
|
|
48768
|
+
}
|
|
48769
|
+
var GitHubAPIError = class extends Error {
|
|
48770
|
+
constructor(status, statusText, body) {
|
|
48771
|
+
const msg = typeof body === "object" && body !== null && "message" in body ? body.message : statusText;
|
|
48772
|
+
super(`GitHub API error ${status}: ${msg}`);
|
|
48773
|
+
this.status = status;
|
|
48774
|
+
this.statusText = statusText;
|
|
48775
|
+
this.body = body;
|
|
48776
|
+
this.name = "GitHubAPIError";
|
|
48777
|
+
}
|
|
48778
|
+
};
|
|
48779
|
+
async function githubFetch(connector, endpoint, options) {
|
|
48780
|
+
let url2 = endpoint;
|
|
48781
|
+
if (options?.queryParams && Object.keys(options.queryParams).length > 0) {
|
|
48782
|
+
const params = new URLSearchParams();
|
|
48783
|
+
for (const [key, value] of Object.entries(options.queryParams)) {
|
|
48784
|
+
params.append(key, String(value));
|
|
48785
|
+
}
|
|
48786
|
+
url2 += (url2.includes("?") ? "&" : "?") + params.toString();
|
|
48787
|
+
}
|
|
48788
|
+
const headers = {
|
|
48789
|
+
"Accept": options?.accept ?? "application/vnd.github+json",
|
|
48790
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
48791
|
+
};
|
|
48792
|
+
if (options?.body) {
|
|
48793
|
+
headers["Content-Type"] = "application/json";
|
|
48794
|
+
}
|
|
48795
|
+
const response = await connector.fetch(
|
|
48796
|
+
url2,
|
|
48797
|
+
{
|
|
48798
|
+
method: options?.method ?? "GET",
|
|
48799
|
+
headers,
|
|
48800
|
+
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
48801
|
+
},
|
|
48802
|
+
options?.userId
|
|
48803
|
+
);
|
|
48804
|
+
const text = await response.text();
|
|
48805
|
+
let data;
|
|
48806
|
+
try {
|
|
48807
|
+
data = JSON.parse(text);
|
|
48808
|
+
} catch {
|
|
48809
|
+
data = text;
|
|
48810
|
+
}
|
|
48811
|
+
if (!response.ok) {
|
|
48812
|
+
throw new GitHubAPIError(response.status, response.statusText, data);
|
|
48813
|
+
}
|
|
48814
|
+
return data;
|
|
48815
|
+
}
|
|
48816
|
+
|
|
48817
|
+
// src/tools/github/searchFiles.ts
|
|
48818
|
+
function matchGlobPattern2(pattern, filePath) {
|
|
48819
|
+
let regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, ".").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
48820
|
+
regexPattern = "^" + regexPattern + "$";
|
|
48821
|
+
try {
|
|
48822
|
+
const regex = new RegExp(regexPattern);
|
|
48823
|
+
return regex.test(filePath);
|
|
48824
|
+
} catch {
|
|
48825
|
+
return false;
|
|
48826
|
+
}
|
|
48827
|
+
}
|
|
48828
|
+
function createSearchFilesTool(connector, userId) {
|
|
48829
|
+
return {
|
|
48830
|
+
definition: {
|
|
48831
|
+
type: "function",
|
|
48832
|
+
function: {
|
|
48833
|
+
name: "search_files",
|
|
48834
|
+
description: `Search for files by name/path pattern in a GitHub repository.
|
|
48835
|
+
|
|
48836
|
+
USAGE:
|
|
48837
|
+
- Supports glob patterns like "**/*.ts", "src/**/*.tsx"
|
|
48838
|
+
- Returns matching file paths sorted alphabetically
|
|
48839
|
+
- Uses the repository's file tree for fast matching
|
|
48840
|
+
|
|
48841
|
+
PATTERN SYNTAX:
|
|
48842
|
+
- * matches any characters except /
|
|
48843
|
+
- ** matches any characters including /
|
|
48844
|
+
- ? matches a single character
|
|
48845
|
+
|
|
48846
|
+
EXAMPLES:
|
|
48847
|
+
- Find all TypeScript files: { "pattern": "**/*.ts" }
|
|
48848
|
+
- Find files in src: { "pattern": "src/**/*.{ts,tsx}" }
|
|
48849
|
+
- Find package.json: { "pattern": "**/package.json" }
|
|
48850
|
+
- Search specific branch: { "pattern": "**/*.ts", "ref": "develop" }`,
|
|
48851
|
+
parameters: {
|
|
48852
|
+
type: "object",
|
|
48853
|
+
properties: {
|
|
48854
|
+
repository: {
|
|
48855
|
+
type: "string",
|
|
48856
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
48857
|
+
},
|
|
48858
|
+
pattern: {
|
|
48859
|
+
type: "string",
|
|
48860
|
+
description: 'Glob pattern to match files (e.g., "**/*.ts", "src/**/*.tsx")'
|
|
48861
|
+
},
|
|
48862
|
+
ref: {
|
|
48863
|
+
type: "string",
|
|
48864
|
+
description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
|
|
48865
|
+
}
|
|
48866
|
+
},
|
|
48867
|
+
required: ["pattern"]
|
|
48868
|
+
}
|
|
48869
|
+
}
|
|
48870
|
+
},
|
|
48871
|
+
describeCall: (args) => {
|
|
48872
|
+
const parts = [args.pattern];
|
|
48873
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
48874
|
+
if (args.ref) parts.push(`@${args.ref}`);
|
|
48875
|
+
return parts.join(" ");
|
|
48876
|
+
},
|
|
48877
|
+
permission: {
|
|
48878
|
+
scope: "session",
|
|
48879
|
+
riskLevel: "low",
|
|
48880
|
+
approvalMessage: `Search files in a GitHub repository via ${connector.displayName}`
|
|
48881
|
+
},
|
|
48882
|
+
execute: async (args, context) => {
|
|
48883
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
48884
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
48885
|
+
if (!resolved.success) {
|
|
48886
|
+
return { success: false, error: resolved.error };
|
|
48887
|
+
}
|
|
48888
|
+
const { owner, repo } = resolved.repo;
|
|
48889
|
+
try {
|
|
48890
|
+
let ref = args.ref;
|
|
48891
|
+
if (!ref) {
|
|
48892
|
+
const repoInfo = await githubFetch(
|
|
48893
|
+
connector,
|
|
48894
|
+
`/repos/${owner}/${repo}`,
|
|
48895
|
+
{ userId: effectiveUserId }
|
|
48896
|
+
);
|
|
48897
|
+
ref = repoInfo.default_branch;
|
|
48898
|
+
}
|
|
48899
|
+
const tree = await githubFetch(
|
|
48900
|
+
connector,
|
|
48901
|
+
`/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`,
|
|
48902
|
+
{ userId: effectiveUserId }
|
|
48903
|
+
);
|
|
48904
|
+
const matching = tree.tree.filter(
|
|
48905
|
+
(entry) => entry.type === "blob" && matchGlobPattern2(args.pattern, entry.path)
|
|
48906
|
+
).map((entry) => ({
|
|
48907
|
+
path: entry.path,
|
|
48908
|
+
size: entry.size ?? 0,
|
|
48909
|
+
type: entry.type
|
|
48910
|
+
})).sort((a, b) => a.path.localeCompare(b.path));
|
|
48911
|
+
return {
|
|
48912
|
+
success: true,
|
|
48913
|
+
files: matching,
|
|
48914
|
+
count: matching.length,
|
|
48915
|
+
truncated: tree.truncated
|
|
48916
|
+
};
|
|
48917
|
+
} catch (error) {
|
|
48918
|
+
return {
|
|
48919
|
+
success: false,
|
|
48920
|
+
error: `Failed to search files: ${error instanceof Error ? error.message : String(error)}`
|
|
48921
|
+
};
|
|
48922
|
+
}
|
|
48923
|
+
}
|
|
48924
|
+
};
|
|
48925
|
+
}
|
|
48926
|
+
|
|
48927
|
+
// src/tools/github/searchCode.ts
|
|
48928
|
+
function createSearchCodeTool(connector, userId) {
|
|
48929
|
+
return {
|
|
48930
|
+
definition: {
|
|
48931
|
+
type: "function",
|
|
48932
|
+
function: {
|
|
48933
|
+
name: "search_code",
|
|
48934
|
+
description: `Search for code content across a GitHub repository.
|
|
48935
|
+
|
|
48936
|
+
USAGE:
|
|
48937
|
+
- Search by keyword, function name, class name, or any text
|
|
48938
|
+
- Filter by language, path, or file extension
|
|
48939
|
+
- Returns matching files with text fragments showing context
|
|
48940
|
+
|
|
48941
|
+
RATE LIMITS:
|
|
48942
|
+
- GitHub's code search API is limited to 30 requests per minute
|
|
48943
|
+
- Results may be incomplete for very large repositories
|
|
48944
|
+
|
|
48945
|
+
EXAMPLES:
|
|
48946
|
+
- Find function: { "query": "function handleAuth", "language": "typescript" }
|
|
48947
|
+
- Find imports: { "query": "import React", "extension": "tsx" }
|
|
48948
|
+
- Search in path: { "query": "TODO", "path": "src/utils" }
|
|
48949
|
+
- Limit results: { "query": "console.log", "limit": 10 }`,
|
|
48950
|
+
parameters: {
|
|
48951
|
+
type: "object",
|
|
48952
|
+
properties: {
|
|
48953
|
+
repository: {
|
|
48954
|
+
type: "string",
|
|
48955
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
48956
|
+
},
|
|
48957
|
+
query: {
|
|
48958
|
+
type: "string",
|
|
48959
|
+
description: "Search query \u2014 keyword, function name, or any text to find in code"
|
|
48960
|
+
},
|
|
48961
|
+
language: {
|
|
48962
|
+
type: "string",
|
|
48963
|
+
description: 'Filter by programming language (e.g., "typescript", "python", "go")'
|
|
48964
|
+
},
|
|
48965
|
+
path: {
|
|
48966
|
+
type: "string",
|
|
48967
|
+
description: 'Filter by file path prefix (e.g., "src/", "lib/utils")'
|
|
48968
|
+
},
|
|
48969
|
+
extension: {
|
|
48970
|
+
type: "string",
|
|
48971
|
+
description: 'Filter by file extension without dot (e.g., "ts", "py", "go")'
|
|
48972
|
+
},
|
|
48973
|
+
limit: {
|
|
48974
|
+
type: "number",
|
|
48975
|
+
description: "Maximum number of results (default: 30, max: 100)"
|
|
48976
|
+
}
|
|
48977
|
+
},
|
|
48978
|
+
required: ["query"]
|
|
48979
|
+
}
|
|
48980
|
+
}
|
|
48981
|
+
},
|
|
48982
|
+
describeCall: (args) => {
|
|
48983
|
+
const parts = [`"${args.query}"`];
|
|
48984
|
+
if (args.language) parts.push(`lang:${args.language}`);
|
|
48985
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
48986
|
+
return parts.join(" ");
|
|
48987
|
+
},
|
|
48988
|
+
permission: {
|
|
48989
|
+
scope: "session",
|
|
48990
|
+
riskLevel: "low",
|
|
48991
|
+
approvalMessage: `Search code in a GitHub repository via ${connector.displayName}`
|
|
48992
|
+
},
|
|
48993
|
+
execute: async (args, context) => {
|
|
48994
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
48995
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
48996
|
+
if (!resolved.success) {
|
|
48997
|
+
return { success: false, error: resolved.error };
|
|
48998
|
+
}
|
|
48999
|
+
const { owner, repo } = resolved.repo;
|
|
49000
|
+
try {
|
|
49001
|
+
const qualifiers = [`repo:${owner}/${repo}`];
|
|
49002
|
+
if (args.language) qualifiers.push(`language:${args.language}`);
|
|
49003
|
+
if (args.path) qualifiers.push(`path:${args.path}`);
|
|
49004
|
+
if (args.extension) qualifiers.push(`extension:${args.extension}`);
|
|
49005
|
+
const q = `${args.query} ${qualifiers.join(" ")}`;
|
|
49006
|
+
const perPage = Math.min(args.limit ?? 30, 100);
|
|
49007
|
+
const result = await githubFetch(
|
|
49008
|
+
connector,
|
|
49009
|
+
`/search/code`,
|
|
49010
|
+
{
|
|
49011
|
+
userId: effectiveUserId,
|
|
49012
|
+
// Request text-match fragments
|
|
49013
|
+
accept: "application/vnd.github.text-match+json",
|
|
49014
|
+
queryParams: { q, per_page: perPage }
|
|
49015
|
+
}
|
|
49016
|
+
);
|
|
49017
|
+
const matches = result.items.map((item) => ({
|
|
49018
|
+
file: item.path,
|
|
49019
|
+
fragment: item.text_matches?.[0]?.fragment
|
|
49020
|
+
}));
|
|
49021
|
+
return {
|
|
49022
|
+
success: true,
|
|
49023
|
+
matches,
|
|
49024
|
+
count: result.total_count,
|
|
49025
|
+
truncated: result.incomplete_results || result.total_count > perPage
|
|
49026
|
+
};
|
|
49027
|
+
} catch (error) {
|
|
49028
|
+
return {
|
|
49029
|
+
success: false,
|
|
49030
|
+
error: `Failed to search code: ${error instanceof Error ? error.message : String(error)}`
|
|
49031
|
+
};
|
|
49032
|
+
}
|
|
49033
|
+
}
|
|
49034
|
+
};
|
|
49035
|
+
}
|
|
49036
|
+
|
|
49037
|
+
// src/tools/github/readFile.ts
|
|
49038
|
+
function createGitHubReadFileTool(connector, userId) {
|
|
49039
|
+
return {
|
|
49040
|
+
definition: {
|
|
49041
|
+
type: "function",
|
|
49042
|
+
function: {
|
|
49043
|
+
name: "read_file",
|
|
49044
|
+
description: `Read file content from a GitHub repository.
|
|
49045
|
+
|
|
49046
|
+
USAGE:
|
|
49047
|
+
- Reads a file and returns content with line numbers
|
|
49048
|
+
- Supports line range selection with offset/limit for large files
|
|
49049
|
+
- By default reads up to 2000 lines from the beginning
|
|
49050
|
+
|
|
49051
|
+
EXAMPLES:
|
|
49052
|
+
- Read entire file: { "path": "src/index.ts" }
|
|
49053
|
+
- Read specific branch: { "path": "README.md", "ref": "develop" }
|
|
49054
|
+
- Read lines 100-200: { "path": "src/app.ts", "offset": 100, "limit": 100 }
|
|
49055
|
+
- Specific repo: { "repository": "owner/repo", "path": "package.json" }
|
|
49056
|
+
|
|
49057
|
+
NOTE: Files larger than 1MB are fetched via the Git Blob API. Very large files (>5MB) may be truncated.`,
|
|
49058
|
+
parameters: {
|
|
49059
|
+
type: "object",
|
|
49060
|
+
properties: {
|
|
49061
|
+
repository: {
|
|
49062
|
+
type: "string",
|
|
49063
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49064
|
+
},
|
|
49065
|
+
path: {
|
|
49066
|
+
type: "string",
|
|
49067
|
+
description: 'File path within the repository (e.g., "src/index.ts")'
|
|
49068
|
+
},
|
|
49069
|
+
ref: {
|
|
49070
|
+
type: "string",
|
|
49071
|
+
description: "Branch, tag, or commit SHA. Defaults to the repository's default branch."
|
|
49072
|
+
},
|
|
49073
|
+
offset: {
|
|
49074
|
+
type: "number",
|
|
49075
|
+
description: "Line number to start reading from (1-indexed). Only provide if the file is too large."
|
|
49076
|
+
},
|
|
49077
|
+
limit: {
|
|
49078
|
+
type: "number",
|
|
49079
|
+
description: "Number of lines to read (default: 2000). Only provide if the file is too large."
|
|
49080
|
+
}
|
|
49081
|
+
},
|
|
49082
|
+
required: ["path"]
|
|
49083
|
+
}
|
|
49084
|
+
}
|
|
49085
|
+
},
|
|
49086
|
+
describeCall: (args) => {
|
|
49087
|
+
const parts = [args.path];
|
|
49088
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49089
|
+
if (args.ref) parts.push(`@${args.ref}`);
|
|
49090
|
+
if (args.offset && args.limit) parts.push(`[lines ${args.offset}-${args.offset + args.limit}]`);
|
|
49091
|
+
return parts.join(" ");
|
|
49092
|
+
},
|
|
49093
|
+
permission: {
|
|
49094
|
+
scope: "session",
|
|
49095
|
+
riskLevel: "low",
|
|
49096
|
+
approvalMessage: `Read a file from a GitHub repository via ${connector.displayName}`
|
|
49097
|
+
},
|
|
49098
|
+
execute: async (args, context) => {
|
|
49099
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
49100
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49101
|
+
if (!resolved.success) {
|
|
49102
|
+
return { success: false, error: resolved.error };
|
|
49103
|
+
}
|
|
49104
|
+
const { owner, repo } = resolved.repo;
|
|
49105
|
+
try {
|
|
49106
|
+
let fileContent;
|
|
49107
|
+
let fileSha;
|
|
49108
|
+
let fileSize;
|
|
49109
|
+
const refParam = args.ref ? `?ref=${encodeURIComponent(args.ref)}` : "";
|
|
49110
|
+
const contentResp = await githubFetch(
|
|
49111
|
+
connector,
|
|
49112
|
+
`/repos/${owner}/${repo}/contents/${args.path}${refParam}`,
|
|
49113
|
+
{ userId: effectiveUserId }
|
|
49114
|
+
);
|
|
49115
|
+
if (contentResp.type !== "file") {
|
|
49116
|
+
return {
|
|
49117
|
+
success: false,
|
|
49118
|
+
error: `Path is not a file: ${args.path} (type: ${contentResp.type}). Use search_files to explore the repository.`,
|
|
49119
|
+
path: args.path
|
|
49120
|
+
};
|
|
49121
|
+
}
|
|
49122
|
+
fileSha = contentResp.sha;
|
|
49123
|
+
fileSize = contentResp.size;
|
|
49124
|
+
if (contentResp.content && contentResp.encoding === "base64") {
|
|
49125
|
+
fileContent = Buffer.from(contentResp.content, "base64").toString("utf-8");
|
|
49126
|
+
} else if (contentResp.git_url) {
|
|
49127
|
+
const blob = await githubFetch(
|
|
49128
|
+
connector,
|
|
49129
|
+
contentResp.git_url,
|
|
49130
|
+
{ userId: effectiveUserId }
|
|
49131
|
+
);
|
|
49132
|
+
fileContent = Buffer.from(blob.content, "base64").toString("utf-8");
|
|
49133
|
+
fileSize = blob.size;
|
|
49134
|
+
} else {
|
|
49135
|
+
return {
|
|
49136
|
+
success: false,
|
|
49137
|
+
error: `Cannot read file content: ${args.path} (no content or git_url in response)`,
|
|
49138
|
+
path: args.path
|
|
49139
|
+
};
|
|
49140
|
+
}
|
|
49141
|
+
const offset = args.offset ?? 1;
|
|
49142
|
+
const limit = args.limit ?? 2e3;
|
|
49143
|
+
const allLines = fileContent.split("\n");
|
|
49144
|
+
const totalLines = allLines.length;
|
|
49145
|
+
const startIndex = Math.max(0, offset - 1);
|
|
49146
|
+
const endIndex = Math.min(totalLines, startIndex + limit);
|
|
49147
|
+
const selectedLines = allLines.slice(startIndex, endIndex);
|
|
49148
|
+
const lineNumberWidth = String(endIndex).length;
|
|
49149
|
+
const formattedLines = selectedLines.map((line, i) => {
|
|
49150
|
+
const lineNum = startIndex + i + 1;
|
|
49151
|
+
const paddedNum = String(lineNum).padStart(lineNumberWidth, " ");
|
|
49152
|
+
const truncatedLine = line.length > 2e3 ? line.substring(0, 2e3) + "..." : line;
|
|
49153
|
+
return `${paddedNum} ${truncatedLine}`;
|
|
49154
|
+
});
|
|
49155
|
+
const truncated = endIndex < totalLines;
|
|
49156
|
+
const result = formattedLines.join("\n");
|
|
49157
|
+
return {
|
|
49158
|
+
success: true,
|
|
49159
|
+
content: result,
|
|
49160
|
+
path: args.path,
|
|
49161
|
+
size: fileSize,
|
|
49162
|
+
lines: totalLines,
|
|
49163
|
+
truncated,
|
|
49164
|
+
sha: fileSha
|
|
49165
|
+
};
|
|
49166
|
+
} catch (error) {
|
|
49167
|
+
return {
|
|
49168
|
+
success: false,
|
|
49169
|
+
error: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
|
|
49170
|
+
path: args.path
|
|
49171
|
+
};
|
|
49172
|
+
}
|
|
49173
|
+
}
|
|
49174
|
+
};
|
|
49175
|
+
}
|
|
49176
|
+
|
|
49177
|
+
// src/tools/github/getPR.ts
|
|
49178
|
+
function createGetPRTool(connector, userId) {
|
|
49179
|
+
return {
|
|
49180
|
+
definition: {
|
|
49181
|
+
type: "function",
|
|
49182
|
+
function: {
|
|
49183
|
+
name: "get_pr",
|
|
49184
|
+
description: `Get full details of a pull request from a GitHub repository.
|
|
49185
|
+
|
|
49186
|
+
Returns: title, description, state, author, labels, reviewers, merge status, branches, file stats, and more.
|
|
49187
|
+
|
|
49188
|
+
EXAMPLES:
|
|
49189
|
+
- Get PR: { "pull_number": 123 }
|
|
49190
|
+
- Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
|
|
49191
|
+
parameters: {
|
|
49192
|
+
type: "object",
|
|
49193
|
+
properties: {
|
|
49194
|
+
repository: {
|
|
49195
|
+
type: "string",
|
|
49196
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49197
|
+
},
|
|
49198
|
+
pull_number: {
|
|
49199
|
+
type: "number",
|
|
49200
|
+
description: "Pull request number"
|
|
49201
|
+
}
|
|
49202
|
+
},
|
|
49203
|
+
required: ["pull_number"]
|
|
49204
|
+
}
|
|
49205
|
+
}
|
|
49206
|
+
},
|
|
49207
|
+
describeCall: (args) => {
|
|
49208
|
+
const parts = [`#${args.pull_number}`];
|
|
49209
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49210
|
+
return parts.join(" ");
|
|
49211
|
+
},
|
|
49212
|
+
permission: {
|
|
49213
|
+
scope: "session",
|
|
49214
|
+
riskLevel: "low",
|
|
49215
|
+
approvalMessage: `Get pull request details from GitHub via ${connector.displayName}`
|
|
49216
|
+
},
|
|
49217
|
+
execute: async (args, context) => {
|
|
49218
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
49219
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49220
|
+
if (!resolved.success) {
|
|
49221
|
+
return { success: false, error: resolved.error };
|
|
49222
|
+
}
|
|
49223
|
+
const { owner, repo } = resolved.repo;
|
|
49224
|
+
try {
|
|
49225
|
+
const pr = await githubFetch(
|
|
49226
|
+
connector,
|
|
49227
|
+
`/repos/${owner}/${repo}/pulls/${args.pull_number}`,
|
|
49228
|
+
{ userId: effectiveUserId }
|
|
49229
|
+
);
|
|
49230
|
+
return {
|
|
49231
|
+
success: true,
|
|
49232
|
+
data: {
|
|
49233
|
+
number: pr.number,
|
|
49234
|
+
title: pr.title,
|
|
49235
|
+
body: pr.body,
|
|
49236
|
+
state: pr.state,
|
|
49237
|
+
draft: pr.draft,
|
|
49238
|
+
author: pr.user.login,
|
|
49239
|
+
labels: pr.labels.map((l) => l.name),
|
|
49240
|
+
reviewers: pr.requested_reviewers.map((r) => r.login),
|
|
49241
|
+
mergeable: pr.mergeable,
|
|
49242
|
+
head: pr.head.ref,
|
|
49243
|
+
base: pr.base.ref,
|
|
49244
|
+
url: pr.html_url,
|
|
49245
|
+
created_at: pr.created_at,
|
|
49246
|
+
updated_at: pr.updated_at,
|
|
49247
|
+
additions: pr.additions,
|
|
49248
|
+
deletions: pr.deletions,
|
|
49249
|
+
changed_files: pr.changed_files
|
|
49250
|
+
}
|
|
49251
|
+
};
|
|
49252
|
+
} catch (error) {
|
|
49253
|
+
return {
|
|
49254
|
+
success: false,
|
|
49255
|
+
error: `Failed to get PR: ${error instanceof Error ? error.message : String(error)}`
|
|
49256
|
+
};
|
|
49257
|
+
}
|
|
49258
|
+
}
|
|
49259
|
+
};
|
|
49260
|
+
}
|
|
49261
|
+
|
|
49262
|
+
// src/tools/github/prFiles.ts
|
|
49263
|
+
function createPRFilesTool(connector, userId) {
|
|
49264
|
+
return {
|
|
49265
|
+
definition: {
|
|
49266
|
+
type: "function",
|
|
49267
|
+
function: {
|
|
49268
|
+
name: "pr_files",
|
|
49269
|
+
description: `Get the files changed in a pull request with diffs.
|
|
49270
|
+
|
|
49271
|
+
Returns: filename, status (added/modified/removed/renamed), additions, deletions, and patch (diff) content for each file.
|
|
49272
|
+
|
|
49273
|
+
EXAMPLES:
|
|
49274
|
+
- Get files: { "pull_number": 123 }
|
|
49275
|
+
- Specific repo: { "repository": "owner/repo", "pull_number": 456 }
|
|
49276
|
+
|
|
49277
|
+
NOTE: Very large diffs may be truncated by GitHub. Patch content may be absent for binary files.`,
|
|
49278
|
+
parameters: {
|
|
49279
|
+
type: "object",
|
|
49280
|
+
properties: {
|
|
49281
|
+
repository: {
|
|
49282
|
+
type: "string",
|
|
49283
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49284
|
+
},
|
|
49285
|
+
pull_number: {
|
|
49286
|
+
type: "number",
|
|
49287
|
+
description: "Pull request number"
|
|
49288
|
+
}
|
|
49289
|
+
},
|
|
49290
|
+
required: ["pull_number"]
|
|
49291
|
+
}
|
|
49292
|
+
}
|
|
49293
|
+
},
|
|
49294
|
+
describeCall: (args) => {
|
|
49295
|
+
const parts = [`files for #${args.pull_number}`];
|
|
49296
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49297
|
+
return parts.join(" ");
|
|
49298
|
+
},
|
|
49299
|
+
permission: {
|
|
49300
|
+
scope: "session",
|
|
49301
|
+
riskLevel: "low",
|
|
49302
|
+
approvalMessage: `Get PR changed files from GitHub via ${connector.displayName}`
|
|
49303
|
+
},
|
|
49304
|
+
execute: async (args, context) => {
|
|
49305
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
49306
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49307
|
+
if (!resolved.success) {
|
|
49308
|
+
return { success: false, error: resolved.error };
|
|
49309
|
+
}
|
|
49310
|
+
const { owner, repo } = resolved.repo;
|
|
49311
|
+
try {
|
|
49312
|
+
const files = await githubFetch(
|
|
49313
|
+
connector,
|
|
49314
|
+
`/repos/${owner}/${repo}/pulls/${args.pull_number}/files`,
|
|
49315
|
+
{
|
|
49316
|
+
userId: effectiveUserId,
|
|
49317
|
+
queryParams: { per_page: 100 }
|
|
49318
|
+
}
|
|
49319
|
+
);
|
|
49320
|
+
return {
|
|
49321
|
+
success: true,
|
|
49322
|
+
files: files.map((f) => ({
|
|
49323
|
+
filename: f.filename,
|
|
49324
|
+
status: f.status,
|
|
49325
|
+
additions: f.additions,
|
|
49326
|
+
deletions: f.deletions,
|
|
49327
|
+
changes: f.changes,
|
|
49328
|
+
patch: f.patch
|
|
49329
|
+
})),
|
|
49330
|
+
count: files.length
|
|
49331
|
+
};
|
|
49332
|
+
} catch (error) {
|
|
49333
|
+
return {
|
|
49334
|
+
success: false,
|
|
49335
|
+
error: `Failed to get PR files: ${error instanceof Error ? error.message : String(error)}`
|
|
49336
|
+
};
|
|
49337
|
+
}
|
|
49338
|
+
}
|
|
49339
|
+
};
|
|
49340
|
+
}
|
|
49341
|
+
|
|
49342
|
+
// src/tools/github/prComments.ts
|
|
49343
|
+
function createPRCommentsTool(connector, userId) {
|
|
49344
|
+
return {
|
|
49345
|
+
definition: {
|
|
49346
|
+
type: "function",
|
|
49347
|
+
function: {
|
|
49348
|
+
name: "pr_comments",
|
|
49349
|
+
description: `Get all comments and reviews on a pull request.
|
|
49350
|
+
|
|
49351
|
+
Returns a unified list of:
|
|
49352
|
+
- **review_comment**: Line-level comments on specific code (includes file path and line number)
|
|
49353
|
+
- **review**: Full reviews (approve/request changes/comment)
|
|
49354
|
+
- **comment**: General comments on the PR (issue-level)
|
|
49355
|
+
|
|
49356
|
+
All entries are sorted by creation date (oldest first).
|
|
49357
|
+
|
|
49358
|
+
EXAMPLES:
|
|
49359
|
+
- Get comments: { "pull_number": 123 }
|
|
49360
|
+
- Specific repo: { "repository": "owner/repo", "pull_number": 456 }`,
|
|
49361
|
+
parameters: {
|
|
49362
|
+
type: "object",
|
|
49363
|
+
properties: {
|
|
49364
|
+
repository: {
|
|
49365
|
+
type: "string",
|
|
49366
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49367
|
+
},
|
|
49368
|
+
pull_number: {
|
|
49369
|
+
type: "number",
|
|
49370
|
+
description: "Pull request number"
|
|
49371
|
+
}
|
|
49372
|
+
},
|
|
49373
|
+
required: ["pull_number"]
|
|
49374
|
+
}
|
|
49375
|
+
}
|
|
49376
|
+
},
|
|
49377
|
+
describeCall: (args) => {
|
|
49378
|
+
const parts = [`comments for #${args.pull_number}`];
|
|
49379
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49380
|
+
return parts.join(" ");
|
|
49381
|
+
},
|
|
49382
|
+
permission: {
|
|
49383
|
+
scope: "session",
|
|
49384
|
+
riskLevel: "low",
|
|
49385
|
+
approvalMessage: `Get PR comments and reviews from GitHub via ${connector.displayName}`
|
|
49386
|
+
},
|
|
49387
|
+
execute: async (args, context) => {
|
|
49388
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
49389
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49390
|
+
if (!resolved.success) {
|
|
49391
|
+
return { success: false, error: resolved.error };
|
|
49392
|
+
}
|
|
49393
|
+
const { owner, repo } = resolved.repo;
|
|
49394
|
+
try {
|
|
49395
|
+
const basePath = `/repos/${owner}/${repo}`;
|
|
49396
|
+
const queryOpts = { userId: effectiveUserId, queryParams: { per_page: 100 } };
|
|
49397
|
+
const [reviewComments, reviews, issueComments] = await Promise.all([
|
|
49398
|
+
githubFetch(
|
|
49399
|
+
connector,
|
|
49400
|
+
`${basePath}/pulls/${args.pull_number}/comments`,
|
|
49401
|
+
queryOpts
|
|
49402
|
+
),
|
|
49403
|
+
githubFetch(
|
|
49404
|
+
connector,
|
|
49405
|
+
`${basePath}/pulls/${args.pull_number}/reviews`,
|
|
49406
|
+
queryOpts
|
|
49407
|
+
),
|
|
49408
|
+
githubFetch(
|
|
49409
|
+
connector,
|
|
49410
|
+
`${basePath}/issues/${args.pull_number}/comments`,
|
|
49411
|
+
queryOpts
|
|
49412
|
+
)
|
|
49413
|
+
]);
|
|
49414
|
+
const allComments = [];
|
|
49415
|
+
for (const rc of reviewComments) {
|
|
49416
|
+
allComments.push({
|
|
49417
|
+
id: rc.id,
|
|
49418
|
+
type: "review_comment",
|
|
49419
|
+
author: rc.user.login,
|
|
49420
|
+
body: rc.body,
|
|
49421
|
+
created_at: rc.created_at,
|
|
49422
|
+
path: rc.path,
|
|
49423
|
+
line: rc.line ?? rc.original_line ?? void 0
|
|
49424
|
+
});
|
|
49425
|
+
}
|
|
49426
|
+
for (const r of reviews) {
|
|
49427
|
+
if (!r.body && r.state === "APPROVED") continue;
|
|
49428
|
+
allComments.push({
|
|
49429
|
+
id: r.id,
|
|
49430
|
+
type: "review",
|
|
49431
|
+
author: r.user.login,
|
|
49432
|
+
body: r.body || `[${r.state}]`,
|
|
49433
|
+
created_at: r.submitted_at,
|
|
49434
|
+
state: r.state
|
|
49435
|
+
});
|
|
49436
|
+
}
|
|
49437
|
+
for (const ic of issueComments) {
|
|
49438
|
+
allComments.push({
|
|
49439
|
+
id: ic.id,
|
|
49440
|
+
type: "comment",
|
|
49441
|
+
author: ic.user.login,
|
|
49442
|
+
body: ic.body,
|
|
49443
|
+
created_at: ic.created_at
|
|
49444
|
+
});
|
|
49445
|
+
}
|
|
49446
|
+
allComments.sort(
|
|
49447
|
+
(a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
|
|
49448
|
+
);
|
|
49449
|
+
return {
|
|
49450
|
+
success: true,
|
|
49451
|
+
comments: allComments,
|
|
49452
|
+
count: allComments.length
|
|
49453
|
+
};
|
|
49454
|
+
} catch (error) {
|
|
49455
|
+
return {
|
|
49456
|
+
success: false,
|
|
49457
|
+
error: `Failed to get PR comments: ${error instanceof Error ? error.message : String(error)}`
|
|
49458
|
+
};
|
|
49459
|
+
}
|
|
49460
|
+
}
|
|
49461
|
+
};
|
|
49462
|
+
}
|
|
49463
|
+
|
|
49464
|
+
// src/tools/github/createPR.ts
|
|
49465
|
+
function createCreatePRTool(connector, userId) {
|
|
49466
|
+
return {
|
|
49467
|
+
definition: {
|
|
49468
|
+
type: "function",
|
|
49469
|
+
function: {
|
|
49470
|
+
name: "create_pr",
|
|
49471
|
+
description: `Create a pull request on a GitHub repository.
|
|
49472
|
+
|
|
49473
|
+
USAGE:
|
|
49474
|
+
- Specify source branch (head) and target branch (base)
|
|
49475
|
+
- Optionally create as draft
|
|
49476
|
+
|
|
49477
|
+
EXAMPLES:
|
|
49478
|
+
- Create PR: { "title": "Add feature", "head": "feature-branch", "base": "main" }
|
|
49479
|
+
- Draft PR: { "title": "WIP: Refactor", "head": "refactor", "base": "develop", "draft": true }
|
|
49480
|
+
- With body: { "title": "Fix bug #42", "body": "Fixes the login issue\\n\\n## Changes\\n- Fixed auth flow", "head": "fix/42", "base": "main" }`,
|
|
49481
|
+
parameters: {
|
|
49482
|
+
type: "object",
|
|
49483
|
+
properties: {
|
|
49484
|
+
repository: {
|
|
49485
|
+
type: "string",
|
|
49486
|
+
description: 'Repository in "owner/repo" format or full GitHub URL. Optional if connector has a default repository.'
|
|
49487
|
+
},
|
|
49488
|
+
title: {
|
|
49489
|
+
type: "string",
|
|
49490
|
+
description: "Pull request title"
|
|
49491
|
+
},
|
|
49492
|
+
body: {
|
|
49493
|
+
type: "string",
|
|
49494
|
+
description: "Pull request description/body (Markdown supported)"
|
|
49495
|
+
},
|
|
49496
|
+
head: {
|
|
49497
|
+
type: "string",
|
|
49498
|
+
description: "Source branch name (the branch with your changes)"
|
|
49499
|
+
},
|
|
49500
|
+
base: {
|
|
49501
|
+
type: "string",
|
|
49502
|
+
description: 'Target branch name (the branch you want to merge into, e.g., "main")'
|
|
49503
|
+
},
|
|
49504
|
+
draft: {
|
|
49505
|
+
type: "boolean",
|
|
49506
|
+
description: "Create as a draft pull request (default: false)"
|
|
49507
|
+
}
|
|
49508
|
+
},
|
|
49509
|
+
required: ["title", "head", "base"]
|
|
49510
|
+
}
|
|
49511
|
+
}
|
|
49512
|
+
},
|
|
49513
|
+
describeCall: (args) => {
|
|
49514
|
+
const parts = [args.title];
|
|
49515
|
+
if (args.repository) parts.push(`in ${args.repository}`);
|
|
49516
|
+
return parts.join(" ");
|
|
49517
|
+
},
|
|
49518
|
+
permission: {
|
|
49519
|
+
scope: "session",
|
|
49520
|
+
riskLevel: "medium",
|
|
49521
|
+
approvalMessage: `Create a pull request on GitHub via ${connector.displayName}`
|
|
49522
|
+
},
|
|
49523
|
+
execute: async (args, context) => {
|
|
49524
|
+
const effectiveUserId = context?.userId ?? userId;
|
|
49525
|
+
const resolved = resolveRepository(args.repository, connector);
|
|
49526
|
+
if (!resolved.success) {
|
|
49527
|
+
return { success: false, error: resolved.error };
|
|
49528
|
+
}
|
|
49529
|
+
const { owner, repo } = resolved.repo;
|
|
49530
|
+
try {
|
|
49531
|
+
const pr = await githubFetch(
|
|
49532
|
+
connector,
|
|
49533
|
+
`/repos/${owner}/${repo}/pulls`,
|
|
49534
|
+
{
|
|
49535
|
+
method: "POST",
|
|
49536
|
+
userId: effectiveUserId,
|
|
49537
|
+
body: {
|
|
49538
|
+
title: args.title,
|
|
49539
|
+
body: args.body,
|
|
49540
|
+
head: args.head,
|
|
49541
|
+
base: args.base,
|
|
49542
|
+
draft: args.draft ?? false
|
|
49543
|
+
}
|
|
49544
|
+
}
|
|
49545
|
+
);
|
|
49546
|
+
return {
|
|
49547
|
+
success: true,
|
|
49548
|
+
data: {
|
|
49549
|
+
number: pr.number,
|
|
49550
|
+
url: pr.html_url,
|
|
49551
|
+
state: pr.state,
|
|
49552
|
+
title: pr.title
|
|
49553
|
+
}
|
|
49554
|
+
};
|
|
49555
|
+
} catch (error) {
|
|
49556
|
+
return {
|
|
49557
|
+
success: false,
|
|
49558
|
+
error: `Failed to create PR: ${error instanceof Error ? error.message : String(error)}`
|
|
49559
|
+
};
|
|
49560
|
+
}
|
|
49561
|
+
}
|
|
49562
|
+
};
|
|
49563
|
+
}
|
|
49564
|
+
|
|
49565
|
+
// src/tools/github/register.ts
|
|
49566
|
+
function registerGitHubTools() {
|
|
49567
|
+
ConnectorTools.registerService("github", (connector, userId) => {
|
|
49568
|
+
return [
|
|
49569
|
+
createSearchFilesTool(connector, userId),
|
|
49570
|
+
createSearchCodeTool(connector, userId),
|
|
49571
|
+
createGitHubReadFileTool(connector, userId),
|
|
49572
|
+
createGetPRTool(connector, userId),
|
|
49573
|
+
createPRFilesTool(connector, userId),
|
|
49574
|
+
createPRCommentsTool(connector, userId),
|
|
49575
|
+
createCreatePRTool(connector, userId)
|
|
49576
|
+
];
|
|
49577
|
+
});
|
|
49578
|
+
}
|
|
49579
|
+
|
|
49580
|
+
// src/tools/github/index.ts
|
|
49581
|
+
registerGitHubTools();
|
|
49582
|
+
|
|
48640
49583
|
// src/tools/registry.generated.ts
|
|
48641
49584
|
var toolRegistry = [
|
|
48642
49585
|
{
|
|
@@ -48690,7 +49633,7 @@ var toolRegistry = [
|
|
|
48690
49633
|
displayName: "Read File",
|
|
48691
49634
|
category: "filesystem",
|
|
48692
49635
|
description: "Read content from a file on the local filesystem.",
|
|
48693
|
-
tool:
|
|
49636
|
+
tool: readFile5,
|
|
48694
49637
|
safeByDefault: true
|
|
48695
49638
|
},
|
|
48696
49639
|
{
|
|
@@ -48699,7 +49642,7 @@ var toolRegistry = [
|
|
|
48699
49642
|
displayName: "Write File",
|
|
48700
49643
|
category: "filesystem",
|
|
48701
49644
|
description: "Write content to a file on the local filesystem.",
|
|
48702
|
-
tool:
|
|
49645
|
+
tool: writeFile5,
|
|
48703
49646
|
safeByDefault: false
|
|
48704
49647
|
},
|
|
48705
49648
|
{
|
|
@@ -48728,37 +49671,6 @@ var toolRegistry = [
|
|
|
48728
49671
|
description: "Fetch and extract text content from a web page URL.",
|
|
48729
49672
|
tool: webFetch,
|
|
48730
49673
|
safeByDefault: true
|
|
48731
|
-
},
|
|
48732
|
-
{
|
|
48733
|
-
name: "web_fetch_js",
|
|
48734
|
-
exportName: "webFetchJS",
|
|
48735
|
-
displayName: "Web Fetch Js",
|
|
48736
|
-
category: "web",
|
|
48737
|
-
description: "Fetch and extract content from JavaScript-rendered websites using a headless browser (Puppeteer).",
|
|
48738
|
-
tool: webFetchJS,
|
|
48739
|
-
safeByDefault: true
|
|
48740
|
-
},
|
|
48741
|
-
{
|
|
48742
|
-
name: "web_scrape",
|
|
48743
|
-
exportName: "webScrape",
|
|
48744
|
-
displayName: "Web Scrape",
|
|
48745
|
-
category: "web",
|
|
48746
|
-
description: "Scrape any URL with automatic fallback - guaranteed to work on most sites.",
|
|
48747
|
-
tool: webScrape,
|
|
48748
|
-
safeByDefault: true,
|
|
48749
|
-
requiresConnector: true,
|
|
48750
|
-
connectorServiceTypes: ["zenrows"]
|
|
48751
|
-
},
|
|
48752
|
-
{
|
|
48753
|
-
name: "web_search",
|
|
48754
|
-
exportName: "webSearch",
|
|
48755
|
-
displayName: "Web Search",
|
|
48756
|
-
category: "web",
|
|
48757
|
-
description: "Search the web and get relevant results with snippets.",
|
|
48758
|
-
tool: webSearch,
|
|
48759
|
-
safeByDefault: true,
|
|
48760
|
-
requiresConnector: true,
|
|
48761
|
-
connectorServiceTypes: ["serper", "brave-search", "tavily", "rapidapi-websearch"]
|
|
48762
49674
|
}
|
|
48763
49675
|
];
|
|
48764
49676
|
function getAllBuiltInTools() {
|
|
@@ -48928,8 +49840,8 @@ var ToolRegistry = class {
|
|
|
48928
49840
|
|
|
48929
49841
|
// src/tools/index.ts
|
|
48930
49842
|
var developerTools = [
|
|
48931
|
-
|
|
48932
|
-
|
|
49843
|
+
readFile5,
|
|
49844
|
+
writeFile5,
|
|
48933
49845
|
editFile,
|
|
48934
49846
|
glob,
|
|
48935
49847
|
grep,
|
|
@@ -49153,7 +50065,8 @@ exports.ExternalDependencyHandler = ExternalDependencyHandler;
|
|
|
49153
50065
|
exports.FileAgentDefinitionStorage = FileAgentDefinitionStorage;
|
|
49154
50066
|
exports.FileConnectorStorage = FileConnectorStorage;
|
|
49155
50067
|
exports.FileContextStorage = FileContextStorage;
|
|
49156
|
-
exports.FileMediaOutputHandler =
|
|
50068
|
+
exports.FileMediaOutputHandler = FileMediaStorage;
|
|
50069
|
+
exports.FileMediaStorage = FileMediaStorage;
|
|
49157
50070
|
exports.FilePersistentInstructionsStorage = FilePersistentInstructionsStorage;
|
|
49158
50071
|
exports.FileStorage = FileStorage;
|
|
49159
50072
|
exports.HookManager = HookManager;
|
|
@@ -49259,11 +50172,15 @@ exports.createAgentStorage = createAgentStorage;
|
|
|
49259
50172
|
exports.createAuthenticatedFetch = createAuthenticatedFetch;
|
|
49260
50173
|
exports.createBashTool = createBashTool;
|
|
49261
50174
|
exports.createConnectorFromTemplate = createConnectorFromTemplate;
|
|
50175
|
+
exports.createCreatePRTool = createCreatePRTool;
|
|
49262
50176
|
exports.createEditFileTool = createEditFileTool;
|
|
49263
50177
|
exports.createEstimator = createEstimator;
|
|
49264
50178
|
exports.createExecuteJavaScriptTool = createExecuteJavaScriptTool;
|
|
49265
50179
|
exports.createFileAgentDefinitionStorage = createFileAgentDefinitionStorage;
|
|
49266
50180
|
exports.createFileContextStorage = createFileContextStorage;
|
|
50181
|
+
exports.createFileMediaStorage = createFileMediaStorage;
|
|
50182
|
+
exports.createGetPRTool = createGetPRTool;
|
|
50183
|
+
exports.createGitHubReadFileTool = createGitHubReadFileTool;
|
|
49267
50184
|
exports.createGlobTool = createGlobTool;
|
|
49268
50185
|
exports.createGrepTool = createGrepTool;
|
|
49269
50186
|
exports.createImageGenerationTool = createImageGenerationTool;
|
|
@@ -49271,9 +50188,13 @@ exports.createImageProvider = createImageProvider;
|
|
|
49271
50188
|
exports.createListDirectoryTool = createListDirectoryTool;
|
|
49272
50189
|
exports.createMessageWithImages = createMessageWithImages;
|
|
49273
50190
|
exports.createMetricsCollector = createMetricsCollector;
|
|
50191
|
+
exports.createPRCommentsTool = createPRCommentsTool;
|
|
50192
|
+
exports.createPRFilesTool = createPRFilesTool;
|
|
49274
50193
|
exports.createPlan = createPlan;
|
|
49275
50194
|
exports.createProvider = createProvider;
|
|
49276
50195
|
exports.createReadFileTool = createReadFileTool;
|
|
50196
|
+
exports.createSearchCodeTool = createSearchCodeTool;
|
|
50197
|
+
exports.createSearchFilesTool = createSearchFilesTool;
|
|
49277
50198
|
exports.createSpeechToTextTool = createSpeechToTextTool;
|
|
49278
50199
|
exports.createTask = createTask;
|
|
49279
50200
|
exports.createTextMessage = createTextMessage;
|
|
@@ -49313,6 +50234,7 @@ exports.getImageModelInfo = getImageModelInfo;
|
|
|
49313
50234
|
exports.getImageModelsByVendor = getImageModelsByVendor;
|
|
49314
50235
|
exports.getImageModelsWithFeature = getImageModelsWithFeature;
|
|
49315
50236
|
exports.getMediaOutputHandler = getMediaOutputHandler;
|
|
50237
|
+
exports.getMediaStorage = getMediaStorage;
|
|
49316
50238
|
exports.getModelInfo = getModelInfo;
|
|
49317
50239
|
exports.getModelsByVendor = getModelsByVendor;
|
|
49318
50240
|
exports.getNextExecutableTasks = getNextExecutableTasks;
|
|
@@ -49335,6 +50257,7 @@ exports.getToolsByCategory = getToolsByCategory;
|
|
|
49335
50257
|
exports.getToolsRequiringConnector = getToolsRequiringConnector;
|
|
49336
50258
|
exports.getVendorAuthTemplate = getVendorAuthTemplate;
|
|
49337
50259
|
exports.getVendorColor = getVendorColor;
|
|
50260
|
+
exports.getVendorDefaultBaseURL = getVendorDefaultBaseURL;
|
|
49338
50261
|
exports.getVendorInfo = getVendorInfo;
|
|
49339
50262
|
exports.getVendorLogo = getVendorLogo;
|
|
49340
50263
|
exports.getVendorLogoCdnUrl = getVendorLogoCdnUrl;
|
|
@@ -49373,15 +50296,18 @@ exports.listVendors = listVendors;
|
|
|
49373
50296
|
exports.listVendorsByAuthType = listVendorsByAuthType;
|
|
49374
50297
|
exports.listVendorsByCategory = listVendorsByCategory;
|
|
49375
50298
|
exports.listVendorsWithLogos = listVendorsWithLogos;
|
|
50299
|
+
exports.parseRepository = parseRepository;
|
|
49376
50300
|
exports.readClipboardImage = readClipboardImage;
|
|
49377
|
-
exports.readFile =
|
|
50301
|
+
exports.readFile = readFile5;
|
|
49378
50302
|
exports.registerScrapeProvider = registerScrapeProvider;
|
|
49379
50303
|
exports.resolveConnector = resolveConnector;
|
|
49380
50304
|
exports.resolveDependencies = resolveDependencies;
|
|
50305
|
+
exports.resolveRepository = resolveRepository;
|
|
49381
50306
|
exports.retryWithBackoff = retryWithBackoff;
|
|
49382
50307
|
exports.scopeEquals = scopeEquals;
|
|
49383
50308
|
exports.scopeMatches = scopeMatches;
|
|
49384
50309
|
exports.setMediaOutputHandler = setMediaOutputHandler;
|
|
50310
|
+
exports.setMediaStorage = setMediaStorage;
|
|
49385
50311
|
exports.setMetricsCollector = setMetricsCollector;
|
|
49386
50312
|
exports.simpleTokenEstimator = simpleTokenEstimator;
|
|
49387
50313
|
exports.toConnectorOptions = toConnectorOptions;
|
|
@@ -49389,6 +50315,6 @@ exports.toolRegistry = toolRegistry;
|
|
|
49389
50315
|
exports.tools = tools_exports;
|
|
49390
50316
|
exports.updateTaskStatus = updateTaskStatus;
|
|
49391
50317
|
exports.validatePath = validatePath;
|
|
49392
|
-
exports.writeFile =
|
|
50318
|
+
exports.writeFile = writeFile5;
|
|
49393
50319
|
//# sourceMappingURL=index.cjs.map
|
|
49394
50320
|
//# sourceMappingURL=index.cjs.map
|