@probelabs/probe 0.6.0-rc291 → 0.6.0-rc293
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-rc291-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc293-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc291-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc293-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc291-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc293-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc291-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc293-x86_64-pc-windows-msvc.zip} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc291-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc293-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/dsl/environment.js +8 -1
- package/build/agent/dsl/runtime.js +9 -1
- package/build/agent/shared/prompts.js +33 -3
- package/build/tools/executePlan.js +1 -0
- package/build/tools/fileTracker.js +33 -17
- package/build/tools/fuzzyMatch.js +52 -1
- package/build/tools/lineEditHeuristics.js +11 -0
- package/build/tools/vercel.js +13 -10
- package/cjs/agent/ProbeAgent.cjs +125 -40
- package/cjs/index.cjs +132 -47
- package/package.json +1 -1
- package/src/agent/dsl/environment.js +8 -1
- package/src/agent/dsl/runtime.js +9 -1
- package/src/agent/shared/prompts.js +33 -3
- package/src/tools/executePlan.js +1 -0
- package/src/tools/fileTracker.js +33 -17
- package/src/tools/fuzzyMatch.js +52 -1
- package/src/tools/lineEditHeuristics.js +11 -0
- package/src/tools/vercel.js +13 -10
package/cjs/index.cjs
CHANGED
|
@@ -27260,6 +27260,10 @@ var init_symbolEdit = __esm({
|
|
|
27260
27260
|
});
|
|
27261
27261
|
|
|
27262
27262
|
// src/tools/fileTracker.js
|
|
27263
|
+
function normalizePath(filePath) {
|
|
27264
|
+
if (!filePath) return filePath;
|
|
27265
|
+
return (0, import_path6.resolve)(filePath);
|
|
27266
|
+
}
|
|
27263
27267
|
function computeContentHash(content) {
|
|
27264
27268
|
const normalized = (content || "").split("\n").map((l) => l.trimEnd()).join("\n");
|
|
27265
27269
|
return (0, import_crypto2.createHash)("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
@@ -27322,10 +27326,11 @@ var init_fileTracker = __esm({
|
|
|
27322
27326
|
* @param {string} resolvedPath - Absolute path to the file
|
|
27323
27327
|
*/
|
|
27324
27328
|
markFileSeen(resolvedPath) {
|
|
27325
|
-
|
|
27326
|
-
this.
|
|
27329
|
+
const normalized = normalizePath(resolvedPath);
|
|
27330
|
+
this._seenFiles.add(normalized);
|
|
27331
|
+
this._textEditCounts.set(normalized, 0);
|
|
27327
27332
|
if (this.debug) {
|
|
27328
|
-
console.error(`[FileTracker] Marked as seen: ${
|
|
27333
|
+
console.error(`[FileTracker] Marked as seen: ${normalized}`);
|
|
27329
27334
|
}
|
|
27330
27335
|
}
|
|
27331
27336
|
/**
|
|
@@ -27334,7 +27339,7 @@ var init_fileTracker = __esm({
|
|
|
27334
27339
|
* @returns {boolean}
|
|
27335
27340
|
*/
|
|
27336
27341
|
isFileSeen(resolvedPath) {
|
|
27337
|
-
return this._seenFiles.has(resolvedPath);
|
|
27342
|
+
return this._seenFiles.has(normalizePath(resolvedPath));
|
|
27338
27343
|
}
|
|
27339
27344
|
/**
|
|
27340
27345
|
* Store a content hash for a symbol in a file.
|
|
@@ -27346,7 +27351,7 @@ var init_fileTracker = __esm({
|
|
|
27346
27351
|
* @param {string} [source='extract'] - How the content was obtained
|
|
27347
27352
|
*/
|
|
27348
27353
|
trackSymbolContent(resolvedPath, symbolName, code, startLine, endLine, source = "extract") {
|
|
27349
|
-
const key = `${resolvedPath}#${symbolName}`;
|
|
27354
|
+
const key = `${normalizePath(resolvedPath)}#${symbolName}`;
|
|
27350
27355
|
const contentHash = computeContentHash(code);
|
|
27351
27356
|
this._contentRecords.set(key, {
|
|
27352
27357
|
contentHash,
|
|
@@ -27367,7 +27372,7 @@ var init_fileTracker = __esm({
|
|
|
27367
27372
|
* @returns {Object|null} The stored record or null
|
|
27368
27373
|
*/
|
|
27369
27374
|
getSymbolRecord(resolvedPath, symbolName) {
|
|
27370
|
-
return this._contentRecords.get(`${resolvedPath}#${symbolName}`) || null;
|
|
27375
|
+
return this._contentRecords.get(`${normalizePath(resolvedPath)}#${symbolName}`) || null;
|
|
27371
27376
|
}
|
|
27372
27377
|
/**
|
|
27373
27378
|
* Check if a symbol's current content matches what was stored.
|
|
@@ -27377,7 +27382,7 @@ var init_fileTracker = __esm({
|
|
|
27377
27382
|
* @returns {{ok: boolean, reason?: string, message?: string}}
|
|
27378
27383
|
*/
|
|
27379
27384
|
checkSymbolContent(resolvedPath, symbolName, currentCode) {
|
|
27380
|
-
const key = `${resolvedPath}#${symbolName}`;
|
|
27385
|
+
const key = `${normalizePath(resolvedPath)}#${symbolName}`;
|
|
27381
27386
|
const record2 = this._contentRecords.get(key);
|
|
27382
27387
|
if (!record2) {
|
|
27383
27388
|
return { ok: true };
|
|
@@ -27454,7 +27459,7 @@ var init_fileTracker = __esm({
|
|
|
27454
27459
|
* @returns {{ok: boolean, reason?: string, message?: string}}
|
|
27455
27460
|
*/
|
|
27456
27461
|
checkBeforeEdit(resolvedPath) {
|
|
27457
|
-
if (!this._seenFiles.has(resolvedPath)) {
|
|
27462
|
+
if (!this._seenFiles.has(normalizePath(resolvedPath))) {
|
|
27458
27463
|
return {
|
|
27459
27464
|
ok: false,
|
|
27460
27465
|
reason: "untracked",
|
|
@@ -27469,8 +27474,9 @@ var init_fileTracker = __esm({
|
|
|
27469
27474
|
* @param {string} resolvedPath - Absolute path to the file
|
|
27470
27475
|
*/
|
|
27471
27476
|
async trackFileAfterWrite(resolvedPath) {
|
|
27472
|
-
|
|
27473
|
-
this.
|
|
27477
|
+
const normalized = normalizePath(resolvedPath);
|
|
27478
|
+
this._seenFiles.add(normalized);
|
|
27479
|
+
this.invalidateFileRecords(normalized);
|
|
27474
27480
|
}
|
|
27475
27481
|
/**
|
|
27476
27482
|
* Record a text-mode edit (old_string/new_string) to a file.
|
|
@@ -27478,10 +27484,11 @@ var init_fileTracker = __esm({
|
|
|
27478
27484
|
* @param {string} resolvedPath - Absolute path to the file
|
|
27479
27485
|
*/
|
|
27480
27486
|
recordTextEdit(resolvedPath) {
|
|
27481
|
-
const
|
|
27482
|
-
this._textEditCounts.
|
|
27487
|
+
const normalized = normalizePath(resolvedPath);
|
|
27488
|
+
const count = (this._textEditCounts.get(normalized) || 0) + 1;
|
|
27489
|
+
this._textEditCounts.set(normalized, count);
|
|
27483
27490
|
if (this.debug) {
|
|
27484
|
-
console.error(`[FileTracker] Text edit #${count} for ${
|
|
27491
|
+
console.error(`[FileTracker] Text edit #${count} for ${normalized}`);
|
|
27485
27492
|
}
|
|
27486
27493
|
}
|
|
27487
27494
|
/**
|
|
@@ -27490,7 +27497,7 @@ var init_fileTracker = __esm({
|
|
|
27490
27497
|
* @returns {{ok: boolean, editCount?: number, message?: string}}
|
|
27491
27498
|
*/
|
|
27492
27499
|
checkTextEditStaleness(resolvedPath) {
|
|
27493
|
-
const count = this._textEditCounts.get(resolvedPath) || 0;
|
|
27500
|
+
const count = this._textEditCounts.get(normalizePath(resolvedPath)) || 0;
|
|
27494
27501
|
if (count >= this.maxConsecutiveTextEdits) {
|
|
27495
27502
|
return {
|
|
27496
27503
|
ok: false,
|
|
@@ -27519,7 +27526,7 @@ var init_fileTracker = __esm({
|
|
|
27519
27526
|
* @param {string} resolvedPath - Absolute path to the file
|
|
27520
27527
|
*/
|
|
27521
27528
|
invalidateFileRecords(resolvedPath) {
|
|
27522
|
-
const prefix = resolvedPath + "#";
|
|
27529
|
+
const prefix = normalizePath(resolvedPath) + "#";
|
|
27523
27530
|
for (const key of this._contentRecords.keys()) {
|
|
27524
27531
|
if (key.startsWith(prefix)) {
|
|
27525
27532
|
this._contentRecords.delete(key);
|
|
@@ -27535,7 +27542,7 @@ var init_fileTracker = __esm({
|
|
|
27535
27542
|
* @returns {boolean}
|
|
27536
27543
|
*/
|
|
27537
27544
|
isTracked(resolvedPath) {
|
|
27538
|
-
return this.isFileSeen(resolvedPath);
|
|
27545
|
+
return this.isFileSeen(normalizePath(resolvedPath));
|
|
27539
27546
|
}
|
|
27540
27547
|
/**
|
|
27541
27548
|
* Clear all tracking state.
|
|
@@ -31588,7 +31595,7 @@ var init_esm3 = __esm({
|
|
|
31588
31595
|
});
|
|
31589
31596
|
|
|
31590
31597
|
// node_modules/path-scurry/dist/esm/index.js
|
|
31591
|
-
var import_node_path, import_node_url, import_fs4, actualFS, import_promises, 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,
|
|
31598
|
+
var import_node_path, import_node_url, import_fs4, actualFS, import_promises, 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, normalize2, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
|
|
31592
31599
|
var init_esm4 = __esm({
|
|
31593
31600
|
"node_modules/path-scurry/dist/esm/index.js"() {
|
|
31594
31601
|
init_esm2();
|
|
@@ -31643,7 +31650,7 @@ var init_esm4 = __esm({
|
|
|
31643
31650
|
TYPEMASK = 1023;
|
|
31644
31651
|
entToType = (s) => s.isFile() ? IFREG : s.isDirectory() ? IFDIR : s.isSymbolicLink() ? IFLNK : s.isCharacterDevice() ? IFCHR : s.isBlockDevice() ? IFBLK : s.isSocket() ? IFSOCK : s.isFIFO() ? IFIFO : UNKNOWN;
|
|
31645
31652
|
normalizeCache = /* @__PURE__ */ new Map();
|
|
31646
|
-
|
|
31653
|
+
normalize2 = (s) => {
|
|
31647
31654
|
const c = normalizeCache.get(s);
|
|
31648
31655
|
if (c)
|
|
31649
31656
|
return c;
|
|
@@ -31656,7 +31663,7 @@ var init_esm4 = __esm({
|
|
|
31656
31663
|
const c = normalizeNocaseCache.get(s);
|
|
31657
31664
|
if (c)
|
|
31658
31665
|
return c;
|
|
31659
|
-
const n =
|
|
31666
|
+
const n = normalize2(s.toLowerCase());
|
|
31660
31667
|
normalizeNocaseCache.set(s, n);
|
|
31661
31668
|
return n;
|
|
31662
31669
|
};
|
|
@@ -31823,7 +31830,7 @@ var init_esm4 = __esm({
|
|
|
31823
31830
|
*/
|
|
31824
31831
|
constructor(name15, type = UNKNOWN, root2, roots, nocase, children, opts) {
|
|
31825
31832
|
this.name = name15;
|
|
31826
|
-
this.#matchName = nocase ? normalizeNocase(name15) :
|
|
31833
|
+
this.#matchName = nocase ? normalizeNocase(name15) : normalize2(name15);
|
|
31827
31834
|
this.#type = type & TYPEMASK;
|
|
31828
31835
|
this.nocase = nocase;
|
|
31829
31836
|
this.roots = roots;
|
|
@@ -31916,7 +31923,7 @@ var init_esm4 = __esm({
|
|
|
31916
31923
|
return this.parent || this;
|
|
31917
31924
|
}
|
|
31918
31925
|
const children = this.children();
|
|
31919
|
-
const name15 = this.nocase ? normalizeNocase(pathPart) :
|
|
31926
|
+
const name15 = this.nocase ? normalizeNocase(pathPart) : normalize2(pathPart);
|
|
31920
31927
|
for (const p of children) {
|
|
31921
31928
|
if (p.#matchName === name15) {
|
|
31922
31929
|
return p;
|
|
@@ -32161,7 +32168,7 @@ var init_esm4 = __esm({
|
|
|
32161
32168
|
* directly.
|
|
32162
32169
|
*/
|
|
32163
32170
|
isNamed(n) {
|
|
32164
|
-
return !this.nocase ? this.#matchName ===
|
|
32171
|
+
return !this.nocase ? this.#matchName === normalize2(n) : this.#matchName === normalizeNocase(n);
|
|
32165
32172
|
}
|
|
32166
32173
|
/**
|
|
32167
32174
|
* Return the Path object corresponding to the target of a symbolic link.
|
|
@@ -32300,7 +32307,7 @@ var init_esm4 = __esm({
|
|
|
32300
32307
|
#readdirMaybePromoteChild(e, c) {
|
|
32301
32308
|
for (let p = c.provisional; p < c.length; p++) {
|
|
32302
32309
|
const pchild = c[p];
|
|
32303
|
-
const name15 = this.nocase ? normalizeNocase(e.name) :
|
|
32310
|
+
const name15 = this.nocase ? normalizeNocase(e.name) : normalize2(e.name);
|
|
32304
32311
|
if (name15 !== pchild.#matchName) {
|
|
32305
32312
|
continue;
|
|
32306
32313
|
}
|
|
@@ -53617,7 +53624,7 @@ var init_graph_builder = __esm({
|
|
|
53617
53624
|
applyLinkStyles() {
|
|
53618
53625
|
if (!this.pendingLinkStyles.length || !this.edges.length)
|
|
53619
53626
|
return;
|
|
53620
|
-
const
|
|
53627
|
+
const normalize4 = (s) => {
|
|
53621
53628
|
const out = {};
|
|
53622
53629
|
for (const [kRaw, vRaw] of Object.entries(s)) {
|
|
53623
53630
|
const k = kRaw.trim().toLowerCase();
|
|
@@ -53638,7 +53645,7 @@ var init_graph_builder = __esm({
|
|
|
53638
53645
|
return out;
|
|
53639
53646
|
};
|
|
53640
53647
|
for (const cmd of this.pendingLinkStyles) {
|
|
53641
|
-
const style =
|
|
53648
|
+
const style = normalize4(cmd.props);
|
|
53642
53649
|
for (const idx of cmd.indices) {
|
|
53643
53650
|
if (idx >= 0 && idx < this.edges.length) {
|
|
53644
53651
|
const e = this.edges[idx];
|
|
@@ -60905,7 +60912,7 @@ var require_layout = __commonJS({
|
|
|
60905
60912
|
"use strict";
|
|
60906
60913
|
var _ = require_lodash2();
|
|
60907
60914
|
var acyclic = require_acyclic();
|
|
60908
|
-
var
|
|
60915
|
+
var normalize4 = require_normalize();
|
|
60909
60916
|
var rank = require_rank();
|
|
60910
60917
|
var normalizeRanks = require_util().normalizeRanks;
|
|
60911
60918
|
var parentDummyChains = require_parent_dummy_chains();
|
|
@@ -60967,7 +60974,7 @@ var require_layout = __commonJS({
|
|
|
60967
60974
|
removeEdgeLabelProxies(g);
|
|
60968
60975
|
});
|
|
60969
60976
|
time3(" normalize.run", function() {
|
|
60970
|
-
|
|
60977
|
+
normalize4.run(g);
|
|
60971
60978
|
});
|
|
60972
60979
|
time3(" parentDummyChains", function() {
|
|
60973
60980
|
parentDummyChains(g);
|
|
@@ -60994,7 +61001,7 @@ var require_layout = __commonJS({
|
|
|
60994
61001
|
removeBorderNodes(g);
|
|
60995
61002
|
});
|
|
60996
61003
|
time3(" normalize.undo", function() {
|
|
60997
|
-
|
|
61004
|
+
normalize4.undo(g);
|
|
60998
61005
|
});
|
|
60999
61006
|
time3(" fixupEdgeLabelCoords", function() {
|
|
61000
61007
|
fixupEdgeLabelCoords(g);
|
|
@@ -67365,8 +67372,8 @@ var require_resolve = __commonJS({
|
|
|
67365
67372
|
}
|
|
67366
67373
|
return count;
|
|
67367
67374
|
}
|
|
67368
|
-
function getFullPath(resolver, id = "",
|
|
67369
|
-
if (
|
|
67375
|
+
function getFullPath(resolver, id = "", normalize4) {
|
|
67376
|
+
if (normalize4 !== false)
|
|
67370
67377
|
id = normalizeId(id);
|
|
67371
67378
|
const p = resolver.parse(id);
|
|
67372
67379
|
return _getFullPath(resolver, p);
|
|
@@ -68706,7 +68713,7 @@ var require_fast_uri = __commonJS({
|
|
|
68706
68713
|
"use strict";
|
|
68707
68714
|
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
|
|
68708
68715
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
68709
|
-
function
|
|
68716
|
+
function normalize4(uri, options) {
|
|
68710
68717
|
if (typeof uri === "string") {
|
|
68711
68718
|
uri = /** @type {T} */
|
|
68712
68719
|
serialize(parse11(uri, options), options);
|
|
@@ -68942,7 +68949,7 @@ var require_fast_uri = __commonJS({
|
|
|
68942
68949
|
}
|
|
68943
68950
|
var fastUri = {
|
|
68944
68951
|
SCHEMES,
|
|
68945
|
-
normalize:
|
|
68952
|
+
normalize: normalize4,
|
|
68946
68953
|
resolve: resolve9,
|
|
68947
68954
|
resolveComponent,
|
|
68948
68955
|
equal,
|
|
@@ -73149,9 +73156,9 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
73149
73156
|
- Do not add code comments unless the logic is genuinely complex and non-obvious.
|
|
73150
73157
|
|
|
73151
73158
|
# Before Implementation
|
|
73152
|
-
-
|
|
73153
|
-
-
|
|
73154
|
-
-
|
|
73159
|
+
- Read tests first \u2014 find existing test files for the module you're changing. They reveal expected behavior, edge cases, and the project's testing patterns.
|
|
73160
|
+
- Read neighboring files \u2014 understand naming conventions, error handling patterns, import style, and existing utilities before creating new ones.
|
|
73161
|
+
- Trace the call chain \u2014 follow how the code you're changing is called and what depends on it. Check interfaces, types, and consumers.
|
|
73155
73162
|
- Focus on backward compatibility
|
|
73156
73163
|
- Consider scalability, maintainability, and extensibility in your analysis
|
|
73157
73164
|
|
|
@@ -73176,6 +73183,20 @@ Before building or testing, determine the project's toolchain:
|
|
|
73176
73183
|
- Read README for build/test instructions if the above are unclear
|
|
73177
73184
|
- Common patterns: \`make build\`/\`make test\`, \`npm run build\`/\`npm test\`, \`cargo build\`/\`cargo test\`, \`go build ./...\`/\`go test ./...\`, \`python -m pytest\`
|
|
73178
73185
|
|
|
73186
|
+
# File Editing Rules
|
|
73187
|
+
You have access to the \`edit\`, \`create\`, and \`multi_edit\` tools for modifying files. You MUST use these tools for ALL code changes. They are purpose-built, atomic, and safe.
|
|
73188
|
+
|
|
73189
|
+
DO NOT use sed, awk, echo/cat redirection, or heredocs to modify source code. These commands cause real damage in practice: truncated lines, duplicate code blocks, broken syntax. Every bad edit wastes iterations on fix-up commits.
|
|
73190
|
+
|
|
73191
|
+
Use the right tool:
|
|
73192
|
+
1. To MODIFY existing code \u2192 \`edit\` tool (old_string \u2192 new_string, or start_line/end_line)
|
|
73193
|
+
2. To CREATE a new file \u2192 \`create\` tool
|
|
73194
|
+
3. To CHANGE multiple files at once \u2192 \`multi_edit\` tool
|
|
73195
|
+
4. To READ code \u2192 \`extract\` or \`search\` tools
|
|
73196
|
+
5. If \`edit\` fails with "file has not been read yet" \u2192 use \`extract\` with the EXACT same file path you will pass to \`edit\`. Relative vs absolute path mismatch causes this error. Use the same path format consistently. If it still fails, use bash \`cat\` to read the file, then use \`create\` to write the entire modified file. Do NOT fall back to sed.
|
|
73197
|
+
|
|
73198
|
+
Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands, git operations, and read-only file inspection (cat, head, tail). sed/awk should ONLY be used for trivial non-code tasks (e.g., config file tweaks) where the replacement is a simple literal string swap.
|
|
73199
|
+
|
|
73179
73200
|
# During Implementation
|
|
73180
73201
|
- Always create a new branch before making changes to the codebase.
|
|
73181
73202
|
- Fix problems at the root cause, not with surface-level patches. Prefer general solutions over special cases.
|
|
@@ -73202,6 +73223,22 @@ Before committing or creating a PR, run through this checklist:
|
|
|
73202
73223
|
|
|
73203
73224
|
Do NOT skip verification. Do NOT proceed to PR creation with a broken build or failing tests.
|
|
73204
73225
|
|
|
73226
|
+
# Output Integrity
|
|
73227
|
+
Your final output MUST accurately reflect what ACTUALLY happened. Do NOT fabricate, hallucinate, or report aspirational results.
|
|
73228
|
+
|
|
73229
|
+
- Only report PR URLs you actually created or updated with \`gh pr create\` or \`git push\`. If you checked out an existing PR but did NOT push changes to it, do NOT claim you updated it.
|
|
73230
|
+
- Describe what you ACTUALLY DID, not what you planned or intended to do. If you ran out of iterations, say so. If tests failed, say so.
|
|
73231
|
+
- Only list files you actually modified AND committed.
|
|
73232
|
+
- If you could not complete the task \u2014 ran out of iterations, tests failed, build broken, push rejected \u2014 report the real reason honestly.
|
|
73233
|
+
|
|
73234
|
+
NEVER claim success when:
|
|
73235
|
+
- You did not run \`git push\` successfully
|
|
73236
|
+
- Tests failed and you did not fix them
|
|
73237
|
+
- You hit the iteration limit before completing the work
|
|
73238
|
+
- You only analyzed/investigated but did not implement changes
|
|
73239
|
+
|
|
73240
|
+
A false success report is WORSE than an honest failure \u2014 it misleads the user into thinking work is done when it is not.
|
|
73241
|
+
|
|
73205
73242
|
# GitHub Integration
|
|
73206
73243
|
- Use the \`gh\` CLI for all GitHub operations: issues, pull requests, checks, releases.
|
|
73207
73244
|
- To view issues or PRs: \`gh issue view <number>\`, \`gh pr view <number>\`.
|
|
@@ -92219,7 +92256,12 @@ function generateSandboxGlobals(options) {
|
|
|
92219
92256
|
}
|
|
92220
92257
|
return tryParseJSONValue(text);
|
|
92221
92258
|
};
|
|
92222
|
-
|
|
92259
|
+
const tracedFn = traceToolCall(name15, rawMcpFn, tracer, logFn);
|
|
92260
|
+
globals[name15] = tracedFn;
|
|
92261
|
+
const sanitized = name15.replace(/[^a-zA-Z0-9_$]/g, "_");
|
|
92262
|
+
if (sanitized !== name15) {
|
|
92263
|
+
globals[sanitized] = tracedFn;
|
|
92264
|
+
}
|
|
92223
92265
|
}
|
|
92224
92266
|
}
|
|
92225
92267
|
if (llmCall) {
|
|
@@ -92574,9 +92616,17 @@ ${validation.errors.join("\n")}`,
|
|
|
92574
92616
|
"dsl.duration_ms": elapsed,
|
|
92575
92617
|
"dsl.error": e.message?.substring(0, 500)
|
|
92576
92618
|
});
|
|
92619
|
+
let errorMsg = `Execution failed: ${e.message}`;
|
|
92620
|
+
if (e.message && e.message.includes("is not defined")) {
|
|
92621
|
+
const globalNames = Object.keys(toolGlobals).sort();
|
|
92622
|
+
errorMsg += `
|
|
92623
|
+
Available functions: ${globalNames.join(", ")}`;
|
|
92624
|
+
errorMsg += `
|
|
92625
|
+
Note: Tools with hyphens (e.g. "my-tool") are available with underscores: my_tool()`;
|
|
92626
|
+
}
|
|
92577
92627
|
return {
|
|
92578
92628
|
status: "error",
|
|
92579
|
-
error:
|
|
92629
|
+
error: errorMsg,
|
|
92580
92630
|
logs
|
|
92581
92631
|
};
|
|
92582
92632
|
}
|
|
@@ -101391,7 +101441,7 @@ var init_vercel = __esm({
|
|
|
101391
101441
|
name: "search",
|
|
101392
101442
|
description: searchDelegate ? searchDelegateDescription : searchDescription,
|
|
101393
101443
|
inputSchema: searchSchema,
|
|
101394
|
-
execute: async ({ query: searchQuery, path: path9, allow_tests, exact, maxTokens: paramMaxTokens, language, session, nextPage }) => {
|
|
101444
|
+
execute: async ({ query: searchQuery, path: path9, allow_tests, exact, maxTokens: paramMaxTokens, language, session, nextPage, workingDirectory }) => {
|
|
101395
101445
|
if (!exact && searchQuery) {
|
|
101396
101446
|
const originalQuery = searchQuery;
|
|
101397
101447
|
searchQuery = autoQuoteSearchTerms(searchQuery);
|
|
@@ -101400,18 +101450,19 @@ var init_vercel = __esm({
|
|
|
101400
101450
|
}
|
|
101401
101451
|
}
|
|
101402
101452
|
const effectiveMaxTokens = paramMaxTokens || maxTokens;
|
|
101453
|
+
const effectiveSearchCwd = workingDirectory || options.cwd || ".";
|
|
101403
101454
|
let searchPaths;
|
|
101404
101455
|
if (path9) {
|
|
101405
|
-
searchPaths = parseAndResolvePaths(path9,
|
|
101456
|
+
searchPaths = parseAndResolvePaths(path9, effectiveSearchCwd);
|
|
101406
101457
|
}
|
|
101407
101458
|
if (!searchPaths || searchPaths.length === 0) {
|
|
101408
|
-
searchPaths = [
|
|
101459
|
+
searchPaths = [effectiveSearchCwd];
|
|
101409
101460
|
}
|
|
101410
101461
|
const searchPath = searchPaths.join(" ");
|
|
101411
101462
|
const searchOptions = {
|
|
101412
101463
|
query: searchQuery,
|
|
101413
101464
|
path: searchPath,
|
|
101414
|
-
cwd:
|
|
101465
|
+
cwd: effectiveSearchCwd,
|
|
101415
101466
|
// Working directory for resolving relative paths
|
|
101416
101467
|
allowTests: allow_tests ?? true,
|
|
101417
101468
|
exact,
|
|
@@ -101462,7 +101513,7 @@ var init_vercel = __esm({
|
|
|
101462
101513
|
try {
|
|
101463
101514
|
const result = maybeAnnotate(await runRawSearch());
|
|
101464
101515
|
if (options.fileTracker && typeof result === "string") {
|
|
101465
|
-
options.fileTracker.trackFilesFromOutput(result,
|
|
101516
|
+
options.fileTracker.trackFilesFromOutput(result, effectiveSearchCwd).catch(() => {
|
|
101466
101517
|
});
|
|
101467
101518
|
}
|
|
101468
101519
|
return result;
|
|
@@ -101515,7 +101566,7 @@ var init_vercel = __esm({
|
|
|
101515
101566
|
}
|
|
101516
101567
|
const fallbackResult = maybeAnnotate(await runRawSearch());
|
|
101517
101568
|
if (options.fileTracker && typeof fallbackResult === "string") {
|
|
101518
|
-
options.fileTracker.trackFilesFromOutput(fallbackResult,
|
|
101569
|
+
options.fileTracker.trackFilesFromOutput(fallbackResult, effectiveSearchCwd).catch(() => {
|
|
101519
101570
|
});
|
|
101520
101571
|
}
|
|
101521
101572
|
return fallbackResult;
|
|
@@ -101578,7 +101629,7 @@ var init_vercel = __esm({
|
|
|
101578
101629
|
try {
|
|
101579
101630
|
const fallbackResult2 = maybeAnnotate(await runRawSearch());
|
|
101580
101631
|
if (options.fileTracker && typeof fallbackResult2 === "string") {
|
|
101581
|
-
options.fileTracker.trackFilesFromOutput(fallbackResult2,
|
|
101632
|
+
options.fileTracker.trackFilesFromOutput(fallbackResult2, effectiveSearchCwd).catch(() => {
|
|
101582
101633
|
});
|
|
101583
101634
|
}
|
|
101584
101635
|
return fallbackResult2;
|
|
@@ -101632,9 +101683,9 @@ var init_vercel = __esm({
|
|
|
101632
101683
|
name: "extract",
|
|
101633
101684
|
description: extractDescription,
|
|
101634
101685
|
inputSchema: extractSchema,
|
|
101635
|
-
execute: async ({ targets, input_content, line, end_line, allow_tests, context_lines, format }) => {
|
|
101686
|
+
execute: async ({ targets, input_content, line, end_line, allow_tests, context_lines, format, workingDirectory }) => {
|
|
101636
101687
|
try {
|
|
101637
|
-
const effectiveCwd = options.cwd || ".";
|
|
101688
|
+
const effectiveCwd = workingDirectory || options.cwd || ".";
|
|
101638
101689
|
if (debug) {
|
|
101639
101690
|
if (targets) {
|
|
101640
101691
|
console.error(`Executing extract with targets: "${targets}", cwd: "${effectiveCwd}", context lines: ${context_lines || 10}`);
|
|
@@ -101893,7 +101944,14 @@ function lineTrimmedMatch(contentLines, searchLines) {
|
|
|
101893
101944
|
}
|
|
101894
101945
|
}
|
|
101895
101946
|
if (allMatch) {
|
|
101896
|
-
const
|
|
101947
|
+
const windowLines = contentLines.slice(i, i + windowSize);
|
|
101948
|
+
const windowMinIndent = getMinIndent(windowLines);
|
|
101949
|
+
const searchMinIndent = getMinIndent(searchLines);
|
|
101950
|
+
const indentDiff = Math.abs(windowMinIndent - searchMinIndent);
|
|
101951
|
+
if (isIndentDiffTooLarge(windowLines, searchLines, indentDiff)) {
|
|
101952
|
+
continue;
|
|
101953
|
+
}
|
|
101954
|
+
const matchedText = windowLines.join("\n");
|
|
101897
101955
|
matches.push(matchedText);
|
|
101898
101956
|
}
|
|
101899
101957
|
}
|
|
@@ -101923,6 +101981,15 @@ function whitespaceNormalizedMatch(content, search2) {
|
|
|
101923
101981
|
actualEnd++;
|
|
101924
101982
|
}
|
|
101925
101983
|
const matchedText = content.substring(originalStart, actualEnd);
|
|
101984
|
+
const matchedLines = matchedText.split("\n");
|
|
101985
|
+
const searchLines = search2.split("\n");
|
|
101986
|
+
const matchMinIndent = getMinIndent(matchedLines);
|
|
101987
|
+
const searchMinIndent = getMinIndent(searchLines);
|
|
101988
|
+
const indentDiff = Math.abs(matchMinIndent - searchMinIndent);
|
|
101989
|
+
if (isIndentDiffTooLarge(matchedLines, searchLines, indentDiff)) {
|
|
101990
|
+
searchStart = idx + 1;
|
|
101991
|
+
continue;
|
|
101992
|
+
}
|
|
101926
101993
|
matches.push(matchedText);
|
|
101927
101994
|
searchStart = idx + 1;
|
|
101928
101995
|
}
|
|
@@ -101974,6 +102041,10 @@ function indentFlexibleMatch(contentLines, searchLines) {
|
|
|
101974
102041
|
}
|
|
101975
102042
|
}
|
|
101976
102043
|
if (allMatch) {
|
|
102044
|
+
const indentDiff = Math.abs(windowMinIndent - searchMinIndent);
|
|
102045
|
+
if (isIndentDiffTooLarge(windowLines, searchLines, indentDiff)) {
|
|
102046
|
+
continue;
|
|
102047
|
+
}
|
|
101977
102048
|
const matchedText = windowLines.join("\n");
|
|
101978
102049
|
matches.push(matchedText);
|
|
101979
102050
|
}
|
|
@@ -101984,6 +102055,14 @@ function indentFlexibleMatch(contentLines, searchLines) {
|
|
|
101984
102055
|
count: matches.length
|
|
101985
102056
|
};
|
|
101986
102057
|
}
|
|
102058
|
+
function isIndentDiffTooLarge(linesA, linesB, indentDiff) {
|
|
102059
|
+
if (indentDiff <= 0) return false;
|
|
102060
|
+
const sampleA = linesA.find((l) => l.trim().length > 0) || "";
|
|
102061
|
+
const sampleB = linesB.find((l) => l.trim().length > 0) || "";
|
|
102062
|
+
const useTabs = sampleA.startsWith(" ") || sampleB.startsWith(" ");
|
|
102063
|
+
const maxAllowedDiff = useTabs ? 1 : 4;
|
|
102064
|
+
return indentDiff > maxAllowedDiff;
|
|
102065
|
+
}
|
|
101987
102066
|
function getMinIndent(lines) {
|
|
101988
102067
|
let min = Infinity;
|
|
101989
102068
|
for (const line of lines) {
|
|
@@ -102058,6 +102137,12 @@ function restoreIndentation(newStr, originalLines) {
|
|
|
102058
102137
|
const targetIndent = detectBaseIndent(originalCode);
|
|
102059
102138
|
const newIndent = detectBaseIndent(newStr);
|
|
102060
102139
|
if (targetIndent !== newIndent) {
|
|
102140
|
+
const indentDiff = Math.abs(targetIndent.length - newIndent.length);
|
|
102141
|
+
const useTabs = targetIndent.includes(" ") || newIndent.includes(" ");
|
|
102142
|
+
const maxAllowedDiff = useTabs ? 1 : 4;
|
|
102143
|
+
if (indentDiff > maxAllowedDiff) {
|
|
102144
|
+
return { result: newStr, modifications };
|
|
102145
|
+
}
|
|
102061
102146
|
const reindented = reindent(newStr, targetIndent);
|
|
102062
102147
|
if (reindented !== newStr) {
|
|
102063
102148
|
modifications.push(`reindented from "${newIndent}" to "${targetIndent}"`);
|
package/package.json
CHANGED
|
@@ -234,7 +234,14 @@ export function generateSandboxGlobals(options) {
|
|
|
234
234
|
}
|
|
235
235
|
return tryParseJSONValue(text);
|
|
236
236
|
};
|
|
237
|
-
|
|
237
|
+
const tracedFn = traceToolCall(name, rawMcpFn, tracer, logFn);
|
|
238
|
+
globals[name] = tracedFn;
|
|
239
|
+
// Register sanitized alias for names with hyphens/dots/etc that aren't valid JS identifiers
|
|
240
|
+
// e.g. "workable-api" → also available as "workable_api"
|
|
241
|
+
const sanitized = name.replace(/[^a-zA-Z0-9_$]/g, '_');
|
|
242
|
+
if (sanitized !== name) {
|
|
243
|
+
globals[sanitized] = tracedFn;
|
|
244
|
+
}
|
|
238
245
|
}
|
|
239
246
|
}
|
|
240
247
|
|
package/src/agent/dsl/runtime.js
CHANGED
|
@@ -181,9 +181,17 @@ export function createDSLRuntime(options) {
|
|
|
181
181
|
'dsl.error': e.message?.substring(0, 500),
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
+
// Enrich "X is not defined" errors with available tool names
|
|
185
|
+
let errorMsg = `Execution failed: ${e.message}`;
|
|
186
|
+
if (e.message && e.message.includes('is not defined')) {
|
|
187
|
+
const globalNames = Object.keys(toolGlobals).sort();
|
|
188
|
+
errorMsg += `\nAvailable functions: ${globalNames.join(', ')}`;
|
|
189
|
+
errorMsg += `\nNote: Tools with hyphens (e.g. "my-tool") are available with underscores: my_tool()`;
|
|
190
|
+
}
|
|
191
|
+
|
|
184
192
|
return {
|
|
185
193
|
status: 'error',
|
|
186
|
-
error:
|
|
194
|
+
error: errorMsg,
|
|
187
195
|
logs,
|
|
188
196
|
};
|
|
189
197
|
}
|
|
@@ -90,9 +90,9 @@ If the solution is clear, you can jump to implementation right away. If not, ask
|
|
|
90
90
|
- Do not add code comments unless the logic is genuinely complex and non-obvious.
|
|
91
91
|
|
|
92
92
|
# Before Implementation
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
93
|
+
- Read tests first — find existing test files for the module you're changing. They reveal expected behavior, edge cases, and the project's testing patterns.
|
|
94
|
+
- Read neighboring files — understand naming conventions, error handling patterns, import style, and existing utilities before creating new ones.
|
|
95
|
+
- Trace the call chain — follow how the code you're changing is called and what depends on it. Check interfaces, types, and consumers.
|
|
96
96
|
- Focus on backward compatibility
|
|
97
97
|
- Consider scalability, maintainability, and extensibility in your analysis
|
|
98
98
|
|
|
@@ -117,6 +117,20 @@ Before building or testing, determine the project's toolchain:
|
|
|
117
117
|
- Read README for build/test instructions if the above are unclear
|
|
118
118
|
- Common patterns: \`make build\`/\`make test\`, \`npm run build\`/\`npm test\`, \`cargo build\`/\`cargo test\`, \`go build ./...\`/\`go test ./...\`, \`python -m pytest\`
|
|
119
119
|
|
|
120
|
+
# File Editing Rules
|
|
121
|
+
You have access to the \`edit\`, \`create\`, and \`multi_edit\` tools for modifying files. You MUST use these tools for ALL code changes. They are purpose-built, atomic, and safe.
|
|
122
|
+
|
|
123
|
+
DO NOT use sed, awk, echo/cat redirection, or heredocs to modify source code. These commands cause real damage in practice: truncated lines, duplicate code blocks, broken syntax. Every bad edit wastes iterations on fix-up commits.
|
|
124
|
+
|
|
125
|
+
Use the right tool:
|
|
126
|
+
1. To MODIFY existing code → \`edit\` tool (old_string → new_string, or start_line/end_line)
|
|
127
|
+
2. To CREATE a new file → \`create\` tool
|
|
128
|
+
3. To CHANGE multiple files at once → \`multi_edit\` tool
|
|
129
|
+
4. To READ code → \`extract\` or \`search\` tools
|
|
130
|
+
5. If \`edit\` fails with "file has not been read yet" → use \`extract\` with the EXACT same file path you will pass to \`edit\`. Relative vs absolute path mismatch causes this error. Use the same path format consistently. If it still fails, use bash \`cat\` to read the file, then use \`create\` to write the entire modified file. Do NOT fall back to sed.
|
|
131
|
+
|
|
132
|
+
Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands, git operations, and read-only file inspection (cat, head, tail). sed/awk should ONLY be used for trivial non-code tasks (e.g., config file tweaks) where the replacement is a simple literal string swap.
|
|
133
|
+
|
|
120
134
|
# During Implementation
|
|
121
135
|
- Always create a new branch before making changes to the codebase.
|
|
122
136
|
- Fix problems at the root cause, not with surface-level patches. Prefer general solutions over special cases.
|
|
@@ -143,6 +157,22 @@ Before committing or creating a PR, run through this checklist:
|
|
|
143
157
|
|
|
144
158
|
Do NOT skip verification. Do NOT proceed to PR creation with a broken build or failing tests.
|
|
145
159
|
|
|
160
|
+
# Output Integrity
|
|
161
|
+
Your final output MUST accurately reflect what ACTUALLY happened. Do NOT fabricate, hallucinate, or report aspirational results.
|
|
162
|
+
|
|
163
|
+
- Only report PR URLs you actually created or updated with \`gh pr create\` or \`git push\`. If you checked out an existing PR but did NOT push changes to it, do NOT claim you updated it.
|
|
164
|
+
- Describe what you ACTUALLY DID, not what you planned or intended to do. If you ran out of iterations, say so. If tests failed, say so.
|
|
165
|
+
- Only list files you actually modified AND committed.
|
|
166
|
+
- If you could not complete the task — ran out of iterations, tests failed, build broken, push rejected — report the real reason honestly.
|
|
167
|
+
|
|
168
|
+
NEVER claim success when:
|
|
169
|
+
- You did not run \`git push\` successfully
|
|
170
|
+
- Tests failed and you did not fix them
|
|
171
|
+
- You hit the iteration limit before completing the work
|
|
172
|
+
- You only analyzed/investigated but did not implement changes
|
|
173
|
+
|
|
174
|
+
A false success report is WORSE than an honest failure — it misleads the user into thinking work is done when it is not.
|
|
175
|
+
|
|
146
176
|
# GitHub Integration
|
|
147
177
|
- Use the \`gh\` CLI for all GitHub operations: issues, pull requests, checks, releases.
|
|
148
178
|
- To view issues or PRs: \`gh issue view <number>\`, \`gh pr view <number>\`.
|
package/src/tools/executePlan.js
CHANGED
|
@@ -778,6 +778,7 @@ return table;
|
|
|
778
778
|
- Do NOT define helper functions that call tools. Write all logic inline or use for..of loops.
|
|
779
779
|
- Do NOT use regex literals (/pattern/) — use String methods like indexOf, includes, startsWith instead.
|
|
780
780
|
- ONLY use functions listed below. Do NOT call functions that are not listed.
|
|
781
|
+
- MCP tools with hyphens in their names (e.g. \`workable-api\`) are available using underscores: \`workable_api()\`. Hyphens are not valid in JS identifiers.
|
|
781
782
|
|
|
782
783
|
### Available functions
|
|
783
784
|
|