copilot-api-plus 1.3.0 → 1.3.2

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/dist/main.js CHANGED
@@ -3209,6 +3209,39 @@ function normalizeAdaptiveThinkingForCopilot(payload) {
3209
3209
  }
3210
3210
  }
3211
3211
  /**
3212
+ * If the client did not specify a `thinking` field, inject the maximum
3213
+ * thinking budget the model supports — pulled from Copilot's `/models`
3214
+ * capabilities. Mutates in place.
3215
+ *
3216
+ * - Models with `adaptive_thinking: true` (claude-opus-4.7,
3217
+ * claude-sonnet-4.6) get `{ type: "adaptive" }` so the model
3218
+ * decides depth dynamically — recommended by Anthropic for
3219
+ * these models.
3220
+ * - Other thinking-capable models get
3221
+ * `{ type: "enabled", budget_tokens: max_thinking_budget }`.
3222
+ * - Models without thinking capability are left untouched.
3223
+ *
3224
+ * Skipped if the client already specified `thinking` (any value) — we
3225
+ * always defer to explicit client intent.
3226
+ */
3227
+ function injectMaxThinkingBudget(payload) {
3228
+ if (payload.thinking !== void 0) return;
3229
+ const supports = findModel(payload.model)?.capabilities.supports;
3230
+ if (!supports) return;
3231
+ const maxBudget = supports.max_thinking_budget;
3232
+ if (!maxBudget || maxBudget <= 0) return;
3233
+ if (supports.adaptive_thinking === true) {
3234
+ payload.thinking = { type: "adaptive" };
3235
+ consola.debug(`Injected adaptive thinking for ${payload.model} (no client preference)`);
3236
+ return;
3237
+ }
3238
+ payload.thinking = {
3239
+ type: "enabled",
3240
+ budget_tokens: maxBudget
3241
+ };
3242
+ consola.debug(`Injected enabled thinking budget=${maxBudget} for ${payload.model} (no client preference)`);
3243
+ }
3244
+ /**
3212
3245
  * Remove all `thinking` and `redacted_thinking` blocks from assistant
3213
3246
  * messages, and drop any assistant turns left empty as a result.
3214
3247
  *
@@ -3253,6 +3286,7 @@ function stripAssistantThinkingBlocks(payload) {
3253
3286
  /** Detect the upstream "invalid thinking signature" 400 to trigger retry. */
3254
3287
  async function isInvalidThinkingSignatureError(error) {
3255
3288
  if (!(error instanceof HTTPError) || error.response.status !== 400) return false;
3289
+ if (INVALID_THINKING_SIGNATURE_PATTERN.test(error.message)) return true;
3256
3290
  const message = await readUpstreamErrorMessage(error.response);
3257
3291
  return typeof message === "string" && INVALID_THINKING_SIGNATURE_PATTERN.test(message);
3258
3292
  }
@@ -3315,12 +3349,21 @@ function looksLikeClaudeModel(model) {
3315
3349
  /** Per-process cache of the routing decision keyed by model id. */
3316
3350
  const routeCache = /* @__PURE__ */ new Map();
3317
3351
  /**
3352
+ * Endpoint identifiers that mean "native Anthropic /v1/messages".
3353
+ *
3354
+ * Copilot's `/models` response uses the literal `/v1/messages` path,
3355
+ * but jer-y/copilot-proxy and earlier Copilot betas used the symbolic
3356
+ * name `anthropic-messages`. Accept both so we are forward- and
3357
+ * backward-compatible with whichever wire format Copilot returns.
3358
+ */
3359
+ const NATIVE_ANTHROPIC_ENDPOINT_IDS = new Set(["/v1/messages", "anthropic-messages"]);
3360
+ /**
3318
3361
  * Resolve the upstream route for an Anthropic /v1/messages payload.
3319
3362
  *
3320
3363
  * Order of precedence:
3321
3364
  * 1. User force-disabled native passthrough — always translate.
3322
- * 2. Model advertises `anthropic-messages` in supported_endpoints → native.
3323
- * 3. Model advertises supported_endpoints WITHOUT anthropic-messages → translate.
3365
+ * 2. Model advertises a native Anthropic endpoint → native.
3366
+ * 3. Model advertises supported_endpoints WITHOUT a native one → translate.
3324
3367
  * 4. Capability missing → fall back to name heuristic (claude-* → native).
3325
3368
  */
3326
3369
  function resolveAnthropicRoute(model) {
@@ -3333,7 +3376,7 @@ function resolveAnthropicRoute(model) {
3333
3376
  }
3334
3377
  function decideRoute(model) {
3335
3378
  const endpoints = findModel(model)?.supported_endpoints;
3336
- if (Array.isArray(endpoints) && endpoints.length > 0) return endpoints.includes("anthropic-messages") ? "native-anthropic" : "translate-openai";
3379
+ if (Array.isArray(endpoints) && endpoints.length > 0) return endpoints.some((ep) => NATIVE_ANTHROPIC_ENDPOINT_IDS.has(ep)) ? "native-anthropic" : "translate-openai";
3337
3380
  return looksLikeClaudeModel(model) ? "native-anthropic" : "translate-openai";
3338
3381
  }
3339
3382
 
@@ -3384,13 +3427,20 @@ function buildAnthropicHeaders(payload, source, options$1) {
3384
3427
  };
3385
3428
  }
3386
3429
  async function createAnthropicMessages(payload, options$1) {
3387
- sanitizeForCopilotBackend(payload);
3388
- normalizeAdaptiveThinkingForCopilot(payload);
3430
+ injectMaxThinkingBudget(payload);
3431
+ const preStripped = stripAssistantThinkingBlocks(payload);
3432
+ let workingPayload = payload;
3433
+ if (preStripped.stripped) {
3434
+ consola.debug(`Pre-stripped ${preStripped.strippedBlocks} assistant thinking block(s) from history (Copilot/Vertex does not accept replay)`);
3435
+ workingPayload = preStripped.payload;
3436
+ }
3437
+ sanitizeForCopilotBackend(workingPayload);
3438
+ normalizeAdaptiveThinkingForCopilot(workingPayload);
3389
3439
  try {
3390
- return await dispatchAnthropicRequest(payload, options$1);
3440
+ return await dispatchAnthropicRequest(workingPayload, options$1);
3391
3441
  } catch (error) {
3392
3442
  if (!await isInvalidThinkingSignatureError(error)) throw error;
3393
- const stripped = stripAssistantThinkingBlocks(payload);
3443
+ const stripped = stripAssistantThinkingBlocks(workingPayload);
3394
3444
  if (!stripped.stripped) throw error;
3395
3445
  const droppedSuffix = stripped.droppedAssistantMessages > 0 ? ` and dropping ${stripped.droppedAssistantMessages} thinking-only assistant turn(s)` : "";
3396
3446
  consola.warn(`Native /v1/messages signature retry: stripped ${stripped.strippedBlocks} thinking block(s)${droppedSuffix}`);