@probelabs/probe 0.6.0-rc225 → 0.6.0-rc227
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/bin/binaries/probe-v0.6.0-rc227-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc227-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc227-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc227-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc227-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.d.ts +24 -0
- package/build/agent/ProbeAgent.js +310 -141
- package/build/agent/engines/enhanced-claude-code.js +72 -3
- package/build/agent/index.js +386 -129
- package/build/tools/analyzeAll.js +6 -1
- package/build/tools/bash.js +18 -3
- package/build/tools/edit.js +19 -10
- package/build/tools/vercel.js +17 -7
- package/build/utils/path-validation.js +148 -1
- package/cjs/agent/ProbeAgent.cjs +683 -389
- package/cjs/index.cjs +680 -389
- package/package.json +1 -1
- package/src/agent/ProbeAgent.d.ts +24 -0
- package/src/agent/ProbeAgent.js +310 -141
- package/src/agent/engines/enhanced-claude-code.js +72 -3
- package/src/tools/analyzeAll.js +6 -1
- package/src/tools/bash.js +18 -3
- package/src/tools/edit.js +19 -10
- package/src/tools/vercel.js +17 -7
- package/src/utils/path-validation.js +148 -1
- package/bin/binaries/probe-v0.6.0-rc225-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-x86_64-unknown-linux-musl.tar.gz +0 -0
package/build/agent/index.js
CHANGED
|
@@ -3288,7 +3288,26 @@ var init_error_types = __esm({
|
|
|
3288
3288
|
|
|
3289
3289
|
// src/utils/path-validation.js
|
|
3290
3290
|
import path4 from "path";
|
|
3291
|
-
import { promises as fs5 } from "fs";
|
|
3291
|
+
import { promises as fs5, realpathSync } from "fs";
|
|
3292
|
+
function safeRealpath(inputPath) {
|
|
3293
|
+
try {
|
|
3294
|
+
return realpathSync(inputPath);
|
|
3295
|
+
} catch (error) {
|
|
3296
|
+
const normalized = path4.normalize(inputPath);
|
|
3297
|
+
const parts = normalized.split(path4.sep);
|
|
3298
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
3299
|
+
const ancestorPath = parts.slice(0, i).join(path4.sep) || path4.sep;
|
|
3300
|
+
try {
|
|
3301
|
+
const resolvedAncestor = realpathSync(ancestorPath);
|
|
3302
|
+
const remainingParts = parts.slice(i);
|
|
3303
|
+
return path4.join(resolvedAncestor, ...remainingParts);
|
|
3304
|
+
} catch (ancestorError) {
|
|
3305
|
+
continue;
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
return normalized;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3292
3311
|
async function validateCwdPath(inputPath, defaultPath = process.cwd()) {
|
|
3293
3312
|
const targetPath = inputPath || defaultPath;
|
|
3294
3313
|
const normalizedPath = path4.normalize(path4.resolve(targetPath));
|
|
@@ -3321,6 +3340,53 @@ async function validateCwdPath(inputPath, defaultPath = process.cwd()) {
|
|
|
3321
3340
|
}
|
|
3322
3341
|
return normalizedPath;
|
|
3323
3342
|
}
|
|
3343
|
+
function getCommonPrefix(folders) {
|
|
3344
|
+
if (!folders || folders.length === 0) {
|
|
3345
|
+
return process.cwd();
|
|
3346
|
+
}
|
|
3347
|
+
if (folders.length === 1) {
|
|
3348
|
+
return safeRealpath(folders[0]);
|
|
3349
|
+
}
|
|
3350
|
+
const normalized = folders.map((f) => safeRealpath(f));
|
|
3351
|
+
const segments = normalized.map((f) => f.split(path4.sep));
|
|
3352
|
+
const minLen = Math.min(...segments.map((s) => s.length));
|
|
3353
|
+
const commonSegments = [];
|
|
3354
|
+
for (let i = 0; i < minLen; i++) {
|
|
3355
|
+
const segment = segments[0][i];
|
|
3356
|
+
if (segments.every((s) => s[i] === segment)) {
|
|
3357
|
+
commonSegments.push(segment);
|
|
3358
|
+
} else {
|
|
3359
|
+
break;
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
if (commonSegments.length === 0) {
|
|
3363
|
+
return normalized[0];
|
|
3364
|
+
}
|
|
3365
|
+
if (commonSegments.length === 1 && /^[a-zA-Z]:$/.test(commonSegments[0])) {
|
|
3366
|
+
return normalized[0];
|
|
3367
|
+
}
|
|
3368
|
+
if (commonSegments.length === 1 && commonSegments[0] === "") {
|
|
3369
|
+
return normalized[0];
|
|
3370
|
+
}
|
|
3371
|
+
return commonSegments.join(path4.sep);
|
|
3372
|
+
}
|
|
3373
|
+
function toRelativePath(absolutePath, workspaceRoot) {
|
|
3374
|
+
if (!absolutePath || !workspaceRoot) {
|
|
3375
|
+
return absolutePath;
|
|
3376
|
+
}
|
|
3377
|
+
let normalized = safeRealpath(absolutePath);
|
|
3378
|
+
let normalizedRoot = safeRealpath(workspaceRoot);
|
|
3379
|
+
while (normalizedRoot.length > 1 && normalizedRoot.endsWith(path4.sep)) {
|
|
3380
|
+
normalizedRoot = normalizedRoot.slice(0, -1);
|
|
3381
|
+
}
|
|
3382
|
+
if (normalized === normalizedRoot) {
|
|
3383
|
+
return ".";
|
|
3384
|
+
}
|
|
3385
|
+
if (normalized.startsWith(normalizedRoot + path4.sep)) {
|
|
3386
|
+
return path4.relative(normalizedRoot, normalized);
|
|
3387
|
+
}
|
|
3388
|
+
return absolutePath;
|
|
3389
|
+
}
|
|
3324
3390
|
var init_path_validation = __esm({
|
|
3325
3391
|
"src/utils/path-validation.js"() {
|
|
3326
3392
|
"use strict";
|
|
@@ -4515,6 +4581,7 @@ async function analyzeAll(options) {
|
|
|
4515
4581
|
sessionId,
|
|
4516
4582
|
debug = false,
|
|
4517
4583
|
cwd,
|
|
4584
|
+
workspaceRoot,
|
|
4518
4585
|
allowedFolders,
|
|
4519
4586
|
provider,
|
|
4520
4587
|
model,
|
|
@@ -4527,10 +4594,11 @@ async function analyzeAll(options) {
|
|
|
4527
4594
|
if (!question) {
|
|
4528
4595
|
throw new Error('The "question" parameter is required.');
|
|
4529
4596
|
}
|
|
4597
|
+
const effectiveWorkspaceRoot = workspaceRoot || cwd || allowedFolders?.[0] || path9;
|
|
4530
4598
|
const delegateOptions = {
|
|
4531
4599
|
debug,
|
|
4532
4600
|
sessionId,
|
|
4533
|
-
path:
|
|
4601
|
+
path: effectiveWorkspaceRoot,
|
|
4534
4602
|
allowedFolders,
|
|
4535
4603
|
provider,
|
|
4536
4604
|
model,
|
|
@@ -8747,29 +8815,33 @@ import { dirname, resolve, isAbsolute, sep } from "path";
|
|
|
8747
8815
|
import { existsSync } from "fs";
|
|
8748
8816
|
function isPathAllowed(filePath, allowedFolders) {
|
|
8749
8817
|
if (!allowedFolders || allowedFolders.length === 0) {
|
|
8750
|
-
const resolvedPath2 =
|
|
8751
|
-
const cwd =
|
|
8818
|
+
const resolvedPath2 = safeRealpath(filePath);
|
|
8819
|
+
const cwd = safeRealpath(process.cwd());
|
|
8752
8820
|
return resolvedPath2 === cwd || resolvedPath2.startsWith(cwd + sep);
|
|
8753
8821
|
}
|
|
8754
|
-
const resolvedPath =
|
|
8822
|
+
const resolvedPath = safeRealpath(filePath);
|
|
8755
8823
|
return allowedFolders.some((folder) => {
|
|
8756
|
-
const allowedPath =
|
|
8824
|
+
const allowedPath = safeRealpath(folder);
|
|
8757
8825
|
return resolvedPath === allowedPath || resolvedPath.startsWith(allowedPath + sep);
|
|
8758
8826
|
});
|
|
8759
8827
|
}
|
|
8760
8828
|
function parseFileToolOptions(options = {}) {
|
|
8829
|
+
const allowedFolders = options.allowedFolders || [];
|
|
8761
8830
|
return {
|
|
8762
8831
|
debug: options.debug || false,
|
|
8763
|
-
allowedFolders
|
|
8764
|
-
cwd: options.cwd
|
|
8832
|
+
allowedFolders,
|
|
8833
|
+
cwd: options.cwd,
|
|
8834
|
+
// Consistent fallback chain: workspaceRoot > cwd > allowedFolders[0] > process.cwd()
|
|
8835
|
+
workspaceRoot: options.workspaceRoot || options.cwd || allowedFolders.length > 0 && allowedFolders[0] || process.cwd()
|
|
8765
8836
|
};
|
|
8766
8837
|
}
|
|
8767
8838
|
var editTool, createTool, editSchema, createSchema, editDescription, createDescription, editToolDefinition, createToolDefinition;
|
|
8768
8839
|
var init_edit = __esm({
|
|
8769
8840
|
"src/tools/edit.js"() {
|
|
8770
8841
|
"use strict";
|
|
8842
|
+
init_path_validation();
|
|
8771
8843
|
editTool = (options = {}) => {
|
|
8772
|
-
const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
|
|
8844
|
+
const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
|
|
8773
8845
|
return tool({
|
|
8774
8846
|
name: "edit",
|
|
8775
8847
|
description: `Edit files using exact string replacement (Claude Code style).
|
|
@@ -8825,7 +8897,8 @@ Important:
|
|
|
8825
8897
|
console.error(`[Edit] Attempting to edit file: ${resolvedPath}`);
|
|
8826
8898
|
}
|
|
8827
8899
|
if (!isPathAllowed(resolvedPath, allowedFolders)) {
|
|
8828
|
-
|
|
8900
|
+
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
8901
|
+
return `Error editing file: Permission denied - ${relativePath} is outside allowed directories`;
|
|
8829
8902
|
}
|
|
8830
8903
|
if (!existsSync(resolvedPath)) {
|
|
8831
8904
|
return `Error editing file: File not found - ${file_path}`;
|
|
@@ -8861,7 +8934,7 @@ Important:
|
|
|
8861
8934
|
});
|
|
8862
8935
|
};
|
|
8863
8936
|
createTool = (options = {}) => {
|
|
8864
|
-
const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
|
|
8937
|
+
const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
|
|
8865
8938
|
return tool({
|
|
8866
8939
|
name: "create",
|
|
8867
8940
|
description: `Create new files with specified content.
|
|
@@ -8909,7 +8982,8 @@ Important:
|
|
|
8909
8982
|
console.error(`[Create] Attempting to create file: ${resolvedPath}`);
|
|
8910
8983
|
}
|
|
8911
8984
|
if (!isPathAllowed(resolvedPath, allowedFolders)) {
|
|
8912
|
-
|
|
8985
|
+
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
8986
|
+
return `Error creating file: Permission denied - ${relativePath} is outside allowed directories`;
|
|
8913
8987
|
}
|
|
8914
8988
|
if (existsSync(resolvedPath) && !overwrite) {
|
|
8915
8989
|
return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
|
|
@@ -10471,7 +10545,7 @@ var init_vercel = __esm({
|
|
|
10471
10545
|
});
|
|
10472
10546
|
};
|
|
10473
10547
|
delegateTool = (options = {}) => {
|
|
10474
|
-
const { debug = false, timeout = 300, cwd, allowedFolders, enableBash = false, bashConfig, architectureFileName, enableMcp = false, mcpConfig = null, mcpConfigPath = null, delegationManager = null } = options;
|
|
10548
|
+
const { debug = false, timeout = 300, cwd, allowedFolders, workspaceRoot, enableBash = false, bashConfig, architectureFileName, enableMcp = false, mcpConfig = null, mcpConfigPath = null, delegationManager = null } = options;
|
|
10475
10549
|
return tool2({
|
|
10476
10550
|
name: "delegate",
|
|
10477
10551
|
description: delegateDescription,
|
|
@@ -10504,8 +10578,8 @@ var init_vercel = __esm({
|
|
|
10504
10578
|
if (searchDelegate !== void 0 && typeof searchDelegate !== "boolean") {
|
|
10505
10579
|
throw new TypeError("searchDelegate must be a boolean if provided");
|
|
10506
10580
|
}
|
|
10507
|
-
const
|
|
10508
|
-
const effectivePath = path9 ||
|
|
10581
|
+
const effectiveWorkspaceRoot = workspaceRoot || allowedFolders && allowedFolders[0];
|
|
10582
|
+
const effectivePath = path9 || effectiveWorkspaceRoot || cwd;
|
|
10509
10583
|
if (debug) {
|
|
10510
10584
|
console.error(`Executing delegate with task: "${task.substring(0, 100)}${task.length > 100 ? "..." : ""}"`);
|
|
10511
10585
|
if (parentSessionId) {
|
|
@@ -10542,7 +10616,7 @@ var init_vercel = __esm({
|
|
|
10542
10616
|
});
|
|
10543
10617
|
};
|
|
10544
10618
|
analyzeAllTool = (options = {}) => {
|
|
10545
|
-
const { sessionId, debug = false, delegationManager = null } = options;
|
|
10619
|
+
const { sessionId, debug = false, delegationManager = null, workspaceRoot } = options;
|
|
10546
10620
|
return tool2({
|
|
10547
10621
|
name: "analyze_all",
|
|
10548
10622
|
description: analyzeAllDescription,
|
|
@@ -10561,12 +10635,14 @@ var init_vercel = __esm({
|
|
|
10561
10635
|
console.error(`[analyze_all] Question: ${question}`);
|
|
10562
10636
|
console.error(`[analyze_all] Path: ${searchPath}`);
|
|
10563
10637
|
}
|
|
10638
|
+
const effectiveWorkspaceRoot = workspaceRoot || options.cwd || options.allowedFolders && options.allowedFolders[0];
|
|
10564
10639
|
const result = await analyzeAll({
|
|
10565
10640
|
question,
|
|
10566
10641
|
path: searchPath,
|
|
10567
10642
|
sessionId,
|
|
10568
10643
|
debug,
|
|
10569
10644
|
cwd: options.cwd,
|
|
10645
|
+
workspaceRoot: effectiveWorkspaceRoot,
|
|
10570
10646
|
allowedFolders: options.allowedFolders,
|
|
10571
10647
|
provider: options.provider,
|
|
10572
10648
|
model: options.model,
|
|
@@ -12042,14 +12118,17 @@ var init_bash = __esm({
|
|
|
12042
12118
|
"use strict";
|
|
12043
12119
|
init_bashPermissions();
|
|
12044
12120
|
init_bashExecutor();
|
|
12121
|
+
init_path_validation();
|
|
12045
12122
|
bashTool = (options = {}) => {
|
|
12046
12123
|
const {
|
|
12047
12124
|
bashConfig = {},
|
|
12048
12125
|
debug = false,
|
|
12049
12126
|
cwd,
|
|
12050
12127
|
allowedFolders = [],
|
|
12128
|
+
workspaceRoot: providedWorkspaceRoot,
|
|
12051
12129
|
tracer = null
|
|
12052
12130
|
} = options;
|
|
12131
|
+
const workspaceRoot = providedWorkspaceRoot || cwd || allowedFolders.length > 0 && allowedFolders[0] || process.cwd();
|
|
12053
12132
|
const permissionChecker = new BashPermissionChecker({
|
|
12054
12133
|
allow: bashConfig.allow,
|
|
12055
12134
|
deny: bashConfig.deny,
|
|
@@ -12065,6 +12144,9 @@ var init_bash = __esm({
|
|
|
12065
12144
|
if (cwd) {
|
|
12066
12145
|
return cwd;
|
|
12067
12146
|
}
|
|
12147
|
+
if (workspaceRoot) {
|
|
12148
|
+
return workspaceRoot;
|
|
12149
|
+
}
|
|
12068
12150
|
if (allowedFolders && allowedFolders.length > 0) {
|
|
12069
12151
|
return allowedFolders[0];
|
|
12070
12152
|
}
|
|
@@ -12152,13 +12234,15 @@ For code exploration, try these safe alternatives:
|
|
|
12152
12234
|
const defaultDir = getDefaultWorkingDirectory();
|
|
12153
12235
|
const workingDir = workingDirectory ? isAbsolute3(workingDirectory) ? resolve4(workingDirectory) : resolve4(defaultDir, workingDirectory) : defaultDir;
|
|
12154
12236
|
if (allowedFolders && allowedFolders.length > 0) {
|
|
12155
|
-
const resolvedWorkingDir =
|
|
12237
|
+
const resolvedWorkingDir = safeRealpath(workingDir);
|
|
12156
12238
|
const isAllowed = allowedFolders.some((folder) => {
|
|
12157
|
-
const resolvedFolder =
|
|
12239
|
+
const resolvedFolder = safeRealpath(folder);
|
|
12158
12240
|
return resolvedWorkingDir === resolvedFolder || resolvedWorkingDir.startsWith(resolvedFolder + sep2);
|
|
12159
12241
|
});
|
|
12160
12242
|
if (!isAllowed) {
|
|
12161
|
-
|
|
12243
|
+
const relativeDir = toRelativePath(workingDir, workspaceRoot);
|
|
12244
|
+
const relativeAllowed = allowedFolders.map((f) => toRelativePath(f, workspaceRoot));
|
|
12245
|
+
return `Error: Working directory "${relativeDir}" is not within allowed folders: ${relativeAllowed.join(", ")}`;
|
|
12162
12246
|
}
|
|
12163
12247
|
}
|
|
12164
12248
|
const executionOptions = {
|
|
@@ -16765,18 +16849,18 @@ import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
|
16765
16849
|
import { lstatSync, readdir as readdirCB, readdirSync, readlinkSync, realpathSync as rps } from "fs";
|
|
16766
16850
|
import * as actualFS from "node:fs";
|
|
16767
16851
|
import { lstat, readdir, readlink, realpath } from "node:fs/promises";
|
|
16768
|
-
var
|
|
16852
|
+
var realpathSync2, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
|
|
16769
16853
|
var init_esm4 = __esm({
|
|
16770
16854
|
"node_modules/path-scurry/dist/esm/index.js"() {
|
|
16771
16855
|
init_esm2();
|
|
16772
16856
|
init_esm3();
|
|
16773
|
-
|
|
16857
|
+
realpathSync2 = rps.native;
|
|
16774
16858
|
defaultFS = {
|
|
16775
16859
|
lstatSync,
|
|
16776
16860
|
readdir: readdirCB,
|
|
16777
16861
|
readdirSync,
|
|
16778
16862
|
readlinkSync,
|
|
16779
|
-
realpathSync,
|
|
16863
|
+
realpathSync: realpathSync2,
|
|
16780
16864
|
promises: {
|
|
16781
16865
|
lstat,
|
|
16782
16866
|
readdir,
|
|
@@ -69367,7 +69451,7 @@ import path8 from "path";
|
|
|
69367
69451
|
import os3 from "os";
|
|
69368
69452
|
import { EventEmitter as EventEmitter4 } from "events";
|
|
69369
69453
|
async function createEnhancedClaudeCLIEngine(options = {}) {
|
|
69370
|
-
const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools } = options;
|
|
69454
|
+
const { agent, systemPrompt, customPrompt, debug, sessionId, allowedTools, timeout = 12e4 } = options;
|
|
69371
69455
|
const session = new Session(
|
|
69372
69456
|
sessionId || randomBytes(8).toString("hex"),
|
|
69373
69457
|
debug
|
|
@@ -69466,6 +69550,30 @@ ${opts.schema}`;
|
|
|
69466
69550
|
stdio: ["ignore", "pipe", "pipe"]
|
|
69467
69551
|
// Ignore stdin since echo handles it
|
|
69468
69552
|
});
|
|
69553
|
+
let killed = false;
|
|
69554
|
+
let timeoutHandle;
|
|
69555
|
+
let sigkillHandle;
|
|
69556
|
+
if (timeout > 0) {
|
|
69557
|
+
timeoutHandle = setTimeout(() => {
|
|
69558
|
+
if (!killed) {
|
|
69559
|
+
killed = true;
|
|
69560
|
+
processEnded = true;
|
|
69561
|
+
proc2.kill("SIGTERM");
|
|
69562
|
+
if (debug) {
|
|
69563
|
+
console.log(`[DEBUG] Process timed out after ${timeout}ms, sending SIGTERM`);
|
|
69564
|
+
}
|
|
69565
|
+
sigkillHandle = setTimeout(() => {
|
|
69566
|
+
if (proc2.exitCode === null) {
|
|
69567
|
+
proc2.kill("SIGKILL");
|
|
69568
|
+
if (debug) {
|
|
69569
|
+
console.log("[DEBUG] Process did not exit, sending SIGKILL");
|
|
69570
|
+
}
|
|
69571
|
+
}
|
|
69572
|
+
}, 5e3);
|
|
69573
|
+
emitter.emit("error", new Error(`Claude CLI process timed out after ${timeout}ms`));
|
|
69574
|
+
}
|
|
69575
|
+
}, timeout);
|
|
69576
|
+
}
|
|
69469
69577
|
proc2.stdout.on("data", (data) => {
|
|
69470
69578
|
buffer += data.toString();
|
|
69471
69579
|
processJsonBuffer(buffer, emitter, session, debug, toolCollector);
|
|
@@ -69482,10 +69590,20 @@ ${opts.schema}`;
|
|
|
69482
69590
|
}
|
|
69483
69591
|
});
|
|
69484
69592
|
proc2.on("close", (code) => {
|
|
69593
|
+
if (timeoutHandle) {
|
|
69594
|
+
clearTimeout(timeoutHandle);
|
|
69595
|
+
}
|
|
69596
|
+
if (sigkillHandle) {
|
|
69597
|
+
clearTimeout(sigkillHandle);
|
|
69598
|
+
}
|
|
69485
69599
|
processEnded = true;
|
|
69486
69600
|
if (code !== 0 && debug) {
|
|
69487
69601
|
console.log(`[DEBUG] Process exited with code ${code}`);
|
|
69488
69602
|
}
|
|
69603
|
+
if (killed) {
|
|
69604
|
+
emitter.emit("end");
|
|
69605
|
+
return;
|
|
69606
|
+
}
|
|
69489
69607
|
if (buffer.trim()) {
|
|
69490
69608
|
processJsonBuffer(buffer, emitter, session, debug, toolCollector);
|
|
69491
69609
|
}
|
|
@@ -69501,6 +69619,13 @@ ${opts.schema}`;
|
|
|
69501
69619
|
emitter.emit("end");
|
|
69502
69620
|
});
|
|
69503
69621
|
proc2.on("error", (error) => {
|
|
69622
|
+
if (timeoutHandle) {
|
|
69623
|
+
clearTimeout(timeoutHandle);
|
|
69624
|
+
}
|
|
69625
|
+
if (sigkillHandle) {
|
|
69626
|
+
clearTimeout(sigkillHandle);
|
|
69627
|
+
}
|
|
69628
|
+
processEnded = true;
|
|
69504
69629
|
emitter.emit("error", error);
|
|
69505
69630
|
});
|
|
69506
69631
|
const messageQueue = [];
|
|
@@ -69546,7 +69671,22 @@ ${opts.schema}`;
|
|
|
69546
69671
|
\u{1F527} Using ${msg.name}: ${JSON.stringify(msg.input)}
|
|
69547
69672
|
`
|
|
69548
69673
|
};
|
|
69549
|
-
const
|
|
69674
|
+
const toolTimeout = 3e4;
|
|
69675
|
+
let toolTimeoutId;
|
|
69676
|
+
const timeoutPromise = new Promise((_, reject2) => {
|
|
69677
|
+
toolTimeoutId = setTimeout(() => reject2(new Error(`Tool ${msg.name} timed out after ${toolTimeout}ms`)), toolTimeout);
|
|
69678
|
+
});
|
|
69679
|
+
let result;
|
|
69680
|
+
try {
|
|
69681
|
+
result = await Promise.race([
|
|
69682
|
+
executeProbleTool(agent, msg.name, msg.input),
|
|
69683
|
+
timeoutPromise
|
|
69684
|
+
]);
|
|
69685
|
+
} catch (error) {
|
|
69686
|
+
result = `Tool error: ${error.message}`;
|
|
69687
|
+
} finally {
|
|
69688
|
+
clearTimeout(toolTimeoutId);
|
|
69689
|
+
}
|
|
69550
69690
|
yield { type: "text", content: `${result}
|
|
69551
69691
|
` };
|
|
69552
69692
|
} else if (msg.type === "toolBatch") {
|
|
@@ -70113,6 +70253,9 @@ var init_enhanced_vercel = __esm({
|
|
|
70113
70253
|
// src/agent/ProbeAgent.js
|
|
70114
70254
|
var ProbeAgent_exports = {};
|
|
70115
70255
|
__export(ProbeAgent_exports, {
|
|
70256
|
+
ENGINE_ACTIVITY_TIMEOUT_DEFAULT: () => ENGINE_ACTIVITY_TIMEOUT_DEFAULT,
|
|
70257
|
+
ENGINE_ACTIVITY_TIMEOUT_MAX: () => ENGINE_ACTIVITY_TIMEOUT_MAX,
|
|
70258
|
+
ENGINE_ACTIVITY_TIMEOUT_MIN: () => ENGINE_ACTIVITY_TIMEOUT_MIN,
|
|
70116
70259
|
ProbeAgent: () => ProbeAgent
|
|
70117
70260
|
});
|
|
70118
70261
|
import dotenv2 from "dotenv";
|
|
@@ -70147,7 +70290,7 @@ Your content here
|
|
|
70147
70290
|
|
|
70148
70291
|
Do NOT wrap in other tags like <api_call>, <tool_name>, <function>, etc.`;
|
|
70149
70292
|
}
|
|
70150
|
-
var MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
70293
|
+
var ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
70151
70294
|
var init_ProbeAgent = __esm({
|
|
70152
70295
|
"src/agent/ProbeAgent.js"() {
|
|
70153
70296
|
"use strict";
|
|
@@ -70171,10 +70314,14 @@ var init_ProbeAgent = __esm({
|
|
|
70171
70314
|
init_FallbackManager();
|
|
70172
70315
|
init_contextCompactor();
|
|
70173
70316
|
init_error_types();
|
|
70317
|
+
init_path_validation();
|
|
70174
70318
|
init_outputTruncator();
|
|
70175
70319
|
init_delegate();
|
|
70176
70320
|
init_tasks();
|
|
70177
70321
|
dotenv2.config();
|
|
70322
|
+
ENGINE_ACTIVITY_TIMEOUT_DEFAULT = 18e4;
|
|
70323
|
+
ENGINE_ACTIVITY_TIMEOUT_MIN = 5e3;
|
|
70324
|
+
ENGINE_ACTIVITY_TIMEOUT_MAX = 6e5;
|
|
70178
70325
|
MAX_TOOL_ITERATIONS = (() => {
|
|
70179
70326
|
const val = parseInt(process.env.MAX_TOOL_ITERATIONS || "30", 10);
|
|
70180
70327
|
if (isNaN(val) || val < 1 || val > 200) {
|
|
@@ -70233,6 +70380,8 @@ var init_ProbeAgent = __esm({
|
|
|
70233
70380
|
* @param {number} [options.fallback.maxTotalAttempts=10] - Maximum total attempts across all providers
|
|
70234
70381
|
* @param {string} [options.completionPrompt] - Custom prompt to run after attempt_completion for validation/review (runs before mermaid/JSON validation)
|
|
70235
70382
|
* @param {number} [options.maxOutputTokens] - Maximum tokens for tool output before truncation (default: 20000, can also be set via PROBE_MAX_OUTPUT_TOKENS env var)
|
|
70383
|
+
* @param {number} [options.requestTimeout] - Timeout in ms for AI requests (default: 120000 or REQUEST_TIMEOUT env var). Used to abort hung requests.
|
|
70384
|
+
* @param {number} [options.maxOperationTimeout] - Maximum timeout in ms for the entire operation including all retries and fallbacks (default: 300000 or MAX_OPERATION_TIMEOUT env var). This is the absolute maximum time for streamTextWithRetryAndFallback.
|
|
70236
70385
|
*/
|
|
70237
70386
|
constructor(options = {}) {
|
|
70238
70387
|
this.sessionId = options.sessionId || randomUUID6();
|
|
@@ -70288,7 +70437,8 @@ var init_ProbeAgent = __esm({
|
|
|
70288
70437
|
} else {
|
|
70289
70438
|
this.allowedFolders = [process.cwd()];
|
|
70290
70439
|
}
|
|
70291
|
-
this.
|
|
70440
|
+
this.workspaceRoot = getCommonPrefix(this.allowedFolders);
|
|
70441
|
+
this.cwd = options.cwd || this.workspaceRoot;
|
|
70292
70442
|
this.clientApiProvider = options.provider || null;
|
|
70293
70443
|
this.clientApiModel = options.model || null;
|
|
70294
70444
|
this.clientApiKey = null;
|
|
@@ -70300,6 +70450,8 @@ var init_ProbeAgent = __esm({
|
|
|
70300
70450
|
console.log(`[DEBUG] Maximum tool iterations configured: ${MAX_TOOL_ITERATIONS}`);
|
|
70301
70451
|
console.log(`[DEBUG] Allow Edit (implement tool): ${this.allowEdit}`);
|
|
70302
70452
|
console.log(`[DEBUG] Search delegation enabled: ${this.searchDelegate}`);
|
|
70453
|
+
console.log(`[DEBUG] Workspace root: ${this.workspaceRoot}`);
|
|
70454
|
+
console.log(`[DEBUG] Working directory (cwd): ${this.cwd}`);
|
|
70303
70455
|
}
|
|
70304
70456
|
this.initializeTools();
|
|
70305
70457
|
this.history = [];
|
|
@@ -70315,6 +70467,32 @@ var init_ProbeAgent = __esm({
|
|
|
70315
70467
|
this.enableTasks = !!options.enableTasks;
|
|
70316
70468
|
this.taskManager = null;
|
|
70317
70469
|
this.delegationManager = new DelegationManager();
|
|
70470
|
+
this.requestTimeout = options.requestTimeout ?? (() => {
|
|
70471
|
+
if (process.env.REQUEST_TIMEOUT) {
|
|
70472
|
+
const parsed = parseInt(process.env.REQUEST_TIMEOUT, 10);
|
|
70473
|
+
if (isNaN(parsed) || parsed < 1e3 || parsed > 36e5) {
|
|
70474
|
+
return 12e4;
|
|
70475
|
+
}
|
|
70476
|
+
return parsed;
|
|
70477
|
+
}
|
|
70478
|
+
return 12e4;
|
|
70479
|
+
})();
|
|
70480
|
+
if (this.debug) {
|
|
70481
|
+
console.log(`[DEBUG] Request timeout: ${this.requestTimeout}ms`);
|
|
70482
|
+
}
|
|
70483
|
+
this.maxOperationTimeout = options.maxOperationTimeout ?? (() => {
|
|
70484
|
+
if (process.env.MAX_OPERATION_TIMEOUT) {
|
|
70485
|
+
const parsed = parseInt(process.env.MAX_OPERATION_TIMEOUT, 10);
|
|
70486
|
+
if (isNaN(parsed) || parsed < 1e3 || parsed > 72e5) {
|
|
70487
|
+
return 3e5;
|
|
70488
|
+
}
|
|
70489
|
+
return parsed;
|
|
70490
|
+
}
|
|
70491
|
+
return 3e5;
|
|
70492
|
+
})();
|
|
70493
|
+
if (this.debug) {
|
|
70494
|
+
console.log(`[DEBUG] Max operation timeout: ${this.maxOperationTimeout}ms`);
|
|
70495
|
+
}
|
|
70318
70496
|
this.retryConfig = options.retry || {};
|
|
70319
70497
|
this.retryManager = null;
|
|
70320
70498
|
this.fallbackConfig = options.fallback || null;
|
|
@@ -70647,8 +70825,9 @@ var init_ProbeAgent = __esm({
|
|
|
70647
70825
|
const configOptions = {
|
|
70648
70826
|
sessionId: this.sessionId,
|
|
70649
70827
|
debug: this.debug,
|
|
70650
|
-
// Use
|
|
70651
|
-
cwd: this.cwd
|
|
70828
|
+
// Use cwd (which defaults to workspaceRoot in constructor)
|
|
70829
|
+
cwd: this.cwd,
|
|
70830
|
+
workspaceRoot: this.workspaceRoot,
|
|
70652
70831
|
allowedFolders: this.allowedFolders,
|
|
70653
70832
|
outline: this.outline,
|
|
70654
70833
|
searchDelegate: this.searchDelegate,
|
|
@@ -70933,88 +71112,98 @@ var init_ProbeAgent = __esm({
|
|
|
70933
71112
|
}
|
|
70934
71113
|
}
|
|
70935
71114
|
/**
|
|
70936
|
-
*
|
|
70937
|
-
* @param {
|
|
70938
|
-
* @
|
|
71115
|
+
* Create a streamText-compatible result from an engine stream with timeout handling
|
|
71116
|
+
* @param {AsyncGenerator} engineStream - The engine's query result
|
|
71117
|
+
* @param {AbortSignal} abortSignal - Signal for aborting the operation
|
|
71118
|
+
* @param {number} requestTimeout - Per-request timeout in ms
|
|
71119
|
+
* @param {Object} timeoutState - Object with timeoutId property (mutable for cleanup)
|
|
71120
|
+
* @returns {Object} - streamText-compatible result with textStream
|
|
70939
71121
|
* @private
|
|
70940
71122
|
*/
|
|
70941
|
-
|
|
70942
|
-
|
|
71123
|
+
_createEngineTextStreamResult(engineStream, abortSignal, requestTimeout, timeoutState) {
|
|
71124
|
+
const activityTimeout = (() => {
|
|
71125
|
+
const parsed = parseInt(process.env.ENGINE_ACTIVITY_TIMEOUT, 10);
|
|
71126
|
+
return isNaN(parsed) || parsed < ENGINE_ACTIVITY_TIMEOUT_MIN || parsed > ENGINE_ACTIVITY_TIMEOUT_MAX ? ENGINE_ACTIVITY_TIMEOUT_DEFAULT : parsed;
|
|
71127
|
+
})();
|
|
71128
|
+
const startTime = Date.now();
|
|
71129
|
+
async function* createTextStream() {
|
|
71130
|
+
let lastActivity = Date.now();
|
|
70943
71131
|
try {
|
|
70944
|
-
const
|
|
70945
|
-
|
|
70946
|
-
|
|
70947
|
-
|
|
70948
|
-
|
|
70949
|
-
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
70950
|
-
const prompt = lastUserMessage ? lastUserMessage.content : "";
|
|
70951
|
-
const engineOptions = {
|
|
70952
|
-
maxTokens: options.maxTokens,
|
|
70953
|
-
temperature: options.temperature,
|
|
70954
|
-
messages: options.messages,
|
|
70955
|
-
systemPrompt: options.messages.find((m) => m.role === "system")?.content
|
|
70956
|
-
};
|
|
70957
|
-
const engineStream = engine.query(prompt, engineOptions);
|
|
70958
|
-
async function* createTextStream() {
|
|
70959
|
-
for await (const message of engineStream) {
|
|
70960
|
-
if (message.type === "text" && message.content) {
|
|
70961
|
-
yield message.content;
|
|
70962
|
-
} else if (typeof message === "string") {
|
|
70963
|
-
yield message;
|
|
70964
|
-
}
|
|
70965
|
-
}
|
|
71132
|
+
for await (const message of engineStream) {
|
|
71133
|
+
if (abortSignal.aborted) {
|
|
71134
|
+
const abortError = new Error("Operation aborted");
|
|
71135
|
+
abortError.name = "AbortError";
|
|
71136
|
+
throw abortError;
|
|
70966
71137
|
}
|
|
70967
|
-
|
|
70968
|
-
|
|
70969
|
-
|
|
70970
|
-
|
|
70971
|
-
|
|
70972
|
-
|
|
70973
|
-
|
|
70974
|
-
|
|
70975
|
-
|
|
70976
|
-
|
|
70977
|
-
|
|
70978
|
-
|
|
70979
|
-
}
|
|
70980
|
-
if (this.clientApiProvider === "codex" || process.env.USE_CODEX === "true") {
|
|
70981
|
-
try {
|
|
70982
|
-
const engine = await this.getEngine();
|
|
70983
|
-
if (engine && engine.query) {
|
|
70984
|
-
const userMessages = options.messages.filter(
|
|
70985
|
-
(m) => m.role === "user" && !m.content.includes("WARNING: You have reached the maximum tool iterations limit")
|
|
70986
|
-
);
|
|
70987
|
-
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
70988
|
-
const prompt = lastUserMessage ? lastUserMessage.content : "";
|
|
70989
|
-
const engineOptions = {
|
|
70990
|
-
maxTokens: options.maxTokens,
|
|
70991
|
-
temperature: options.temperature,
|
|
70992
|
-
messages: options.messages,
|
|
70993
|
-
systemPrompt: options.messages.find((m) => m.role === "system")?.content
|
|
70994
|
-
};
|
|
70995
|
-
const engineStream = engine.query(prompt, engineOptions);
|
|
70996
|
-
async function* createTextStream() {
|
|
70997
|
-
for await (const message of engineStream) {
|
|
70998
|
-
if (message.type === "text" && message.content) {
|
|
70999
|
-
yield message.content;
|
|
71000
|
-
} else if (typeof message === "string") {
|
|
71001
|
-
yield message;
|
|
71002
|
-
}
|
|
71003
|
-
}
|
|
71138
|
+
const now = Date.now();
|
|
71139
|
+
if (now - lastActivity > activityTimeout) {
|
|
71140
|
+
throw new Error(`Engine stream timeout - no activity for ${activityTimeout}ms`);
|
|
71141
|
+
}
|
|
71142
|
+
if (requestTimeout > 0 && now - startTime > requestTimeout) {
|
|
71143
|
+
throw new Error(`Engine stream timeout - request exceeded ${requestTimeout}ms`);
|
|
71144
|
+
}
|
|
71145
|
+
lastActivity = now;
|
|
71146
|
+
if (message.type === "text" && message.content) {
|
|
71147
|
+
yield message.content;
|
|
71148
|
+
} else if (typeof message === "string") {
|
|
71149
|
+
yield message;
|
|
71004
71150
|
}
|
|
71005
|
-
return {
|
|
71006
|
-
textStream: createTextStream(),
|
|
71007
|
-
usage: Promise.resolve({})
|
|
71008
|
-
// Engine should handle its own usage tracking
|
|
71009
|
-
// Add other streamText-compatible properties as needed
|
|
71010
|
-
};
|
|
71011
71151
|
}
|
|
71012
|
-
}
|
|
71013
|
-
if (
|
|
71014
|
-
|
|
71152
|
+
} finally {
|
|
71153
|
+
if (timeoutState.timeoutId) {
|
|
71154
|
+
clearTimeout(timeoutState.timeoutId);
|
|
71155
|
+
timeoutState.timeoutId = null;
|
|
71015
71156
|
}
|
|
71016
71157
|
}
|
|
71017
71158
|
}
|
|
71159
|
+
return {
|
|
71160
|
+
textStream: createTextStream(),
|
|
71161
|
+
usage: Promise.resolve({})
|
|
71162
|
+
// Engine should handle its own usage tracking
|
|
71163
|
+
// Add other streamText-compatible properties as needed
|
|
71164
|
+
};
|
|
71165
|
+
}
|
|
71166
|
+
/**
|
|
71167
|
+
* Try to use an engine (claude-code or codex) for streaming
|
|
71168
|
+
* @param {Object} options - streamText options
|
|
71169
|
+
* @param {AbortController} controller - Abort controller for the operation
|
|
71170
|
+
* @param {Object} timeoutState - Mutable timeout state for cleanup
|
|
71171
|
+
* @returns {Promise<Object|null>} - Stream result or null if engine unavailable
|
|
71172
|
+
* @private
|
|
71173
|
+
*/
|
|
71174
|
+
async _tryEngineStreamPath(options, controller, timeoutState) {
|
|
71175
|
+
const engine = await this.getEngine();
|
|
71176
|
+
if (!engine || !engine.query) {
|
|
71177
|
+
return null;
|
|
71178
|
+
}
|
|
71179
|
+
const userMessages = options.messages.filter(
|
|
71180
|
+
(m) => m.role === "user" && !m.content.includes("WARNING: You have reached the maximum tool iterations limit")
|
|
71181
|
+
);
|
|
71182
|
+
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
71183
|
+
const prompt = lastUserMessage ? lastUserMessage.content : "";
|
|
71184
|
+
const engineOptions = {
|
|
71185
|
+
maxTokens: options.maxTokens,
|
|
71186
|
+
temperature: options.temperature,
|
|
71187
|
+
messages: options.messages,
|
|
71188
|
+
systemPrompt: options.messages.find((m) => m.role === "system")?.content,
|
|
71189
|
+
abortSignal: controller.signal
|
|
71190
|
+
};
|
|
71191
|
+
const engineStream = engine.query(prompt, engineOptions);
|
|
71192
|
+
return this._createEngineTextStreamResult(
|
|
71193
|
+
engineStream,
|
|
71194
|
+
controller.signal,
|
|
71195
|
+
this.requestTimeout,
|
|
71196
|
+
timeoutState
|
|
71197
|
+
);
|
|
71198
|
+
}
|
|
71199
|
+
/**
|
|
71200
|
+
* Execute streamText with Vercel AI SDK using retry/fallback logic
|
|
71201
|
+
* @param {Object} options - streamText options
|
|
71202
|
+
* @param {AbortController} controller - Abort controller for the operation
|
|
71203
|
+
* @returns {Promise<Object>} - Stream result
|
|
71204
|
+
* @private
|
|
71205
|
+
*/
|
|
71206
|
+
async _executeWithVercelProvider(options, controller) {
|
|
71018
71207
|
if (!this.retryManager) {
|
|
71019
71208
|
this.retryManager = new RetryManager({
|
|
71020
71209
|
maxRetries: this.retryConfig.maxRetries ?? 3,
|
|
@@ -71027,10 +71216,11 @@ var init_ProbeAgent = __esm({
|
|
|
71027
71216
|
}
|
|
71028
71217
|
if (!this.fallbackManager) {
|
|
71029
71218
|
return await this.retryManager.executeWithRetry(
|
|
71030
|
-
() => streamText2(options),
|
|
71219
|
+
() => streamText2({ ...options, abortSignal: controller.signal }),
|
|
71031
71220
|
{
|
|
71032
71221
|
provider: this.apiType,
|
|
71033
|
-
model: this.model
|
|
71222
|
+
model: this.model,
|
|
71223
|
+
signal: controller.signal
|
|
71034
71224
|
}
|
|
71035
71225
|
);
|
|
71036
71226
|
}
|
|
@@ -71038,7 +71228,8 @@ var init_ProbeAgent = __esm({
|
|
|
71038
71228
|
async (provider, model, config) => {
|
|
71039
71229
|
const fallbackOptions = {
|
|
71040
71230
|
...options,
|
|
71041
|
-
model: provider(model)
|
|
71231
|
+
model: provider(model),
|
|
71232
|
+
abortSignal: controller.signal
|
|
71042
71233
|
};
|
|
71043
71234
|
const providerRetryManager = new RetryManager({
|
|
71044
71235
|
maxRetries: config.maxRetries ?? this.retryConfig.maxRetries ?? 3,
|
|
@@ -71052,12 +71243,54 @@ var init_ProbeAgent = __esm({
|
|
|
71052
71243
|
() => streamText2(fallbackOptions),
|
|
71053
71244
|
{
|
|
71054
71245
|
provider: config.provider,
|
|
71055
|
-
model
|
|
71246
|
+
model,
|
|
71247
|
+
signal: controller.signal
|
|
71056
71248
|
}
|
|
71057
71249
|
);
|
|
71058
71250
|
}
|
|
71059
71251
|
);
|
|
71060
71252
|
}
|
|
71253
|
+
/**
|
|
71254
|
+
* Execute streamText with retry and fallback support
|
|
71255
|
+
* @param {Object} options - streamText options
|
|
71256
|
+
* @returns {Promise<Object>} - streamText result
|
|
71257
|
+
* @private
|
|
71258
|
+
*/
|
|
71259
|
+
async streamTextWithRetryAndFallback(options) {
|
|
71260
|
+
const controller = new AbortController();
|
|
71261
|
+
const timeoutState = { timeoutId: null };
|
|
71262
|
+
if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
|
|
71263
|
+
timeoutState.timeoutId = setTimeout(() => {
|
|
71264
|
+
controller.abort();
|
|
71265
|
+
if (this.debug) {
|
|
71266
|
+
console.log(`[DEBUG] Operation timed out after ${this.maxOperationTimeout}ms (max operation timeout)`);
|
|
71267
|
+
}
|
|
71268
|
+
}, this.maxOperationTimeout);
|
|
71269
|
+
}
|
|
71270
|
+
try {
|
|
71271
|
+
const useClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
|
|
71272
|
+
const useCodex = this.clientApiProvider === "codex" || process.env.USE_CODEX === "true";
|
|
71273
|
+
if (useClaudeCode || useCodex) {
|
|
71274
|
+
try {
|
|
71275
|
+
const result = await this._tryEngineStreamPath(options, controller, timeoutState);
|
|
71276
|
+
if (result) {
|
|
71277
|
+
return result;
|
|
71278
|
+
}
|
|
71279
|
+
} catch (error) {
|
|
71280
|
+
if (this.debug) {
|
|
71281
|
+
const engineType = useClaudeCode ? "Claude Code" : "Codex";
|
|
71282
|
+
console.log(`[DEBUG] Failed to use ${engineType} engine, falling back to Vercel:`, error.message);
|
|
71283
|
+
}
|
|
71284
|
+
}
|
|
71285
|
+
}
|
|
71286
|
+
return await this._executeWithVercelProvider(options, controller);
|
|
71287
|
+
} finally {
|
|
71288
|
+
if (timeoutState.timeoutId) {
|
|
71289
|
+
clearTimeout(timeoutState.timeoutId);
|
|
71290
|
+
timeoutState.timeoutId = null;
|
|
71291
|
+
}
|
|
71292
|
+
}
|
|
71293
|
+
}
|
|
71061
71294
|
/**
|
|
71062
71295
|
* Initialize Anthropic model
|
|
71063
71296
|
*/
|
|
@@ -71335,16 +71568,16 @@ var init_ProbeAgent = __esm({
|
|
|
71335
71568
|
let absolutePath;
|
|
71336
71569
|
let isPathAllowed2 = false;
|
|
71337
71570
|
if (isAbsolute5(imagePath)) {
|
|
71338
|
-
absolutePath =
|
|
71571
|
+
absolutePath = safeRealpath(resolve6(imagePath));
|
|
71339
71572
|
isPathAllowed2 = allowedDirs.some((dir) => {
|
|
71340
|
-
const
|
|
71341
|
-
return absolutePath ===
|
|
71573
|
+
const resolvedDir = safeRealpath(dir);
|
|
71574
|
+
return absolutePath === resolvedDir || absolutePath.startsWith(resolvedDir + sep5);
|
|
71342
71575
|
});
|
|
71343
71576
|
} else {
|
|
71344
71577
|
for (const dir of allowedDirs) {
|
|
71345
|
-
const
|
|
71346
|
-
const resolvedPath =
|
|
71347
|
-
if (resolvedPath ===
|
|
71578
|
+
const resolvedDir = safeRealpath(dir);
|
|
71579
|
+
const resolvedPath = safeRealpath(resolve6(dir, imagePath));
|
|
71580
|
+
if (resolvedPath === resolvedDir || resolvedPath.startsWith(resolvedDir + sep5)) {
|
|
71348
71581
|
absolutePath = resolvedPath;
|
|
71349
71582
|
isPathAllowed2 = true;
|
|
71350
71583
|
break;
|
|
@@ -71527,7 +71760,7 @@ var init_ProbeAgent = __esm({
|
|
|
71527
71760
|
if (this._architectureContextLoaded) {
|
|
71528
71761
|
return this.architectureContext;
|
|
71529
71762
|
}
|
|
71530
|
-
const rootDirectory = this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd();
|
|
71763
|
+
const rootDirectory = this.workspaceRoot || (this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd());
|
|
71531
71764
|
const configuredName = typeof this.architectureFileName === "string" ? this.architectureFileName.trim() : "";
|
|
71532
71765
|
const hasConfiguredName = !!configuredName;
|
|
71533
71766
|
let guidanceCandidates = [];
|
|
@@ -71664,6 +71897,9 @@ ${this.architectureContext.content}
|
|
|
71664
71897
|
`;
|
|
71665
71898
|
}
|
|
71666
71899
|
_getSkillsRepoRoot() {
|
|
71900
|
+
if (this.workspaceRoot) {
|
|
71901
|
+
return resolve6(this.workspaceRoot);
|
|
71902
|
+
}
|
|
71667
71903
|
if (this.allowedFolders && this.allowedFolders.length > 0) {
|
|
71668
71904
|
return resolve6(this.allowedFolders[0]);
|
|
71669
71905
|
}
|
|
@@ -71731,7 +71967,7 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
71731
71967
|
|
|
71732
71968
|
# Repository Structure
|
|
71733
71969
|
`;
|
|
71734
|
-
systemPrompt += `You are working with a repository located at: ${this.
|
|
71970
|
+
systemPrompt += `You are working with a repository located at: ${this.workspaceRoot}
|
|
71735
71971
|
|
|
71736
71972
|
`;
|
|
71737
71973
|
systemPrompt += `Here's an overview of the repository structure (showing up to 100 most relevant files):
|
|
@@ -71784,7 +72020,7 @@ Workspace: ${this.allowedFolders.join(", ")}`;
|
|
|
71784
72020
|
|
|
71785
72021
|
# Repository Structure
|
|
71786
72022
|
`;
|
|
71787
|
-
systemPrompt += `You are working with a repository located at: ${this.
|
|
72023
|
+
systemPrompt += `You are working with a repository located at: ${this.workspaceRoot}
|
|
71788
72024
|
|
|
71789
72025
|
`;
|
|
71790
72026
|
systemPrompt += `Here's an overview of the repository structure (showing up to 100 most relevant files):
|
|
@@ -72083,21 +72319,34 @@ For MCP tools, use JSON format within the params tag, e.g.:
|
|
|
72083
72319
|
`;
|
|
72084
72320
|
}
|
|
72085
72321
|
}
|
|
72086
|
-
const searchDirectory = this.
|
|
72322
|
+
const searchDirectory = this.workspaceRoot;
|
|
72087
72323
|
if (this.debug) {
|
|
72088
|
-
console.log(`[DEBUG] Generating file list for
|
|
72324
|
+
console.log(`[DEBUG] Generating file list for workspace root: ${searchDirectory}...`);
|
|
72325
|
+
}
|
|
72326
|
+
const relativeWorkspaces = this.allowedFolders.map((f) => {
|
|
72327
|
+
const rel = toRelativePath(f, this.workspaceRoot);
|
|
72328
|
+
if (rel && rel !== "." && !rel.startsWith(".") && !rel.startsWith("/")) {
|
|
72329
|
+
return "./" + rel;
|
|
72330
|
+
}
|
|
72331
|
+
return rel;
|
|
72332
|
+
}).filter((f) => f && f !== ".");
|
|
72333
|
+
let workspaceDesc;
|
|
72334
|
+
if (relativeWorkspaces.length === 0) {
|
|
72335
|
+
workspaceDesc = ". (current directory)";
|
|
72336
|
+
} else {
|
|
72337
|
+
workspaceDesc = relativeWorkspaces.join(", ");
|
|
72089
72338
|
}
|
|
72090
72339
|
try {
|
|
72091
72340
|
const files = await listFilesByLevel({
|
|
72092
72341
|
directory: searchDirectory,
|
|
72093
72342
|
maxFiles: 100,
|
|
72094
72343
|
respectGitignore: !process.env.PROBE_NO_GITIGNORE || process.env.PROBE_NO_GITIGNORE === "",
|
|
72095
|
-
cwd:
|
|
72344
|
+
cwd: this.workspaceRoot
|
|
72096
72345
|
});
|
|
72097
72346
|
systemMessage += `
|
|
72098
72347
|
# Repository Structure
|
|
72099
72348
|
|
|
72100
|
-
You are working with a
|
|
72349
|
+
You are working with a workspace. Available paths: ${workspaceDesc}
|
|
72101
72350
|
|
|
72102
72351
|
Here's an overview of the repository structure (showing up to 100 most relevant files):
|
|
72103
72352
|
|
|
@@ -72113,15 +72362,22 @@ ${files}
|
|
|
72113
72362
|
systemMessage += `
|
|
72114
72363
|
# Repository Structure
|
|
72115
72364
|
|
|
72116
|
-
You are working with a
|
|
72365
|
+
You are working with a workspace. Available paths: ${workspaceDesc}
|
|
72117
72366
|
|
|
72118
72367
|
`;
|
|
72119
72368
|
}
|
|
72120
72369
|
await this.loadArchitectureContext();
|
|
72121
72370
|
systemMessage += this.getArchitectureSection();
|
|
72122
72371
|
if (this.allowedFolders.length > 0) {
|
|
72372
|
+
const relativeAllowed = this.allowedFolders.map((f) => {
|
|
72373
|
+
const rel = toRelativePath(f, this.workspaceRoot);
|
|
72374
|
+
if (rel && rel !== "." && !rel.startsWith(".") && !rel.startsWith("/")) {
|
|
72375
|
+
return "./" + rel;
|
|
72376
|
+
}
|
|
72377
|
+
return rel;
|
|
72378
|
+
});
|
|
72123
72379
|
systemMessage += `
|
|
72124
|
-
**Important**: For security reasons, you can only
|
|
72380
|
+
**Important**: For security reasons, you can only access these paths: ${relativeAllowed.join(", ")}
|
|
72125
72381
|
|
|
72126
72382
|
`;
|
|
72127
72383
|
}
|
|
@@ -72635,6 +72891,7 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72635
72891
|
console.error(`[DEBUG] ========================================
|
|
72636
72892
|
`);
|
|
72637
72893
|
}
|
|
72894
|
+
currentMessages.push({ role: "assistant", content: assistantResponseContent });
|
|
72638
72895
|
currentMessages.push({ role: "user", content: `<tool_result>
|
|
72639
72896
|
${toolResultContent}
|
|
72640
72897
|
</tool_result>` });
|
|
@@ -72655,17 +72912,18 @@ ${toolResultContent}
|
|
|
72655
72912
|
`);
|
|
72656
72913
|
}
|
|
72657
72914
|
const errorXml = formatErrorForAI(error);
|
|
72915
|
+
currentMessages.push({ role: "assistant", content: assistantResponseContent });
|
|
72658
72916
|
currentMessages.push({ role: "user", content: `<tool_result>
|
|
72659
72917
|
${errorXml}
|
|
72660
72918
|
</tool_result>` });
|
|
72661
72919
|
}
|
|
72662
72920
|
} else if (this.toolImplementations[toolName]) {
|
|
72663
72921
|
try {
|
|
72664
|
-
let resolvedWorkingDirectory = this.cwd || this.allowedFolders && this.allowedFolders[0] || process.cwd();
|
|
72922
|
+
let resolvedWorkingDirectory = this.workspaceRoot || this.cwd || this.allowedFolders && this.allowedFolders[0] || process.cwd();
|
|
72665
72923
|
if (params.workingDirectory) {
|
|
72666
|
-
const requestedDir = isAbsolute5(params.workingDirectory) ? resolve6(params.workingDirectory) : resolve6(resolvedWorkingDirectory, params.workingDirectory);
|
|
72924
|
+
const requestedDir = safeRealpath(isAbsolute5(params.workingDirectory) ? resolve6(params.workingDirectory) : resolve6(resolvedWorkingDirectory, params.workingDirectory));
|
|
72667
72925
|
const isWithinAllowed = !this.allowedFolders || this.allowedFolders.length === 0 || this.allowedFolders.some((folder) => {
|
|
72668
|
-
const resolvedFolder =
|
|
72926
|
+
const resolvedFolder = safeRealpath(folder);
|
|
72669
72927
|
return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + sep5);
|
|
72670
72928
|
});
|
|
72671
72929
|
if (isWithinAllowed) {
|
|
@@ -73134,7 +73392,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
73134
73392
|
}
|
|
73135
73393
|
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
73136
73394
|
debug: this.debug,
|
|
73137
|
-
path: this.allowedFolders[0],
|
|
73395
|
+
path: this.workspaceRoot || this.allowedFolders[0],
|
|
73138
73396
|
provider: this.clientApiProvider,
|
|
73139
73397
|
model: this.model,
|
|
73140
73398
|
tracer: this.tracer
|
|
@@ -73207,7 +73465,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
73207
73465
|
}
|
|
73208
73466
|
const { JsonFixingAgent: JsonFixingAgent2 } = await Promise.resolve().then(() => (init_schemaUtils(), schemaUtils_exports));
|
|
73209
73467
|
const jsonFixer = new JsonFixingAgent2({
|
|
73210
|
-
path: this.allowedFolders[0],
|
|
73468
|
+
path: this.workspaceRoot || this.allowedFolders[0],
|
|
73211
73469
|
provider: this.clientApiProvider,
|
|
73212
73470
|
model: this.model,
|
|
73213
73471
|
debug: this.debug,
|
|
@@ -73276,7 +73534,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
73276
73534
|
}
|
|
73277
73535
|
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
73278
73536
|
debug: this.debug,
|
|
73279
|
-
path: this.allowedFolders[0],
|
|
73537
|
+
path: this.workspaceRoot || this.allowedFolders[0],
|
|
73280
73538
|
provider: this.clientApiProvider,
|
|
73281
73539
|
model: this.model,
|
|
73282
73540
|
tracer: this.tracer
|
|
@@ -73408,7 +73666,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
73408
73666
|
}
|
|
73409
73667
|
const finalMermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
73410
73668
|
debug: this.debug,
|
|
73411
|
-
path: this.allowedFolders[0],
|
|
73669
|
+
path: this.workspaceRoot || this.allowedFolders[0],
|
|
73412
73670
|
provider: this.clientApiProvider,
|
|
73413
73671
|
model: this.model,
|
|
73414
73672
|
tracer: this.tracer
|
|
@@ -73558,8 +73816,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
73558
73816
|
allowEdit: this.allowEdit,
|
|
73559
73817
|
enableDelegate: this.enableDelegate,
|
|
73560
73818
|
architectureFileName: this.architectureFileName,
|
|
73561
|
-
|
|
73562
|
-
// Use first allowed folder as primary path
|
|
73819
|
+
// Pass allowedFolders which will recompute workspaceRoot correctly
|
|
73563
73820
|
allowedFolders: [...this.allowedFolders],
|
|
73564
73821
|
cwd: this.cwd,
|
|
73565
73822
|
// Preserve explicit working directory
|