mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 07:12:12 +03:00
fix(sse): stop force-injecting advanced-tool-use beta via the effort-2025-11-24 gate; forward client-negotiated effort through the allowlist (#9505)
Closes #9505
This commit is contained in:
committed by
GitHub
parent
ee4cd0d795
commit
5f3dad4da6
1
changelog.d/fixes/9505-atu-effort-beta-allowlist.md
Normal file
1
changelog.d/fixes/9505-atu-effort-beta-allowlist.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(sse): stop force-injecting advanced-tool-use beta via the effort-2025-11-24 gate; forward client-negotiated effort through the allowlist (#9505)
|
||||
@@ -57,6 +57,11 @@ export const FORWARDABLE_CLIENT_BETAS = Object.freeze([
|
||||
"context-1m-2025-08-07",
|
||||
"code-execution-2025-08-25",
|
||||
"skills-2025-10-02",
|
||||
// effort-2025-11-24 is a client-negotiated beta (Claude Code sends it on every
|
||||
// request). selectBetaFlags no longer force-adds it as a side-effect of the ATU
|
||||
// gate (#9505), so a client that sent it must keep it through the merge —
|
||||
// otherwise its effort negotiation is silently dropped.
|
||||
"effort-2025-11-24",
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
@@ -357,10 +357,12 @@ export function selectBetaFlags(
|
||||
// betas it actually asked for. Opaque clients (clientBetaSet === null) keep them all.
|
||||
const allowThinking =
|
||||
clientBetaSet === null || clientBetaSet.has("interleaved-thinking-2025-05-14");
|
||||
// effort-2025-11-24 must NOT imply advanced-tool-use-2025-11-20 (#9505): Claude
|
||||
// Code sends effort on every request and never sends ATU, so treating effort as
|
||||
// a proxy for ATU force-injects the heavy-agent pair the client never negotiated —
|
||||
// the same class of mutation #3415 closed. Opaque clients keep the full set.
|
||||
const allowHeavy =
|
||||
clientBetaSet === null ||
|
||||
clientBetaSet.has("advanced-tool-use-2025-11-20") ||
|
||||
clientBetaSet.has("effort-2025-11-24");
|
||||
clientBetaSet === null || clientBetaSet.has("advanced-tool-use-2025-11-20");
|
||||
const hasSystem =
|
||||
!!b.system &&
|
||||
(typeof b.system === "string" || (Array.isArray(b.system) && b.system.length > 0));
|
||||
|
||||
74
tests/unit/claude-atu-effort-leak-9505.test.ts
Normal file
74
tests/unit/claude-atu-effort-leak-9505.test.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
// Regression guard for #9505 — forced advanced-tool-use beta must not survive
|
||||
// the effort-2025-11-24 gate; client-negotiated effort must survive the merge.
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const { selectBetaFlags } = await import(
|
||||
"../../open-sse/executors/claudeIdentity.ts"
|
||||
);
|
||||
const { mergeClientAnthropicBeta } = await import(
|
||||
"../../open-sse/config/anthropicHeaders.ts"
|
||||
);
|
||||
|
||||
function fullAgentBody(model: string) {
|
||||
return {
|
||||
model,
|
||||
system: "You are a coding agent.",
|
||||
tools: [
|
||||
{ name: "read_file", description: "x", input_schema: { type: "object" } },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function pipeline(model: string, clientBeta: string | null) {
|
||||
return mergeClientAnthropicBeta(
|
||||
selectBetaFlags(fullAgentBody(model), null, clientBeta),
|
||||
clientBeta
|
||||
);
|
||||
}
|
||||
|
||||
test("#9505 client sends effort but NOT advanced-tool-use -> ATU must NOT be forced", () => {
|
||||
const out = pipeline("claude-opus-5", "claude-code-20250219,effort-2025-11-24");
|
||||
assert.ok(
|
||||
!out.split(",").includes("advanced-tool-use-2025-11-20"),
|
||||
"must NOT force ATU when client only sent effort"
|
||||
);
|
||||
});
|
||||
|
||||
test("#9505 client sends effort only -> effort still survives the merge", () => {
|
||||
const out = pipeline("claude-opus-5", "claude-code-20250219,effort-2025-11-24");
|
||||
assert.ok(
|
||||
out.split(",").includes("effort-2025-11-24"),
|
||||
"client-sent effort must survive the allowlist merge"
|
||||
);
|
||||
});
|
||||
|
||||
test("#9505 client sends advanced-tool-use explicitly -> ATU preserved", () => {
|
||||
const out = pipeline(
|
||||
"claude-opus-5",
|
||||
"claude-code-20250219,advanced-tool-use-2025-11-20"
|
||||
);
|
||||
assert.ok(
|
||||
out.split(",").includes("advanced-tool-use-2025-11-20"),
|
||||
"must keep ATU when client requested it"
|
||||
);
|
||||
assert.ok(
|
||||
out.split(",").includes("effort-2025-11-24"),
|
||||
"ATU+effort pair stays together when ATU requested"
|
||||
);
|
||||
});
|
||||
|
||||
test("#9505 client sends BOTH effort and ATU -> both preserved", () => {
|
||||
const out = pipeline(
|
||||
"claude-sonnet-5",
|
||||
"claude-code-20250219,advanced-tool-use-2025-11-20,effort-2025-11-24"
|
||||
);
|
||||
assert.ok(out.split(",").includes("advanced-tool-use-2025-11-20"));
|
||||
assert.ok(out.split(",").includes("effort-2025-11-24"));
|
||||
});
|
||||
|
||||
test("#9505 opaque client (no clientBeta) still gets full heavy-agent set", () => {
|
||||
const flags = selectBetaFlags(fullAgentBody("claude-opus-5"));
|
||||
assert.ok(flags.includes("advanced-tool-use-2025-11-20"));
|
||||
assert.ok(flags.includes("effort-2025-11-24"));
|
||||
});
|
||||
Reference in New Issue
Block a user