@probelabs/probe 0.6.0-rc269 → 0.6.0-rc271
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-rc271-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc271-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc271-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc271-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc271-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.js +74 -25
- package/build/agent/index.js +128 -36
- package/build/tools/vercel.js +66 -5
- package/cjs/agent/ProbeAgent.cjs +163 -71
- package/cjs/index.cjs +138 -46
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +74 -25
- package/src/tools/vercel.js +66 -5
- package/bin/binaries/probe-v0.6.0-rc269-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc269-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc269-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc269-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc269-x86_64-unknown-linux-musl.tar.gz +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3582,23 +3582,24 @@ Follow these instructions carefully:
|
|
|
3582
3582
|
// Continue even if storage fails
|
|
3583
3583
|
}
|
|
3584
3584
|
|
|
3585
|
-
// Completion prompt handling -
|
|
3586
|
-
// This
|
|
3587
|
-
//
|
|
3585
|
+
// Completion prompt handling - inject one more user message into the existing conversation
|
|
3586
|
+
// This continues the SAME agentic session (same tools, same TaskManager, same history)
|
|
3587
|
+
// rather than spawning a recursive this.answer() call which would reset state
|
|
3588
3588
|
if (completionAttempted && this.completionPrompt && !options._completionPromptProcessed) {
|
|
3589
3589
|
if (this.debug) {
|
|
3590
|
-
console.log('[DEBUG] Running completion prompt
|
|
3590
|
+
console.log('[DEBUG] Running completion prompt as continuation of current session...');
|
|
3591
3591
|
}
|
|
3592
3592
|
|
|
3593
3593
|
try {
|
|
3594
|
-
|
|
3594
|
+
const originalResult = finalResult;
|
|
3595
|
+
|
|
3595
3596
|
if (this.tracer) {
|
|
3596
3597
|
this.tracer.recordEvent('completion_prompt.started', {
|
|
3597
3598
|
'completion_prompt.original_result_length': finalResult?.length || 0
|
|
3598
3599
|
});
|
|
3599
3600
|
}
|
|
3600
3601
|
|
|
3601
|
-
//
|
|
3602
|
+
// Append completion prompt as a user message to the existing conversation
|
|
3602
3603
|
const completionPromptMessage = `${this.completionPrompt}
|
|
3603
3604
|
|
|
3604
3605
|
Here is the result to review:
|
|
@@ -3606,34 +3607,82 @@ Here is the result to review:
|
|
|
3606
3607
|
${finalResult}
|
|
3607
3608
|
</result>
|
|
3608
3609
|
|
|
3609
|
-
|
|
3610
|
+
Double-check your response based on the criteria above. If everything looks good, respond with your previous answer exactly as-is using attempt_completion. If something needs to be fixed or is missing, do it now, then respond with the COMPLETE updated answer (everything you did in total, not just the fix) using attempt_completion.`;
|
|
3610
3611
|
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
//
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
this.
|
|
3612
|
+
currentMessages.push({ role: 'user', content: completionPromptMessage });
|
|
3613
|
+
|
|
3614
|
+
// Reset completion tracking for the follow-up turn
|
|
3615
|
+
completionResult = null;
|
|
3616
|
+
completionAttempted = false;
|
|
3617
|
+
|
|
3618
|
+
// Run one more streamText pass with the same tools and conversation context
|
|
3619
|
+
// Give a small number of extra iterations for the follow-up
|
|
3620
|
+
const completionMaxIterations = 5;
|
|
3621
|
+
const completionStreamOptions = {
|
|
3622
|
+
model: this.provider ? this.provider(this.model) : this.model,
|
|
3623
|
+
messages: this.prepareMessagesWithImages(currentMessages),
|
|
3624
|
+
tools,
|
|
3625
|
+
stopWhen: stepCountIs(completionMaxIterations),
|
|
3626
|
+
maxTokens: maxResponseTokens,
|
|
3627
|
+
temperature: 0.3,
|
|
3628
|
+
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
3629
|
+
if (usage) {
|
|
3630
|
+
this.tokenCounter.recordUsage(usage);
|
|
3631
|
+
}
|
|
3632
|
+
if (options.onStream && text) {
|
|
3633
|
+
options.onStream(text);
|
|
3634
|
+
}
|
|
3635
|
+
if (this.debug) {
|
|
3636
|
+
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
};
|
|
3640
|
+
|
|
3641
|
+
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
3642
|
+
if (providerOpts) {
|
|
3643
|
+
completionStreamOptions.providerOptions = providerOpts;
|
|
3644
|
+
}
|
|
3645
|
+
|
|
3646
|
+
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
3647
|
+
const cpFinalText = await cpResult.text;
|
|
3648
|
+
const cpUsage = await cpResult.usage;
|
|
3649
|
+
if (cpUsage) {
|
|
3650
|
+
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3653
|
+
// Append follow-up messages to conversation history
|
|
3654
|
+
const cpMessages = await cpResult.response?.messages;
|
|
3655
|
+
if (cpMessages) {
|
|
3656
|
+
for (const msg of cpMessages) {
|
|
3657
|
+
currentMessages.push(msg);
|
|
3658
|
+
}
|
|
3623
3659
|
}
|
|
3624
|
-
this._extractedRawBlocks = savedExtractedBlocks;
|
|
3625
3660
|
|
|
3626
|
-
//
|
|
3627
|
-
|
|
3661
|
+
// Use new completion result if the agent called attempt_completion again,
|
|
3662
|
+
// otherwise keep the original result (the follow-up may have just done side-effects)
|
|
3663
|
+
if (completionResult) {
|
|
3664
|
+
finalResult = completionResult;
|
|
3665
|
+
completionAttempted = true;
|
|
3666
|
+
} else if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
3667
|
+
finalResult = cpFinalText;
|
|
3668
|
+
completionAttempted = true;
|
|
3669
|
+
} else {
|
|
3670
|
+
// Follow-up produced nothing useful — keep the original
|
|
3671
|
+
finalResult = originalResult;
|
|
3672
|
+
completionAttempted = true;
|
|
3673
|
+
if (this.debug) {
|
|
3674
|
+
console.log('[DEBUG] Completion prompt returned empty result, keeping original.');
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3628
3677
|
|
|
3629
3678
|
if (this.debug) {
|
|
3630
|
-
console.log(`[DEBUG] Completion prompt finished.
|
|
3679
|
+
console.log(`[DEBUG] Completion prompt finished. Final result length: ${finalResult?.length || 0}`);
|
|
3631
3680
|
}
|
|
3632
3681
|
|
|
3633
|
-
// Record completion prompt completion in telemetry
|
|
3634
3682
|
if (this.tracer) {
|
|
3635
3683
|
this.tracer.recordEvent('completion_prompt.completed', {
|
|
3636
|
-
'completion_prompt.final_result_length': finalResult?.length || 0
|
|
3684
|
+
'completion_prompt.final_result_length': finalResult?.length || 0,
|
|
3685
|
+
'completion_prompt.used_original': finalResult === originalResult
|
|
3637
3686
|
});
|
|
3638
3687
|
}
|
|
3639
3688
|
} catch (error) {
|
package/build/agent/index.js
CHANGED
|
@@ -9045,6 +9045,7 @@ var init_hashline = __esm({
|
|
|
9045
9045
|
|
|
9046
9046
|
// src/tools/vercel.js
|
|
9047
9047
|
import { tool } from "ai";
|
|
9048
|
+
import { existsSync } from "fs";
|
|
9048
9049
|
function normalizeTargets(targets) {
|
|
9049
9050
|
if (!Array.isArray(targets)) return [];
|
|
9050
9051
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -9121,6 +9122,17 @@ function parseDelegatedTargets(rawResponse) {
|
|
|
9121
9122
|
}
|
|
9122
9123
|
return normalizeTargets(fallbackTargetsFromText(trimmed));
|
|
9123
9124
|
}
|
|
9125
|
+
function splitTargetSuffix(target) {
|
|
9126
|
+
const searchStart = target.length > 2 && target[1] === ":" && /[a-zA-Z]/.test(target[0]) ? 2 : 0;
|
|
9127
|
+
const colonIdx = target.indexOf(":", searchStart);
|
|
9128
|
+
const hashIdx = target.indexOf("#");
|
|
9129
|
+
if (colonIdx !== -1 && (hashIdx === -1 || colonIdx < hashIdx)) {
|
|
9130
|
+
return { filePart: target.substring(0, colonIdx), suffix: target.substring(colonIdx) };
|
|
9131
|
+
} else if (hashIdx !== -1) {
|
|
9132
|
+
return { filePart: target.substring(0, hashIdx), suffix: target.substring(hashIdx) };
|
|
9133
|
+
}
|
|
9134
|
+
return { filePart: target, suffix: "" };
|
|
9135
|
+
}
|
|
9124
9136
|
function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, allowTests }) {
|
|
9125
9137
|
return [
|
|
9126
9138
|
"You are a code-search subagent. Your job is to find ALL relevant code locations for the given query.",
|
|
@@ -9284,10 +9296,47 @@ var init_vercel = __esm({
|
|
|
9284
9296
|
}
|
|
9285
9297
|
return fallbackResult;
|
|
9286
9298
|
}
|
|
9299
|
+
const delegateBase = options.allowedFolders?.[0] || options.cwd || ".";
|
|
9287
9300
|
const resolutionBase = searchPaths[0] || options.cwd || ".";
|
|
9288
|
-
const resolvedTargets = targets.map((target) => resolveTargetPath(target,
|
|
9301
|
+
const resolvedTargets = targets.map((target) => resolveTargetPath(target, delegateBase));
|
|
9302
|
+
const validatedTargets = [];
|
|
9303
|
+
for (const target of resolvedTargets) {
|
|
9304
|
+
const { filePart, suffix } = splitTargetSuffix(target);
|
|
9305
|
+
if (existsSync(filePart)) {
|
|
9306
|
+
validatedTargets.push(target);
|
|
9307
|
+
continue;
|
|
9308
|
+
}
|
|
9309
|
+
let fixed = false;
|
|
9310
|
+
const parts = filePart.split("/").filter(Boolean);
|
|
9311
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
9312
|
+
if (parts[i] === parts[i + 1]) {
|
|
9313
|
+
const candidate = "/" + [...parts.slice(0, i), ...parts.slice(i + 1)].join("/");
|
|
9314
|
+
if (existsSync(candidate)) {
|
|
9315
|
+
validatedTargets.push(candidate + suffix);
|
|
9316
|
+
if (debug) console.error(`[search-delegate] Fixed doubled path segment: ${filePart} \u2192 ${candidate}`);
|
|
9317
|
+
fixed = true;
|
|
9318
|
+
break;
|
|
9319
|
+
}
|
|
9320
|
+
}
|
|
9321
|
+
}
|
|
9322
|
+
if (fixed) continue;
|
|
9323
|
+
for (const altBase of [resolutionBase, options.cwd].filter(Boolean)) {
|
|
9324
|
+
if (altBase === delegateBase) continue;
|
|
9325
|
+
const altResolved = resolveTargetPath(target, altBase);
|
|
9326
|
+
const { filePart: altFile } = splitTargetSuffix(altResolved);
|
|
9327
|
+
if (existsSync(altFile)) {
|
|
9328
|
+
validatedTargets.push(altResolved);
|
|
9329
|
+
if (debug) console.error(`[search-delegate] Resolved with alt base: ${filePart} \u2192 ${altFile}`);
|
|
9330
|
+
fixed = true;
|
|
9331
|
+
break;
|
|
9332
|
+
}
|
|
9333
|
+
}
|
|
9334
|
+
if (fixed) continue;
|
|
9335
|
+
if (debug) console.error(`[search-delegate] Warning: target may not exist: ${filePart}`);
|
|
9336
|
+
validatedTargets.push(target);
|
|
9337
|
+
}
|
|
9289
9338
|
const extractOptions = {
|
|
9290
|
-
files:
|
|
9339
|
+
files: validatedTargets,
|
|
9291
9340
|
cwd: resolutionBase,
|
|
9292
9341
|
allowTests: allow_tests ?? true
|
|
9293
9342
|
};
|
|
@@ -10805,7 +10854,7 @@ var init_bashPermissions = __esm({
|
|
|
10805
10854
|
// src/agent/bashExecutor.js
|
|
10806
10855
|
import { spawn as spawn2 } from "child_process";
|
|
10807
10856
|
import { resolve as resolve2, join } from "path";
|
|
10808
|
-
import { existsSync } from "fs";
|
|
10857
|
+
import { existsSync as existsSync2 } from "fs";
|
|
10809
10858
|
function splitCommandComponents(command) {
|
|
10810
10859
|
const parts = [];
|
|
10811
10860
|
let current2 = "";
|
|
@@ -10935,7 +10984,7 @@ async function executeBashCommand(command, options = {}) {
|
|
|
10935
10984
|
let cwd = workingDirectory;
|
|
10936
10985
|
try {
|
|
10937
10986
|
cwd = resolve2(cwd);
|
|
10938
|
-
if (!
|
|
10987
|
+
if (!existsSync2(cwd)) {
|
|
10939
10988
|
throw new Error(`Working directory does not exist: ${cwd}`);
|
|
10940
10989
|
}
|
|
10941
10990
|
} catch (error) {
|
|
@@ -11191,7 +11240,7 @@ function validateExecutionOptions(options = {}) {
|
|
|
11191
11240
|
if (options.workingDirectory) {
|
|
11192
11241
|
if (typeof options.workingDirectory !== "string") {
|
|
11193
11242
|
errors.push("workingDirectory must be a string");
|
|
11194
|
-
} else if (!
|
|
11243
|
+
} else if (!existsSync2(options.workingDirectory)) {
|
|
11195
11244
|
errors.push(`workingDirectory does not exist: ${options.workingDirectory}`);
|
|
11196
11245
|
}
|
|
11197
11246
|
}
|
|
@@ -11716,7 +11765,7 @@ var init_lineEditHeuristics = __esm({
|
|
|
11716
11765
|
import { tool as tool3 } from "ai";
|
|
11717
11766
|
import { promises as fs6 } from "fs";
|
|
11718
11767
|
import { dirname, resolve as resolve4, isAbsolute as isAbsolute3, sep as sep2 } from "path";
|
|
11719
|
-
import { existsSync as
|
|
11768
|
+
import { existsSync as existsSync3 } from "fs";
|
|
11720
11769
|
function isPathAllowed(filePath, allowedFolders) {
|
|
11721
11770
|
if (!allowedFolders || allowedFolders.length === 0) {
|
|
11722
11771
|
const resolvedPath2 = safeRealpath(filePath);
|
|
@@ -11994,7 +12043,7 @@ Parameters:
|
|
|
11994
12043
|
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
11995
12044
|
return `Error editing file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
11996
12045
|
}
|
|
11997
|
-
if (!
|
|
12046
|
+
if (!existsSync3(resolvedPath)) {
|
|
11998
12047
|
return `Error editing file: File not found - ${file_path}. Verify the path is correct and the file exists. Use 'search' to find files by name, or 'create' to make a new file.`;
|
|
11999
12048
|
}
|
|
12000
12049
|
if (options.fileTracker && !options.fileTracker.isFileSeen(resolvedPath)) {
|
|
@@ -12127,10 +12176,10 @@ Important:
|
|
|
12127
12176
|
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
12128
12177
|
return `Error creating file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
12129
12178
|
}
|
|
12130
|
-
if (
|
|
12179
|
+
if (existsSync3(resolvedPath) && !overwrite) {
|
|
12131
12180
|
return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
|
|
12132
12181
|
}
|
|
12133
|
-
const existed =
|
|
12182
|
+
const existed = existsSync3(resolvedPath);
|
|
12134
12183
|
const dir = dirname(resolvedPath);
|
|
12135
12184
|
await fs6.mkdir(dir, { recursive: true });
|
|
12136
12185
|
await fs6.writeFile(resolvedPath, content, "utf-8");
|
|
@@ -30374,7 +30423,7 @@ var init_fileTracker = __esm({
|
|
|
30374
30423
|
});
|
|
30375
30424
|
|
|
30376
30425
|
// src/agent/simpleTelemetry.js
|
|
30377
|
-
import { existsSync as
|
|
30426
|
+
import { existsSync as existsSync4, mkdirSync, createWriteStream } from "fs";
|
|
30378
30427
|
import { dirname as dirname2 } from "path";
|
|
30379
30428
|
function initializeSimpleTelemetryFromOptions(options) {
|
|
30380
30429
|
const telemetry = new SimpleTelemetry({
|
|
@@ -30403,7 +30452,7 @@ var init_simpleTelemetry = __esm({
|
|
|
30403
30452
|
initializeFileExporter() {
|
|
30404
30453
|
try {
|
|
30405
30454
|
const dir = dirname2(this.filePath);
|
|
30406
|
-
if (!
|
|
30455
|
+
if (!existsSync4(dir)) {
|
|
30407
30456
|
mkdirSync(dir, { recursive: true });
|
|
30408
30457
|
}
|
|
30409
30458
|
this.stream = createWriteStream(this.filePath, { flags: "a" });
|
|
@@ -70834,7 +70883,7 @@ When troubleshooting:
|
|
|
70834
70883
|
});
|
|
70835
70884
|
|
|
70836
70885
|
// src/agent/mcp/config.js
|
|
70837
|
-
import { readFileSync, existsSync as
|
|
70886
|
+
import { readFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
70838
70887
|
import { join as join2, dirname as dirname3 } from "path";
|
|
70839
70888
|
import { homedir } from "os";
|
|
70840
70889
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
@@ -70889,7 +70938,7 @@ function loadMCPConfigurationFromPath(configPath) {
|
|
|
70889
70938
|
if (!configPath) {
|
|
70890
70939
|
throw new Error("Config path is required");
|
|
70891
70940
|
}
|
|
70892
|
-
if (!
|
|
70941
|
+
if (!existsSync5(configPath)) {
|
|
70893
70942
|
throw new Error(`MCP configuration file not found: ${configPath}`);
|
|
70894
70943
|
}
|
|
70895
70944
|
try {
|
|
@@ -70918,7 +70967,7 @@ function loadMCPConfiguration() {
|
|
|
70918
70967
|
].filter(Boolean);
|
|
70919
70968
|
let config = null;
|
|
70920
70969
|
for (const configPath of configPaths) {
|
|
70921
|
-
if (
|
|
70970
|
+
if (existsSync5(configPath)) {
|
|
70922
70971
|
try {
|
|
70923
70972
|
const content = readFileSync(configPath, "utf8");
|
|
70924
70973
|
config = JSON.parse(content);
|
|
@@ -79122,7 +79171,7 @@ var init_parser7 = __esm({
|
|
|
79122
79171
|
});
|
|
79123
79172
|
|
|
79124
79173
|
// src/agent/skills/registry.js
|
|
79125
|
-
import { existsSync as
|
|
79174
|
+
import { existsSync as existsSync6 } from "fs";
|
|
79126
79175
|
import { readdir as readdir2, readFile as readFile2, realpath as realpath2, lstat as lstat2 } from "fs/promises";
|
|
79127
79176
|
import { resolve as resolve6, join as join3, isAbsolute as isAbsolute5, sep as sep4, relative } from "path";
|
|
79128
79177
|
function isPathInside(basePath, targetPath) {
|
|
@@ -79215,7 +79264,7 @@ var init_registry = __esm({
|
|
|
79215
79264
|
return resolvedReal;
|
|
79216
79265
|
}
|
|
79217
79266
|
async _scanSkillDir(dirPath) {
|
|
79218
|
-
if (!
|
|
79267
|
+
if (!existsSync6(dirPath)) return [];
|
|
79219
79268
|
let entries;
|
|
79220
79269
|
try {
|
|
79221
79270
|
entries = await readdir2(dirPath, { withFileTypes: true });
|
|
@@ -79255,7 +79304,7 @@ var init_registry = __esm({
|
|
|
79255
79304
|
}
|
|
79256
79305
|
continue;
|
|
79257
79306
|
}
|
|
79258
|
-
if (!
|
|
79307
|
+
if (!existsSync6(skillFilePath)) continue;
|
|
79259
79308
|
const { skill, error } = await parseSkillFile(skillFilePath, entry.name);
|
|
79260
79309
|
if (!skill) {
|
|
79261
79310
|
if (error) {
|
|
@@ -81771,7 +81820,7 @@ import { createAmazonBedrock as createAmazonBedrock2 } from "@ai-sdk/amazon-bedr
|
|
|
81771
81820
|
import { streamText as streamText2, tool as tool5, stepCountIs, jsonSchema } from "ai";
|
|
81772
81821
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
81773
81822
|
import { EventEmitter as EventEmitter5 } from "events";
|
|
81774
|
-
import { existsSync as
|
|
81823
|
+
import { existsSync as existsSync7 } from "fs";
|
|
81775
81824
|
import { readFile as readFile3, stat, readdir as readdir3 } from "fs/promises";
|
|
81776
81825
|
import { resolve as resolve7, isAbsolute as isAbsolute6, dirname as dirname5, basename, normalize as normalize2, sep as sep5 } from "path";
|
|
81777
81826
|
var ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
@@ -83782,7 +83831,7 @@ var init_ProbeAgent = __esm({
|
|
|
83782
83831
|
} else {
|
|
83783
83832
|
guidanceCandidates = ["agents.md", "claude.md"];
|
|
83784
83833
|
}
|
|
83785
|
-
if (!
|
|
83834
|
+
if (!existsSync7(rootDirectory)) {
|
|
83786
83835
|
this._architectureContextLoaded = true;
|
|
83787
83836
|
return null;
|
|
83788
83837
|
}
|
|
@@ -84554,9 +84603,10 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
84554
84603
|
}
|
|
84555
84604
|
if (completionAttempted && this.completionPrompt && !options._completionPromptProcessed) {
|
|
84556
84605
|
if (this.debug) {
|
|
84557
|
-
console.log("[DEBUG] Running completion prompt
|
|
84606
|
+
console.log("[DEBUG] Running completion prompt as continuation of current session...");
|
|
84558
84607
|
}
|
|
84559
84608
|
try {
|
|
84609
|
+
const originalResult = finalResult;
|
|
84560
84610
|
if (this.tracer) {
|
|
84561
84611
|
this.tracer.recordEvent("completion_prompt.started", {
|
|
84562
84612
|
"completion_prompt.original_result_length": finalResult?.length || 0
|
|
@@ -84569,24 +84619,66 @@ Here is the result to review:
|
|
|
84569
84619
|
${finalResult}
|
|
84570
84620
|
</result>
|
|
84571
84621
|
|
|
84572
|
-
|
|
84573
|
-
|
|
84574
|
-
|
|
84575
|
-
|
|
84576
|
-
|
|
84577
|
-
|
|
84578
|
-
|
|
84579
|
-
|
|
84580
|
-
|
|
84622
|
+
Double-check your response based on the criteria above. If everything looks good, respond with your previous answer exactly as-is using attempt_completion. If something needs to be fixed or is missing, do it now, then respond with the COMPLETE updated answer (everything you did in total, not just the fix) using attempt_completion.`;
|
|
84623
|
+
currentMessages.push({ role: "user", content: completionPromptMessage });
|
|
84624
|
+
completionResult = null;
|
|
84625
|
+
completionAttempted = false;
|
|
84626
|
+
const completionMaxIterations = 5;
|
|
84627
|
+
const completionStreamOptions = {
|
|
84628
|
+
model: this.provider ? this.provider(this.model) : this.model,
|
|
84629
|
+
messages: this.prepareMessagesWithImages(currentMessages),
|
|
84630
|
+
tools: tools2,
|
|
84631
|
+
stopWhen: stepCountIs(completionMaxIterations),
|
|
84632
|
+
maxTokens: maxResponseTokens,
|
|
84633
|
+
temperature: 0.3,
|
|
84634
|
+
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
84635
|
+
if (usage) {
|
|
84636
|
+
this.tokenCounter.recordUsage(usage);
|
|
84637
|
+
}
|
|
84638
|
+
if (options.onStream && text) {
|
|
84639
|
+
options.onStream(text);
|
|
84640
|
+
}
|
|
84641
|
+
if (this.debug) {
|
|
84642
|
+
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
84643
|
+
}
|
|
84644
|
+
}
|
|
84645
|
+
};
|
|
84646
|
+
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
84647
|
+
if (providerOpts) {
|
|
84648
|
+
completionStreamOptions.providerOptions = providerOpts;
|
|
84649
|
+
}
|
|
84650
|
+
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
84651
|
+
const cpFinalText = await cpResult.text;
|
|
84652
|
+
const cpUsage = await cpResult.usage;
|
|
84653
|
+
if (cpUsage) {
|
|
84654
|
+
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
84655
|
+
}
|
|
84656
|
+
const cpMessages = await cpResult.response?.messages;
|
|
84657
|
+
if (cpMessages) {
|
|
84658
|
+
for (const msg of cpMessages) {
|
|
84659
|
+
currentMessages.push(msg);
|
|
84660
|
+
}
|
|
84661
|
+
}
|
|
84662
|
+
if (completionResult) {
|
|
84663
|
+
finalResult = completionResult;
|
|
84664
|
+
completionAttempted = true;
|
|
84665
|
+
} else if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
84666
|
+
finalResult = cpFinalText;
|
|
84667
|
+
completionAttempted = true;
|
|
84668
|
+
} else {
|
|
84669
|
+
finalResult = originalResult;
|
|
84670
|
+
completionAttempted = true;
|
|
84671
|
+
if (this.debug) {
|
|
84672
|
+
console.log("[DEBUG] Completion prompt returned empty result, keeping original.");
|
|
84673
|
+
}
|
|
84581
84674
|
}
|
|
84582
|
-
this._extractedRawBlocks = savedExtractedBlocks;
|
|
84583
|
-
finalResult = completionResult2;
|
|
84584
84675
|
if (this.debug) {
|
|
84585
|
-
console.log(`[DEBUG] Completion prompt finished.
|
|
84676
|
+
console.log(`[DEBUG] Completion prompt finished. Final result length: ${finalResult?.length || 0}`);
|
|
84586
84677
|
}
|
|
84587
84678
|
if (this.tracer) {
|
|
84588
84679
|
this.tracer.recordEvent("completion_prompt.completed", {
|
|
84589
|
-
"completion_prompt.final_result_length": finalResult?.length || 0
|
|
84680
|
+
"completion_prompt.final_result_length": finalResult?.length || 0,
|
|
84681
|
+
"completion_prompt.used_original": finalResult === originalResult
|
|
84590
84682
|
});
|
|
84591
84683
|
}
|
|
84592
84684
|
} catch (error) {
|
|
@@ -85308,7 +85400,7 @@ import {
|
|
|
85308
85400
|
ListToolsRequestSchema as ListToolsRequestSchema2,
|
|
85309
85401
|
McpError
|
|
85310
85402
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
85311
|
-
import { readFileSync as readFileSync2, existsSync as
|
|
85403
|
+
import { readFileSync as readFileSync2, existsSync as existsSync8 } from "fs";
|
|
85312
85404
|
import { resolve as resolve8 } from "path";
|
|
85313
85405
|
|
|
85314
85406
|
// src/agent/acp/server.js
|
|
@@ -85984,7 +86076,7 @@ function readInputContent(input) {
|
|
|
85984
86076
|
if (!input) return null;
|
|
85985
86077
|
try {
|
|
85986
86078
|
const resolvedPath = resolve8(input);
|
|
85987
|
-
if (
|
|
86079
|
+
if (existsSync8(resolvedPath)) {
|
|
85988
86080
|
return readFileSync2(resolvedPath, "utf-8").trim();
|
|
85989
86081
|
}
|
|
85990
86082
|
} catch (error) {
|
|
@@ -86672,7 +86764,7 @@ async function main() {
|
|
|
86672
86764
|
bashConfig.timeout = timeout;
|
|
86673
86765
|
}
|
|
86674
86766
|
if (config.bashWorkingDir) {
|
|
86675
|
-
if (!
|
|
86767
|
+
if (!existsSync8(config.bashWorkingDir)) {
|
|
86676
86768
|
console.error(`Error: Bash working directory does not exist: ${config.bashWorkingDir}`);
|
|
86677
86769
|
process.exit(1);
|
|
86678
86770
|
}
|
package/build/tools/vercel.js
CHANGED
|
@@ -10,6 +10,7 @@ import { extract } from '../extract.js';
|
|
|
10
10
|
import { delegate } from '../delegate.js';
|
|
11
11
|
import { analyzeAll } from './analyzeAll.js';
|
|
12
12
|
import { searchSchema, querySchema, extractSchema, delegateSchema, analyzeAllSchema, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, parseTargets, parseAndResolvePaths, resolveTargetPath } from './common.js';
|
|
13
|
+
import { existsSync } from 'fs';
|
|
13
14
|
import { formatErrorForAI } from '../utils/error-types.js';
|
|
14
15
|
import { annotateOutputWithHashes } from './hashline.js';
|
|
15
16
|
|
|
@@ -118,6 +119,18 @@ function parseDelegatedTargets(rawResponse) {
|
|
|
118
119
|
return normalizeTargets(fallbackTargetsFromText(trimmed));
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
function splitTargetSuffix(target) {
|
|
123
|
+
const searchStart = (target.length > 2 && target[1] === ':' && /[a-zA-Z]/.test(target[0])) ? 2 : 0;
|
|
124
|
+
const colonIdx = target.indexOf(':', searchStart);
|
|
125
|
+
const hashIdx = target.indexOf('#');
|
|
126
|
+
if (colonIdx !== -1 && (hashIdx === -1 || colonIdx < hashIdx)) {
|
|
127
|
+
return { filePart: target.substring(0, colonIdx), suffix: target.substring(colonIdx) };
|
|
128
|
+
} else if (hashIdx !== -1) {
|
|
129
|
+
return { filePart: target.substring(0, hashIdx), suffix: target.substring(hashIdx) };
|
|
130
|
+
}
|
|
131
|
+
return { filePart: target, suffix: '' };
|
|
132
|
+
}
|
|
133
|
+
|
|
121
134
|
function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, allowTests }) {
|
|
122
135
|
return [
|
|
123
136
|
'You are a code-search subagent. Your job is to find ALL relevant code locations for the given query.',
|
|
@@ -286,13 +299,61 @@ export const searchTool = (options = {}) => {
|
|
|
286
299
|
return fallbackResult;
|
|
287
300
|
}
|
|
288
301
|
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
|
|
302
|
+
// The delegate runs from workspace root (allowedFolders[0] or cwd), NOT from searchPaths[0].
|
|
303
|
+
// It returns paths relative to that workspace root. Resolve against the same base.
|
|
304
|
+
const delegateBase = options.allowedFolders?.[0] || options.cwd || '.';
|
|
292
305
|
const resolutionBase = searchPaths[0] || options.cwd || '.';
|
|
293
|
-
const resolvedTargets = targets.map(target => resolveTargetPath(target,
|
|
306
|
+
const resolvedTargets = targets.map(target => resolveTargetPath(target, delegateBase));
|
|
307
|
+
|
|
308
|
+
// Auto-fix: detect and repair invalid paths (doubled segments, AI hallucinations)
|
|
309
|
+
const validatedTargets = [];
|
|
310
|
+
for (const target of resolvedTargets) {
|
|
311
|
+
const { filePart, suffix } = splitTargetSuffix(target);
|
|
312
|
+
|
|
313
|
+
// 1. Path exists as-is
|
|
314
|
+
if (existsSync(filePart)) {
|
|
315
|
+
validatedTargets.push(target);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// 2. Detect doubled directory segments: /ws/proj/proj/src → /ws/proj/src
|
|
320
|
+
let fixed = false;
|
|
321
|
+
const parts = filePart.split('/').filter(Boolean);
|
|
322
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
323
|
+
if (parts[i] === parts[i + 1]) {
|
|
324
|
+
const candidate = '/' + [...parts.slice(0, i), ...parts.slice(i + 1)].join('/');
|
|
325
|
+
if (existsSync(candidate)) {
|
|
326
|
+
validatedTargets.push(candidate + suffix);
|
|
327
|
+
if (debug) console.error(`[search-delegate] Fixed doubled path segment: ${filePart} → ${candidate}`);
|
|
328
|
+
fixed = true;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (fixed) continue;
|
|
334
|
+
|
|
335
|
+
// 3. Try resolving against alternative bases (searchPaths[0], cwd)
|
|
336
|
+
for (const altBase of [resolutionBase, options.cwd].filter(Boolean)) {
|
|
337
|
+
if (altBase === delegateBase) continue;
|
|
338
|
+
const altResolved = resolveTargetPath(target, altBase);
|
|
339
|
+
const { filePart: altFile } = splitTargetSuffix(altResolved);
|
|
340
|
+
if (existsSync(altFile)) {
|
|
341
|
+
validatedTargets.push(altResolved);
|
|
342
|
+
if (debug) console.error(`[search-delegate] Resolved with alt base: ${filePart} → ${altFile}`);
|
|
343
|
+
fixed = true;
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (fixed) continue;
|
|
348
|
+
|
|
349
|
+
// 4. Keep target anyway (probe binary will report the error)
|
|
350
|
+
// but log a warning
|
|
351
|
+
if (debug) console.error(`[search-delegate] Warning: target may not exist: ${filePart}`);
|
|
352
|
+
validatedTargets.push(target);
|
|
353
|
+
}
|
|
354
|
+
|
|
294
355
|
const extractOptions = {
|
|
295
|
-
files:
|
|
356
|
+
files: validatedTargets,
|
|
296
357
|
cwd: resolutionBase,
|
|
297
358
|
allowTests: allow_tests ?? true
|
|
298
359
|
};
|