pi-tool-repair 0.1.6 → 0.1.8
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/package.json +1 -1
- package/src/grammar-repair.ts +15 -0
- package/src/index.ts +9 -0
- package/tool-repair.ts +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-tool-repair",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Validate-then-repair extension for pi — fixes common LLM tool-call mistakes (null fields, stringified arrays, wrong field names, anchor bleed) before tools execute",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Tom X Nguyen",
|
package/src/grammar-repair.ts
CHANGED
|
@@ -156,6 +156,21 @@ export function repairAssistantMessageGrammarLeaks(
|
|
|
156
156
|
changed = true;
|
|
157
157
|
for (const candidate of candidates) {
|
|
158
158
|
if (candidate.stripOnly) continue;
|
|
159
|
+
|
|
160
|
+
// Safety: don't recover tool calls whose grammar parsed to an empty
|
|
161
|
+
// argument object. These are almost always malformed GLM/XML fragments
|
|
162
|
+
// (e.g. `<tool_call>write</tool_call>`) that would otherwise crash as a
|
|
163
|
+
// real tool invocation with missing required properties.
|
|
164
|
+
if (Object.keys(candidate.arguments).length === 0) {
|
|
165
|
+
if (config.debug) {
|
|
166
|
+
process.stderr.write(
|
|
167
|
+
`[pi-tool-repair] grammar-repair skipping ${candidate.grammar}:${candidate.name} ` +
|
|
168
|
+
"(empty arguments, likely malformed grammar)\n",
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
159
174
|
recoveredCalls.push({
|
|
160
175
|
name: candidate.name,
|
|
161
176
|
arguments: candidate.arguments,
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { MinimalAssistantMessage } from "./grammar-repair.js";
|
|
|
12
12
|
export interface RepairConfig {
|
|
13
13
|
debug: boolean;
|
|
14
14
|
anchorBleedModels: RegExp[];
|
|
15
|
+
grammarLeakModels: RegExp[];
|
|
15
16
|
fieldAliases: Record<string, Record<string, string[]>>;
|
|
16
17
|
stringArgTools: Record<string, { field: string; shape: "string" | "array" }>;
|
|
17
18
|
}
|
|
@@ -23,6 +24,9 @@ export const DEFAULT_CONFIG: RepairConfig = {
|
|
|
23
24
|
/minimax/i,
|
|
24
25
|
/glm/i,
|
|
25
26
|
],
|
|
27
|
+
grammarLeakModels: [
|
|
28
|
+
/glm/i,
|
|
29
|
+
],
|
|
26
30
|
fieldAliases: {
|
|
27
31
|
read: {
|
|
28
32
|
path: [
|
|
@@ -80,6 +84,11 @@ export function hasAnchorBleedBug(model: { id?: string } | null | undefined): bo
|
|
|
80
84
|
return DEFAULT_CONFIG.anchorBleedModels.some((re) => re.test(model.id!));
|
|
81
85
|
}
|
|
82
86
|
|
|
87
|
+
export function hasGrammarLeakBug(model: { id?: string } | null | undefined): boolean {
|
|
88
|
+
if (!model || !model.id) return false;
|
|
89
|
+
return DEFAULT_CONFIG.grammarLeakModels.some((re) => re.test(model.id!));
|
|
90
|
+
}
|
|
91
|
+
|
|
83
92
|
export function sanitizePattern(pattern: string): string | undefined {
|
|
84
93
|
if (pattern.includes("|") && (pattern.includes("^") || pattern.includes("$"))) {
|
|
85
94
|
return undefined;
|
package/tool-repair.ts
CHANGED
|
@@ -43,6 +43,7 @@ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
|
43
43
|
import {
|
|
44
44
|
DEFAULT_CONFIG,
|
|
45
45
|
hasAnchorBleedBug,
|
|
46
|
+
hasGrammarLeakBug,
|
|
46
47
|
sanitizeSchemaAnchors,
|
|
47
48
|
stripAnchorBleedInPlace,
|
|
48
49
|
stripGrammarTokenLeaksInPlace,
|
|
@@ -240,9 +241,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
240
241
|
}
|
|
241
242
|
}
|
|
242
243
|
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
|
|
244
|
+
// Strip leaked grammar tokens (e.g. GLM <arg_key>) from parsed tool-call
|
|
245
|
+
// keys/values before the schema sees them. Only for models known to produce
|
|
246
|
+
// grammar token leaks.
|
|
247
|
+
if (input && typeof input === "object" && model && hasGrammarLeakBug(model)) {
|
|
246
248
|
stripGrammarTokenLeaksInPlace(input as Record<string, unknown>);
|
|
247
249
|
}
|
|
248
250
|
|