@r3b1s/pi-repair-layer 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/package.json +3 -3
- package/src/repair-engine.ts +21 -1
package/README.md
CHANGED
|
@@ -41,12 +41,17 @@ Plain-English first, precise meaning after — for readers new to LLM tool-calli
|
|
|
41
41
|
## Install
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
|
|
44
|
+
pi install npm:@r3b1s/pi-repair-layer
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
Or from git:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pi install git:github.com/r3b1s/pi-repair-layer
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
pi's TUI will show a one-time warning that built-in tools were overridden —
|
|
54
|
+
that is this extension working as intended.
|
|
50
55
|
|
|
51
56
|
At runtime pi's extension loader aliases `@earendil-works/pi-coding-agent` and
|
|
52
57
|
`typebox` to the running instance's own modules, so the extension always binds
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@r3b1s/pi-repair-layer",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Tool-input repair layer for the pi coding agent: validate-then-repair for built-in tool calls, ported from the behavior of commandcode's repair layer",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@biomejs/biome": "2.4.8",
|
|
38
|
-
"@earendil-works/pi-ai": "^0.80.
|
|
39
|
-
"@earendil-works/pi-coding-agent": "0.80.
|
|
38
|
+
"@earendil-works/pi-ai": "^0.80.6",
|
|
39
|
+
"@earendil-works/pi-coding-agent": "0.80.6",
|
|
40
40
|
"@types/node": "^24.0.0",
|
|
41
41
|
"eslint": "^9.25.1",
|
|
42
42
|
"typescript": "^5.9.3",
|
package/src/repair-engine.ts
CHANGED
|
@@ -292,6 +292,14 @@ const wrapBareStringAsArray: IssueRule = (site, toolName) => {
|
|
|
292
292
|
return `Wrapped your bare string in a single-element array for \`${String(key)}\` in tool "${toolName}". Send an array (e.g. \`["foo"]\`) next time, not a single string.`;
|
|
293
293
|
};
|
|
294
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Stage 5 re-collects issue sites after each pass that fired a rule, so
|
|
297
|
+
* repairs that reveal nested problems (parse a stringified array, then rename
|
|
298
|
+
* aliased fields inside it) converge instead of failing. Three passes cover
|
|
299
|
+
* every known two-step combination with one pass of headroom.
|
|
300
|
+
*/
|
|
301
|
+
const MAX_ISSUE_PASSES = 3;
|
|
302
|
+
|
|
295
303
|
// Order matters: parse before wrap, rename before drop.
|
|
296
304
|
const ISSUE_RULES: readonly [string, IssueRule][] = [
|
|
297
305
|
["renameAliasedField", renameAliasedField],
|
|
@@ -456,16 +464,28 @@ export function repairToolInput(options: {
|
|
|
456
464
|
}
|
|
457
465
|
|
|
458
466
|
// Stage 5: per-issue repairs at the strict validator's failure sites.
|
|
459
|
-
|
|
467
|
+
// Iterates because one repair can expose sites the first collection couldn't
|
|
468
|
+
// see — e.g. parsing a stringified `edits` array surfaces aliased fields
|
|
469
|
+
// inside the parsed elements. Stops when the value validates or a full pass
|
|
470
|
+
// fires nothing (each firing rule mutates `current`, so a firing pass always
|
|
471
|
+
// makes progress); the cap only bounds pathological rule interactions.
|
|
472
|
+
for (
|
|
473
|
+
let pass = 0;
|
|
474
|
+
pass < MAX_ISSUE_PASSES && !schemaAccepts(schema, current);
|
|
475
|
+
pass++
|
|
476
|
+
) {
|
|
477
|
+
let repairedThisPass = false;
|
|
460
478
|
for (const site of collectIssueSites(schema, current)) {
|
|
461
479
|
for (const [name, rule] of ISSUE_RULES) {
|
|
462
480
|
const note = rule(site, toolName, config);
|
|
463
481
|
if (note !== false) {
|
|
464
482
|
fire(name, note);
|
|
483
|
+
repairedThisPass = true;
|
|
465
484
|
break;
|
|
466
485
|
}
|
|
467
486
|
}
|
|
468
487
|
}
|
|
488
|
+
if (!repairedThisPass) break;
|
|
469
489
|
}
|
|
470
490
|
|
|
471
491
|
// Stage 6: final verdict, now through pi's own pipeline (Convert, then
|