pi-quiver 5.2.2 → 5.2.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/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@ Published to npm as `pi-quiver` (`pi install npm:pi-quiver`). Pushing a
8
8
  via OIDC trusted publishing. The release helper at
9
9
  `.agents/skills/release/scripts/release.sh` cuts the tag; CI publishes.
10
10
 
11
+ ## v5.2.3 - 2026-09-04
12
+
13
+ - `fast-mode`: fix `400 fallbacks: Extra inputs are not permitted` on OAuth/subscription auth with fallback-capable models (`claude-opus-5` on pi 0.84.x). The 5.2.2 beta probe imported `@earendil-works/pi-ai/api/anthropic-messages.lazy`, which pi's extension loader does not alias for installed packages, so it always failed in real installs and the static beta list dropped `server-side-fallback-2026-07-01` while pi kept `fallbacks` in the body. Probe now imports the aliased `@earendil-works/pi-ai/compat`; the static fallback also adds the fallback beta whenever `model.compat.allowedFallbackModels` is non-empty.
14
+
11
15
  ## v5.2.2 - 2026-09-03
12
16
 
13
17
  - fast-mode: discover pi's `anthropic-beta` list at request time by probing
@@ -14,8 +14,10 @@
14
14
  * Header coupling to pi-ai internals: pi assembles `anthropic-beta` AFTER this
15
15
  * hook and merges the hook's headers LAST, so setting the header here REPLACES
16
16
  * pi's list. Instead of guessing that list, the hook discovers it: it probes
17
- * pi-ai's own request assembly (dynamic import of the lazy anthropic-messages
18
- * entrypoint) with a capturing fetch - zero network, zero tokens - and unions
17
+ * pi-ai's own request assembly (dynamic import of `@earendil-works/pi-ai/compat`,
18
+ * one of the four specifiers pi's extension loader aliases for installed
19
+ * packages - deeper subpaths like `/api/*.lazy` do NOT resolve there) with a
20
+ * capturing fetch - zero network, zero tokens - and unions
19
21
  * the captured betas with the fast-mode beta. Probe failure falls back to the
20
22
  * static reconstruction (OAUTH_IDENTITY_BETAS stays, demoted to fallback-only
21
23
  * seeding). Known limit: the probe context is tool-less, so tool/thinking-
@@ -50,6 +52,15 @@ export function scaleCost(cost: Usage["cost"], multiplier: number): Usage["cost"
50
52
  }
51
53
 
52
54
  export const OAUTH_IDENTITY_BETAS = ["claude-code-20250219", "oauth-2025-04-20"];
55
+ // Mirrors pi-ai's SERVER_SIDE_FALLBACK_BETA: pi puts `fallbacks` in the body
56
+ // whenever model.compat.allowedFallbackModels is non-empty, and OAuth rejects
57
+ // that body without the beta (400 "fallbacks: Extra inputs are not permitted").
58
+ export const SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-07-01";
59
+
60
+ export function needsFallbackBeta(model: Model<any> | undefined): boolean {
61
+ const compat = model?.compat as { allowedFallbackModels?: unknown[] } | undefined;
62
+ return (compat?.allowedFallbackModels?.length ?? 0) > 0;
63
+ }
53
64
  const STATUS_KEY = "fast-mode";
54
65
  const BETA_HEADER = "anthropic-beta";
55
66
 
@@ -90,6 +101,7 @@ export function buildBetaHeader(
90
101
  existing: string | null | undefined,
91
102
  isOAuth: boolean,
92
103
  probedBetas: string | null = null,
104
+ fallbackBeta = false,
93
105
  ): string {
94
106
  const seen = new Set<string>();
95
107
  const out: string[] = [];
@@ -101,7 +113,10 @@ export function buildBetaHeader(
101
113
  }
102
114
  };
103
115
  if (probedBetas !== null) probedBetas.split(",").forEach(add);
104
- else if (isOAuth) OAUTH_IDENTITY_BETAS.forEach(add);
116
+ else {
117
+ if (isOAuth) OAUTH_IDENTITY_BETAS.forEach(add);
118
+ if (fallbackBeta) add(SERVER_SIDE_FALLBACK_BETA);
119
+ }
105
120
  if (typeof existing === "string") existing.split(",").forEach(add);
106
121
  add(FAST_MODE_BETA);
107
122
  return out.join(",");
@@ -147,7 +162,7 @@ export async function probePiBetaHeader(
147
162
  maxRetries: 0,
148
163
  };
149
164
  try {
150
- const { anthropicMessagesApi } = await import("@earendil-works/pi-ai/api/anthropic-messages.lazy");
165
+ const { anthropicMessagesApi } = await import("@earendil-works/pi-ai/compat");
151
166
  const stream = anthropicMessagesApi().stream(model, PROBE_CONTEXT, options);
152
167
  await stream.result().catch(() => {});
153
168
  } catch {
@@ -240,7 +255,12 @@ export default function (pi: ExtensionAPI) {
240
255
  return;
241
256
  }
242
257
  const probed = await probePiBetaHeader(ctx.model!, auth);
243
- event.headers[BETA_HEADER] = buildBetaHeader(event.headers[BETA_HEADER], auth.isOAuth, probed);
258
+ event.headers[BETA_HEADER] = buildBetaHeader(
259
+ event.headers[BETA_HEADER],
260
+ auth.isOAuth,
261
+ probed,
262
+ needsFallbackBeta(ctx.model),
263
+ );
244
264
  pendingFastHeader = true;
245
265
  });
246
266
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-quiver",
3
- "version": "5.2.2",
3
+ "version": "5.2.3",
4
4
  "description": "Personal pack of Pi coding-agent extensions: context-safe fetch, doc_to_md PDF/DOCX/PPTX-to-Markdown conversion, session naming, a themed ASCII startup header, Opus 4.8 fast mode, and a provider-stall watchdog.",
5
5
  "author": "Jacek Juraszek",
6
6
  "license": "MIT",