@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
package/cjs/index.cjs
CHANGED
|
@@ -108797,9 +108797,10 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
108797
108797
|
}
|
|
108798
108798
|
if (completionAttempted && this.completionPrompt && !options._completionPromptProcessed) {
|
|
108799
108799
|
if (this.debug) {
|
|
108800
|
-
console.log("[DEBUG] Running completion prompt
|
|
108800
|
+
console.log("[DEBUG] Running completion prompt as continuation of current session...");
|
|
108801
108801
|
}
|
|
108802
108802
|
try {
|
|
108803
|
+
const originalResult = finalResult;
|
|
108803
108804
|
if (this.tracer) {
|
|
108804
108805
|
this.tracer.recordEvent("completion_prompt.started", {
|
|
108805
108806
|
"completion_prompt.original_result_length": finalResult?.length || 0
|
|
@@ -108812,24 +108813,66 @@ Here is the result to review:
|
|
|
108812
108813
|
${finalResult}
|
|
108813
108814
|
</result>
|
|
108814
108815
|
|
|
108815
|
-
|
|
108816
|
-
|
|
108817
|
-
|
|
108818
|
-
|
|
108819
|
-
|
|
108820
|
-
|
|
108821
|
-
|
|
108822
|
-
|
|
108823
|
-
|
|
108816
|
+
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.`;
|
|
108817
|
+
currentMessages.push({ role: "user", content: completionPromptMessage });
|
|
108818
|
+
completionResult = null;
|
|
108819
|
+
completionAttempted = false;
|
|
108820
|
+
const completionMaxIterations = 5;
|
|
108821
|
+
const completionStreamOptions = {
|
|
108822
|
+
model: this.provider ? this.provider(this.model) : this.model,
|
|
108823
|
+
messages: this.prepareMessagesWithImages(currentMessages),
|
|
108824
|
+
tools: tools2,
|
|
108825
|
+
stopWhen: (0, import_ai4.stepCountIs)(completionMaxIterations),
|
|
108826
|
+
maxTokens: maxResponseTokens,
|
|
108827
|
+
temperature: 0.3,
|
|
108828
|
+
onStepFinish: ({ toolResults, text, finishReason, usage }) => {
|
|
108829
|
+
if (usage) {
|
|
108830
|
+
this.tokenCounter.recordUsage(usage);
|
|
108831
|
+
}
|
|
108832
|
+
if (options.onStream && text) {
|
|
108833
|
+
options.onStream(text);
|
|
108834
|
+
}
|
|
108835
|
+
if (this.debug) {
|
|
108836
|
+
console.log(`[DEBUG] Completion prompt step finished (reason: ${finishReason}, tools: ${toolResults?.length || 0})`);
|
|
108837
|
+
}
|
|
108838
|
+
}
|
|
108839
|
+
};
|
|
108840
|
+
const providerOpts = this._buildThinkingProviderOptions(maxResponseTokens);
|
|
108841
|
+
if (providerOpts) {
|
|
108842
|
+
completionStreamOptions.providerOptions = providerOpts;
|
|
108843
|
+
}
|
|
108844
|
+
const cpResult = await this.streamTextWithRetryAndFallback(completionStreamOptions);
|
|
108845
|
+
const cpFinalText = await cpResult.text;
|
|
108846
|
+
const cpUsage = await cpResult.usage;
|
|
108847
|
+
if (cpUsage) {
|
|
108848
|
+
this.tokenCounter.recordUsage(cpUsage, cpResult.experimental_providerMetadata);
|
|
108849
|
+
}
|
|
108850
|
+
const cpMessages = await cpResult.response?.messages;
|
|
108851
|
+
if (cpMessages) {
|
|
108852
|
+
for (const msg of cpMessages) {
|
|
108853
|
+
currentMessages.push(msg);
|
|
108854
|
+
}
|
|
108855
|
+
}
|
|
108856
|
+
if (completionResult) {
|
|
108857
|
+
finalResult = completionResult;
|
|
108858
|
+
completionAttempted = true;
|
|
108859
|
+
} else if (cpFinalText && cpFinalText.trim().length > 0) {
|
|
108860
|
+
finalResult = cpFinalText;
|
|
108861
|
+
completionAttempted = true;
|
|
108862
|
+
} else {
|
|
108863
|
+
finalResult = originalResult;
|
|
108864
|
+
completionAttempted = true;
|
|
108865
|
+
if (this.debug) {
|
|
108866
|
+
console.log("[DEBUG] Completion prompt returned empty result, keeping original.");
|
|
108867
|
+
}
|
|
108824
108868
|
}
|
|
108825
|
-
this._extractedRawBlocks = savedExtractedBlocks;
|
|
108826
|
-
finalResult = completionResult2;
|
|
108827
108869
|
if (this.debug) {
|
|
108828
|
-
console.log(`[DEBUG] Completion prompt finished.
|
|
108870
|
+
console.log(`[DEBUG] Completion prompt finished. Final result length: ${finalResult?.length || 0}`);
|
|
108829
108871
|
}
|
|
108830
108872
|
if (this.tracer) {
|
|
108831
108873
|
this.tracer.recordEvent("completion_prompt.completed", {
|
|
108832
|
-
"completion_prompt.final_result_length": finalResult?.length || 0
|
|
108874
|
+
"completion_prompt.final_result_length": finalResult?.length || 0,
|
|
108875
|
+
"completion_prompt.used_original": finalResult === originalResult
|
|
108833
108876
|
});
|
|
108834
108877
|
}
|
|
108835
108878
|
} catch (error2) {
|
|
@@ -110587,6 +110630,17 @@ function parseDelegatedTargets(rawResponse) {
|
|
|
110587
110630
|
}
|
|
110588
110631
|
return normalizeTargets(fallbackTargetsFromText(trimmed));
|
|
110589
110632
|
}
|
|
110633
|
+
function splitTargetSuffix(target) {
|
|
110634
|
+
const searchStart = target.length > 2 && target[1] === ":" && /[a-zA-Z]/.test(target[0]) ? 2 : 0;
|
|
110635
|
+
const colonIdx = target.indexOf(":", searchStart);
|
|
110636
|
+
const hashIdx = target.indexOf("#");
|
|
110637
|
+
if (colonIdx !== -1 && (hashIdx === -1 || colonIdx < hashIdx)) {
|
|
110638
|
+
return { filePart: target.substring(0, colonIdx), suffix: target.substring(colonIdx) };
|
|
110639
|
+
} else if (hashIdx !== -1) {
|
|
110640
|
+
return { filePart: target.substring(0, hashIdx), suffix: target.substring(hashIdx) };
|
|
110641
|
+
}
|
|
110642
|
+
return { filePart: target, suffix: "" };
|
|
110643
|
+
}
|
|
110590
110644
|
function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, allowTests }) {
|
|
110591
110645
|
return [
|
|
110592
110646
|
"You are a code-search subagent. Your job is to find ALL relevant code locations for the given query.",
|
|
@@ -110615,7 +110669,7 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
110615
110669
|
"Deduplicate targets. Do NOT explain or answer - ONLY return the JSON targets."
|
|
110616
110670
|
].join("\n");
|
|
110617
110671
|
}
|
|
110618
|
-
var import_ai5, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
|
|
110672
|
+
var import_ai5, import_fs11, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
|
|
110619
110673
|
var init_vercel = __esm({
|
|
110620
110674
|
"src/tools/vercel.js"() {
|
|
110621
110675
|
"use strict";
|
|
@@ -110626,6 +110680,7 @@ var init_vercel = __esm({
|
|
|
110626
110680
|
init_delegate();
|
|
110627
110681
|
init_analyzeAll();
|
|
110628
110682
|
init_common2();
|
|
110683
|
+
import_fs11 = require("fs");
|
|
110629
110684
|
init_error_types();
|
|
110630
110685
|
init_hashline();
|
|
110631
110686
|
CODE_SEARCH_SCHEMA = {
|
|
@@ -110751,10 +110806,47 @@ var init_vercel = __esm({
|
|
|
110751
110806
|
}
|
|
110752
110807
|
return fallbackResult;
|
|
110753
110808
|
}
|
|
110809
|
+
const delegateBase = options.allowedFolders?.[0] || options.cwd || ".";
|
|
110754
110810
|
const resolutionBase = searchPaths[0] || options.cwd || ".";
|
|
110755
|
-
const resolvedTargets = targets.map((target) => resolveTargetPath(target,
|
|
110811
|
+
const resolvedTargets = targets.map((target) => resolveTargetPath(target, delegateBase));
|
|
110812
|
+
const validatedTargets = [];
|
|
110813
|
+
for (const target of resolvedTargets) {
|
|
110814
|
+
const { filePart, suffix } = splitTargetSuffix(target);
|
|
110815
|
+
if ((0, import_fs11.existsSync)(filePart)) {
|
|
110816
|
+
validatedTargets.push(target);
|
|
110817
|
+
continue;
|
|
110818
|
+
}
|
|
110819
|
+
let fixed = false;
|
|
110820
|
+
const parts = filePart.split("/").filter(Boolean);
|
|
110821
|
+
for (let i5 = 0; i5 < parts.length - 1; i5++) {
|
|
110822
|
+
if (parts[i5] === parts[i5 + 1]) {
|
|
110823
|
+
const candidate = "/" + [...parts.slice(0, i5), ...parts.slice(i5 + 1)].join("/");
|
|
110824
|
+
if ((0, import_fs11.existsSync)(candidate)) {
|
|
110825
|
+
validatedTargets.push(candidate + suffix);
|
|
110826
|
+
if (debug) console.error(`[search-delegate] Fixed doubled path segment: ${filePart} \u2192 ${candidate}`);
|
|
110827
|
+
fixed = true;
|
|
110828
|
+
break;
|
|
110829
|
+
}
|
|
110830
|
+
}
|
|
110831
|
+
}
|
|
110832
|
+
if (fixed) continue;
|
|
110833
|
+
for (const altBase of [resolutionBase, options.cwd].filter(Boolean)) {
|
|
110834
|
+
if (altBase === delegateBase) continue;
|
|
110835
|
+
const altResolved = resolveTargetPath(target, altBase);
|
|
110836
|
+
const { filePart: altFile } = splitTargetSuffix(altResolved);
|
|
110837
|
+
if ((0, import_fs11.existsSync)(altFile)) {
|
|
110838
|
+
validatedTargets.push(altResolved);
|
|
110839
|
+
if (debug) console.error(`[search-delegate] Resolved with alt base: ${filePart} \u2192 ${altFile}`);
|
|
110840
|
+
fixed = true;
|
|
110841
|
+
break;
|
|
110842
|
+
}
|
|
110843
|
+
}
|
|
110844
|
+
if (fixed) continue;
|
|
110845
|
+
if (debug) console.error(`[search-delegate] Warning: target may not exist: ${filePart}`);
|
|
110846
|
+
validatedTargets.push(target);
|
|
110847
|
+
}
|
|
110756
110848
|
const extractOptions = {
|
|
110757
|
-
files:
|
|
110849
|
+
files: validatedTargets,
|
|
110758
110850
|
cwd: resolutionBase,
|
|
110759
110851
|
allowTests: allow_tests ?? true
|
|
110760
110852
|
};
|
|
@@ -111307,7 +111399,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
|
|
|
111307
111399
|
Example: <extract><targets>${file_path}#${symbol15}</targets></extract>`;
|
|
111308
111400
|
}
|
|
111309
111401
|
}
|
|
111310
|
-
const content = await
|
|
111402
|
+
const content = await import_fs12.promises.readFile(resolvedPath2, "utf-8");
|
|
111311
111403
|
const lines = content.split("\n");
|
|
111312
111404
|
if (position) {
|
|
111313
111405
|
const refIndent = detectBaseIndent(symbolInfo.code);
|
|
@@ -111318,7 +111410,7 @@ Example: <extract><targets>${file_path}#${symbol15}</targets></extract>`;
|
|
|
111318
111410
|
} else {
|
|
111319
111411
|
lines.splice(symbolInfo.startLine - 1, 0, ...newLines, "");
|
|
111320
111412
|
}
|
|
111321
|
-
await
|
|
111413
|
+
await import_fs12.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
|
|
111322
111414
|
if (fileTracker) {
|
|
111323
111415
|
const updated = await findSymbol(resolvedPath2, symbol15, cwd || process.cwd());
|
|
111324
111416
|
if (updated) {
|
|
@@ -111336,7 +111428,7 @@ Example: <extract><targets>${file_path}#${symbol15}</targets></extract>`;
|
|
|
111336
111428
|
const reindented = reindent(new_string, originalIndent);
|
|
111337
111429
|
const newLines = reindented.split("\n");
|
|
111338
111430
|
lines.splice(symbolInfo.startLine - 1, symbolInfo.endLine - symbolInfo.startLine + 1, ...newLines);
|
|
111339
|
-
await
|
|
111431
|
+
await import_fs12.promises.writeFile(resolvedPath2, lines.join("\n"), "utf-8");
|
|
111340
111432
|
if (fileTracker) {
|
|
111341
111433
|
const updated = await findSymbol(resolvedPath2, symbol15, cwd || process.cwd());
|
|
111342
111434
|
if (updated) {
|
|
@@ -111391,7 +111483,7 @@ async function handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_li
|
|
|
111391
111483
|
if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
|
|
111392
111484
|
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before the line, or position="after" to insert after it.';
|
|
111393
111485
|
}
|
|
111394
|
-
const content = await
|
|
111486
|
+
const content = await import_fs12.promises.readFile(resolvedPath2, "utf-8");
|
|
111395
111487
|
const fileLines = content.split("\n");
|
|
111396
111488
|
if (startLine > fileLines.length) {
|
|
111397
111489
|
return `Error editing file: Line ${startLine} is beyond file length (${fileLines.length} lines). Use 'extract' to read the current file content.`;
|
|
@@ -111420,20 +111512,20 @@ async function handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_li
|
|
|
111420
111512
|
const newLines = cleaned === "" ? [] : cleaned.split("\n");
|
|
111421
111513
|
if (position === "after") {
|
|
111422
111514
|
fileLines.splice(startLine, 0, ...newLines);
|
|
111423
|
-
await
|
|
111515
|
+
await import_fs12.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
|
|
111424
111516
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
|
|
111425
111517
|
const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted after line ${startLine}`;
|
|
111426
111518
|
return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine, action, modifications);
|
|
111427
111519
|
} else if (position === "before") {
|
|
111428
111520
|
fileLines.splice(startLine - 1, 0, ...newLines);
|
|
111429
|
-
await
|
|
111521
|
+
await import_fs12.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
|
|
111430
111522
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
|
|
111431
111523
|
const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted before line ${startLine}`;
|
|
111432
111524
|
return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
111433
111525
|
} else {
|
|
111434
111526
|
const replacedCount = endLine - startLine + 1;
|
|
111435
111527
|
fileLines.splice(startLine - 1, replacedCount, ...newLines);
|
|
111436
|
-
await
|
|
111528
|
+
await import_fs12.promises.writeFile(resolvedPath2, fileLines.join("\n"), "utf-8");
|
|
111437
111529
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath2);
|
|
111438
111530
|
let action;
|
|
111439
111531
|
if (newLines.length === 0) {
|
|
@@ -111446,14 +111538,14 @@ async function handleLineEdit({ resolvedPath: resolvedPath2, file_path, start_li
|
|
|
111446
111538
|
return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
111447
111539
|
}
|
|
111448
111540
|
}
|
|
111449
|
-
var import_ai6,
|
|
111541
|
+
var import_ai6, import_fs12, import_path16, import_fs13, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
111450
111542
|
var init_edit = __esm({
|
|
111451
111543
|
"src/tools/edit.js"() {
|
|
111452
111544
|
"use strict";
|
|
111453
111545
|
import_ai6 = require("ai");
|
|
111454
|
-
import_fs11 = require("fs");
|
|
111455
|
-
import_path16 = require("path");
|
|
111456
111546
|
import_fs12 = require("fs");
|
|
111547
|
+
import_path16 = require("path");
|
|
111548
|
+
import_fs13 = require("fs");
|
|
111457
111549
|
init_path_validation();
|
|
111458
111550
|
init_fuzzyMatch();
|
|
111459
111551
|
init_symbolEdit();
|
|
@@ -111537,7 +111629,7 @@ Parameters:
|
|
|
111537
111629
|
const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
|
|
111538
111630
|
return `Error editing file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
111539
111631
|
}
|
|
111540
|
-
if (!(0,
|
|
111632
|
+
if (!(0, import_fs13.existsSync)(resolvedPath2)) {
|
|
111541
111633
|
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.`;
|
|
111542
111634
|
}
|
|
111543
111635
|
if (options.fileTracker && !options.fileTracker.isFileSeen(resolvedPath2)) {
|
|
@@ -111567,7 +111659,7 @@ Example: <extract><targets>${displayPath}</targets></extract>`;
|
|
|
111567
111659
|
Example: <extract><targets>${displayPath}</targets></extract>`;
|
|
111568
111660
|
}
|
|
111569
111661
|
}
|
|
111570
|
-
const content = await
|
|
111662
|
+
const content = await import_fs12.promises.readFile(resolvedPath2, "utf-8");
|
|
111571
111663
|
let matchTarget = old_string;
|
|
111572
111664
|
let matchStrategy = "exact";
|
|
111573
111665
|
if (!content.includes(old_string)) {
|
|
@@ -111599,7 +111691,7 @@ Example: <extract><targets>${displayPath}</targets></extract>`;
|
|
|
111599
111691
|
if (newContent === content) {
|
|
111600
111692
|
return `Error editing file: No changes made - the replacement result is identical to the original. Verify that old_string and new_string are actually different. If fuzzy matching was used, the matched text may already equal new_string.`;
|
|
111601
111693
|
}
|
|
111602
|
-
await
|
|
111694
|
+
await import_fs12.promises.writeFile(resolvedPath2, newContent, "utf-8");
|
|
111603
111695
|
if (options.fileTracker) {
|
|
111604
111696
|
await options.fileTracker.trackFileAfterWrite(resolvedPath2);
|
|
111605
111697
|
options.fileTracker.recordTextEdit(resolvedPath2);
|
|
@@ -111670,13 +111762,13 @@ Important:
|
|
|
111670
111762
|
const relativePath = toRelativePath(resolvedPath2, workspaceRoot);
|
|
111671
111763
|
return `Error creating file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
111672
111764
|
}
|
|
111673
|
-
if ((0,
|
|
111765
|
+
if ((0, import_fs13.existsSync)(resolvedPath2) && !overwrite) {
|
|
111674
111766
|
return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
|
|
111675
111767
|
}
|
|
111676
|
-
const existed = (0,
|
|
111768
|
+
const existed = (0, import_fs13.existsSync)(resolvedPath2);
|
|
111677
111769
|
const dir = (0, import_path16.dirname)(resolvedPath2);
|
|
111678
|
-
await
|
|
111679
|
-
await
|
|
111770
|
+
await import_fs12.promises.mkdir(dir, { recursive: true });
|
|
111771
|
+
await import_fs12.promises.writeFile(resolvedPath2, content, "utf-8");
|
|
111680
111772
|
if (options.fileTracker) await options.fileTracker.trackFileAfterWrite(resolvedPath2);
|
|
111681
111773
|
const action = existed && overwrite ? "overwrote" : "created";
|
|
111682
111774
|
const bytes = Buffer.byteLength(content, "utf-8");
|
|
@@ -112318,10 +112410,10 @@ async function listFilesByLevel(options) {
|
|
|
112318
112410
|
maxFiles = 100,
|
|
112319
112411
|
respectGitignore = true
|
|
112320
112412
|
} = options;
|
|
112321
|
-
if (!
|
|
112413
|
+
if (!import_fs14.default.existsSync(directory)) {
|
|
112322
112414
|
throw new Error(`Directory does not exist: ${directory}`);
|
|
112323
112415
|
}
|
|
112324
|
-
const gitDirExists =
|
|
112416
|
+
const gitDirExists = import_fs14.default.existsSync(import_path17.default.join(directory, ".git"));
|
|
112325
112417
|
if (gitDirExists && respectGitignore) {
|
|
112326
112418
|
try {
|
|
112327
112419
|
return await listFilesUsingGit(directory, maxFiles);
|
|
@@ -112352,7 +112444,7 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
|
|
|
112352
112444
|
while (queue.length > 0 && result.length < maxFiles) {
|
|
112353
112445
|
const { dir, level } = queue.shift();
|
|
112354
112446
|
try {
|
|
112355
|
-
const entries =
|
|
112447
|
+
const entries = import_fs14.default.readdirSync(dir, { withFileTypes: true });
|
|
112356
112448
|
const files = entries.filter((entry) => {
|
|
112357
112449
|
const fullPath = import_path17.default.join(dir, entry.name);
|
|
112358
112450
|
return getEntryTypeSync(entry, fullPath).isFile;
|
|
@@ -112383,11 +112475,11 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
|
|
|
112383
112475
|
}
|
|
112384
112476
|
function loadGitignorePatterns(directory) {
|
|
112385
112477
|
const gitignorePath = import_path17.default.join(directory, ".gitignore");
|
|
112386
|
-
if (!
|
|
112478
|
+
if (!import_fs14.default.existsSync(gitignorePath)) {
|
|
112387
112479
|
return [];
|
|
112388
112480
|
}
|
|
112389
112481
|
try {
|
|
112390
|
-
const content =
|
|
112482
|
+
const content = import_fs14.default.readFileSync(gitignorePath, "utf8");
|
|
112391
112483
|
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
112392
112484
|
} catch (error2) {
|
|
112393
112485
|
console.error(`Warning: Could not read .gitignore: ${error2.message}`);
|
|
@@ -112405,11 +112497,11 @@ function shouldIgnore(filePath, ignorePatterns) {
|
|
|
112405
112497
|
}
|
|
112406
112498
|
return false;
|
|
112407
112499
|
}
|
|
112408
|
-
var
|
|
112500
|
+
var import_fs14, import_path17, import_util12, import_child_process10, execAsync3;
|
|
112409
112501
|
var init_file_lister = __esm({
|
|
112410
112502
|
"src/utils/file-lister.js"() {
|
|
112411
112503
|
"use strict";
|
|
112412
|
-
|
|
112504
|
+
import_fs14 = __toESM(require("fs"), 1);
|
|
112413
112505
|
import_path17 = __toESM(require("path"), 1);
|
|
112414
112506
|
import_util12 = require("util");
|
|
112415
112507
|
import_child_process10 = require("child_process");
|
|
@@ -112428,11 +112520,11 @@ function initializeSimpleTelemetryFromOptions(options) {
|
|
|
112428
112520
|
});
|
|
112429
112521
|
return telemetry;
|
|
112430
112522
|
}
|
|
112431
|
-
var
|
|
112523
|
+
var import_fs15, import_path18, SimpleTelemetry, SimpleAppTracer;
|
|
112432
112524
|
var init_simpleTelemetry = __esm({
|
|
112433
112525
|
"src/agent/simpleTelemetry.js"() {
|
|
112434
112526
|
"use strict";
|
|
112435
|
-
|
|
112527
|
+
import_fs15 = require("fs");
|
|
112436
112528
|
import_path18 = require("path");
|
|
112437
112529
|
SimpleTelemetry = class {
|
|
112438
112530
|
constructor(options = {}) {
|
|
@@ -112448,10 +112540,10 @@ var init_simpleTelemetry = __esm({
|
|
|
112448
112540
|
initializeFileExporter() {
|
|
112449
112541
|
try {
|
|
112450
112542
|
const dir = (0, import_path18.dirname)(this.filePath);
|
|
112451
|
-
if (!(0,
|
|
112452
|
-
(0,
|
|
112543
|
+
if (!(0, import_fs15.existsSync)(dir)) {
|
|
112544
|
+
(0, import_fs15.mkdirSync)(dir, { recursive: true });
|
|
112453
112545
|
}
|
|
112454
|
-
this.stream = (0,
|
|
112546
|
+
this.stream = (0, import_fs15.createWriteStream)(this.filePath, { flags: "a" });
|
|
112455
112547
|
this.stream.on("error", (error2) => {
|
|
112456
112548
|
console.error(`[SimpleTelemetry] Stream error: ${error2.message}`);
|
|
112457
112549
|
});
|
package/package.json
CHANGED
package/src/agent/ProbeAgent.js
CHANGED
|
@@ -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/src/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
|
};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|