@r3b1s/pi-repair-layer 0.4.1 → 0.4.3

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 CHANGED
@@ -8,6 +8,12 @@ same repair pipeline to tools in your own extension.
8
8
 
9
9
  No LLM calls. No network requests. No uploaded telemetry.
10
10
 
11
+ ### Example: Deepseek v4 Pro
12
+ ![deepseek-v4-pro](https://raw.githubusercontent.com/r3b1s/media-assets/refs/heads/main/pi-things/repair-dsv4pro.webp)
13
+
14
+ ### Example: GLM 5.2
15
+ ![glm-5.2](https://raw.githubusercontent.com/r3b1s/media-assets/refs/heads/main/pi-things/repair-glm5.2.webp)
16
+
11
17
  ## Contents
12
18
 
13
19
  - [Why use it?](#why-use-it)
package/docs/research.md CHANGED
@@ -257,9 +257,19 @@ the requested module:
257
257
 
258
258
  **Why it matters:** the optional-integration recipe treats an import failure
259
259
  as "package absent" only when the code is one of these two values **and** the
260
- message names `@r3b1s/pi-repair-layer`; anything else rethrows so a broken
261
- install (a *transitive* module missing) is not silently misread as absent.
262
- All three observed shapes pass that discrimination.
260
+ message names `@r3b1s/pi-repair-layer` **as a quoted module specifier**
261
+ matched as an opening quote immediately followed by the name
262
+ (`'@r3b1s/pi-repair-layer`, no trailing quote so both the bare-package and
263
+ `/pi`-subpath forms match); anything else rethrows so a broken install (a
264
+ *transitive* module missing, e.g. `typebox`) is not silently misread as
265
+ absent. The quote anchor matters because the jiti and compiled-binary shapes
266
+ carry the importer path: a present-but-broken install throws
267
+ `Cannot find module 'typebox/value' from '.../node_modules/@r3b1s/pi-repair-layer/...'`,
268
+ which contains `@r3b1s/pi-repair-layer` only as a path segment (preceded by
269
+ `/`, not a quote). A bare-substring match would misread that as absence; the
270
+ quoted-specifier match rethrows it loudly. All three observed absent-package
271
+ shapes still begin with quote-then-name and pass the discrimination.
272
+ (Refined 2026-07-21; matcher verified by unit test against all three shapes.)
263
273
 
264
274
  ### Claim 12 — Git installs and other scopes do not resolve the shared npm siblings
265
275
 
@@ -191,6 +191,21 @@ const definition: ToolDefinition<typeof parameters> = {
191
191
  },
192
192
  };
193
193
 
194
+ // Opening quote + name, no trailing quote: matches both the bare-package ESM
195
+ // error (`'@r3b1s/pi-repair-layer'`) and the jiti/binary subpath error
196
+ // (`'@r3b1s/pi-repair-layer/pi'`), while a `node_modules/...` path segment
197
+ // (preceded by `/`, not a quote) does not read as absence.
198
+ const REPAIR_PACKAGE_SPECIFIER_QUOTED = "'@r3b1s/pi-repair-layer";
199
+
200
+ export function isRepairPackageAbsent(error: unknown): boolean {
201
+ const code = (error as { code?: unknown } | null)?.code;
202
+ const message = error instanceof Error ? error.message : String(error);
203
+ return (
204
+ (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") &&
205
+ message.includes(REPAIR_PACKAGE_SPECIFIER_QUOTED)
206
+ );
207
+ }
208
+
194
209
  async function loadRepairAdapter(): Promise<
195
210
  typeof adaptToolDefinition | undefined
196
211
  > {
@@ -198,12 +213,7 @@ async function loadRepairAdapter(): Promise<
198
213
  const repair = await import("@r3b1s/pi-repair-layer/pi");
199
214
  return repair.adaptToolDefinition;
200
215
  } catch (error) {
201
- const code = (error as { code?: unknown } | null)?.code;
202
- const message = error instanceof Error ? error.message : String(error);
203
- const packageAbsent =
204
- (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") &&
205
- message.includes("@r3b1s/pi-repair-layer");
206
- if (!packageAbsent) throw error;
216
+ if (!isRepairPackageAbsent(error)) throw error;
207
217
  return undefined;
208
218
  }
209
219
  }
@@ -225,12 +235,16 @@ The details are load-bearing:
225
235
  `code: "MODULE_NOT_FOUND"` (jiti's require path) or
226
236
  `code: "ERR_MODULE_NOT_FOUND"` (native ESM and the compiled pi binary). But
227
237
  a *present-but-broken* install — pi-repair-layer resolvable while one of its
228
- own transitive modules is not — throws the same codes naming the
229
- *transitive* module. Requiring the message to name
230
- `@r3b1s/pi-repair-layer` keeps a broken install loud instead of silently
231
- running unwrapped while the user believes repairs are active. Match the
232
- package name, not the `/pi` subpath: native ESM reports only
233
- `Cannot find package '@r3b1s/pi-repair-layer'`.
238
+ own transitive modules (e.g. `typebox`) is not — throws the same codes
239
+ naming the *transitive* module, and its message embeds
240
+ `.../node_modules/@r3b1s/pi-repair-layer/...` as a path segment. Match the
241
+ package name only where it appears as an imported specifier — an opening
242
+ quote immediately followed by the name (`'@r3b1s/pi-repair-layer`) so that
243
+ path segment does not read as absence. No trailing quote: jiti and the
244
+ compiled binary name the full subpath (`'@r3b1s/pi-repair-layer/pi'`) while
245
+ native ESM names the bare package (`'@r3b1s/pi-repair-layer'`); both start
246
+ with quote-then-name. This keeps a broken install loud (it rethrows) instead
247
+ of silently running unwrapped while the user believes repairs are active.
234
248
  - **Rethrow everything else.** Any other error is a real failure, not
235
249
  absence.
236
250
  - **Emit one stderr line when falling back.** The two branches differ in
@@ -337,7 +351,11 @@ touches is deliberately small and covered by the compatibility contract in
337
351
  current major; documented exports follow semantic versioning.
338
352
  - Absence detection semantics are part of the contract: a missing package
339
353
  surfaces with `code` `MODULE_NOT_FOUND` or `ERR_MODULE_NOT_FOUND` and a
340
- message naming the requested module.
354
+ message naming the requested module. The recipe matches that name as a
355
+ quoted specifier (`'@r3b1s/pi-repair-layer`, opening quote + name), not a
356
+ bare substring, so the package name appearing as a `node_modules` path
357
+ segment in a present-but-broken install rethrows loudly rather than reading
358
+ as absence.
341
359
  - Unrecognized preprocessor `kind`s are ignored — never fatal, no mutation, no
342
360
  claimed change — and results are still schema-validated. Repair options
343
361
  written against a newer minor version therefore degrade to the recognized
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r3b1s/pi-repair-layer",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
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",