fix(combos): default reasoning token buffer off

This commit is contained in:
Xiangzhe
2026-07-07 11:24:42 +08:00
committed by xz-dev
parent 902e66805c
commit 37ac38f17f
8 changed files with 30 additions and 23 deletions

View File

@@ -2431,7 +2431,7 @@ async function handleRoundRobinCombo({
const maxRetries = config.maxRetries ?? 1;
const retryDelayMs = resolveDelayMs(config.retryDelayMs, 2000);
const fallbackDelayMs = resolveDelayMs(config.fallbackDelayMs, 0);
const reasoningTokenBufferEnabled = config.reasoningTokenBufferEnabled !== false;
const reasoningTokenBufferEnabled = config.reasoningTokenBufferEnabled === true;
const resilienceSettings: ResilienceSettings = settings
? resolveResilienceSettings(settings)
@@ -3032,7 +3032,10 @@ async function handleRoundRobinCombo({
resilienceSettings.providerCooldown.enabled &&
provider &&
provider !== "unknown" &&
!(result.status === 500 && hasPerModelQuota(provider, parseModel(modelStr).model || modelStr))
!(
result.status === 500 &&
hasPerModelQuota(provider, parseModel(modelStr).model || modelStr)
)
) {
recordProviderCooldown(
provider,

View File

@@ -90,9 +90,7 @@ export function phaseComboSetup(ctx: ComboContext): ComboSetup {
const universalHandoffConfig = resolveUniversalHandoffConfig(
(combo.universal_handoff || combo.universalHandoff) as
| Record<string, unknown>
| null
| undefined,
Record<string, unknown> | null | undefined,
relayOptions?.universalHandoffConfig as Record<string, unknown> | null | undefined
);
@@ -118,7 +116,7 @@ export function phaseComboSetup(ctx: ComboContext): ComboSetup {
FETCH_TIMEOUT_MS,
DEFAULT_COMBO_TARGET_TIMEOUT_MS
);
const reasoningTokenBufferEnabled = config.reasoningTokenBufferEnabled !== false;
const reasoningTokenBufferEnabled = config.reasoningTokenBufferEnabled === true;
return {
strategy,

View File

@@ -53,7 +53,7 @@ const DEFAULT_COMBO_CONFIG = {
maxComboDepth: 3,
nestedComboMode: "flatten",
trackMetrics: true,
reasoningTokenBufferEnabled: true,
reasoningTokenBufferEnabled: false,
manifestRouting: false,
// Complexity-aware auto routing (2026): when on, the auto router scores
// candidates by how well their tier matches the request's classified

View File

@@ -93,7 +93,7 @@ export default function ComboDefaultsTab() {
retryDelayMs: 2000,
maxComboDepth: 3,
trackMetrics: true,
reasoningTokenBufferEnabled: true,
reasoningTokenBufferEnabled: false,
handoffThreshold: 0.85,
handoffModel: "",
maxMessagesForSummary: 30,
@@ -292,8 +292,7 @@ export default function ComboDefaultsTab() {
// Filtered provider list — excludes already-added ones, filtered by search query
const filteredProviders = availableProviders.filter(
(p) =>
!providerOverrides[p.provider] && matchesSearch(p.provider, searchQuery)
(p) => !providerOverrides[p.provider] && matchesSearch(p.provider, searchQuery)
);
const handleDropdownKeyDown = (e: React.KeyboardEvent) => {
@@ -690,11 +689,11 @@ export default function ComboDefaultsTab() {
</p>
</div>
<Toggle
checked={comboDefaults.reasoningTokenBufferEnabled !== false}
checked={comboDefaults.reasoningTokenBufferEnabled === true}
onChange={() =>
setComboDefaults((prev) => ({
...prev,
reasoningTokenBufferEnabled: prev.reasoningTokenBufferEnabled === false,
reasoningTokenBufferEnabled: prev.reasoningTokenBufferEnabled !== true,
}))
}
/>

View File

@@ -55,7 +55,7 @@ export async function GET(request: Request) {
maxMessagesForSummary: 30,
maxComboDepth: 3,
trackMetrics: true,
reasoningTokenBufferEnabled: true,
reasoningTokenBufferEnabled: false,
zeroLatencyOptimizationsEnabled: false,
},
providerOverrides,

View File

@@ -30,7 +30,7 @@ test("getDefaultComboConfig returns a fresh copy of the defaults", () => {
assert.equal(first.failoverBeforeRetry, true);
assert.equal(first.maxSetRetries, 0);
assert.equal(first.setRetryDelayMs, 2000);
assert.equal(first.reasoningTokenBufferEnabled, true);
assert.equal(first.reasoningTokenBufferEnabled, false);
assert.equal(first.zeroLatencyOptimizationsEnabled, false);
assert.equal(first.hedging, false);
assert.equal(first.fallbackCompressionMode, "lite");

View File

@@ -2869,7 +2869,7 @@ test("handleComboChat aborts combo when 503 response does NOT contain the unavai
);
});
test("#3587 reasoning model gets max_tokens buffer applied", async () => {
test("#3587 reasoning model gets max_tokens buffer applied when explicitly enabled", async () => {
saveModelsDevCapabilities({
openai: {
"gpt-4o-reasoning": capabilityEntry(12000, { reasoning: true, limit_output: 12000 }),
@@ -2882,6 +2882,7 @@ test("#3587 reasoning model gets max_tokens buffer applied", async () => {
combo: {
name: "reasoning-buffer",
models: ["openai/gpt-4o-reasoning"],
config: { reasoningTokenBufferEnabled: true },
},
handleSingleModel: async (body: Record<string, unknown>) => {
bodies.push(body);
@@ -2934,6 +2935,7 @@ test("#3587 reasoning buffer preserves max_tokens when the full buffer exceeds m
combo: {
name: "reasoning-buffer-near-cap",
models: ["openai/gemini-high-cap"],
config: { reasoningTokenBufferEnabled: true },
},
handleSingleModel: async (body: Record<string, unknown>) => {
bodies.push(body);
@@ -2983,7 +2985,7 @@ test("#3587 reasoning buffer is disabled without explicit model capability data"
);
});
test("#3588 reasoning token buffer feature flag preserves client max_tokens", async () => {
test("#3588 reasoning token buffer is disabled by default and preserves client max_tokens", async () => {
saveModelsDevCapabilities({
openai: {
"flagged-reasoning": capabilityEntry(12000, { reasoning: true, limit_output: 12000 }),
@@ -3009,11 +3011,7 @@ test("#3588 reasoning token buffer feature flag preserves client max_tokens", as
},
isModelAvailable: async () => true,
log: createLog(),
settings: {
comboDefaults: {
reasoningTokenBufferEnabled: false,
},
},
settings: null,
relayOptions: null,
allCombos: null,
});
@@ -3078,6 +3076,7 @@ test("#3587 round-robin buffer does NOT compound across reasoning models", async
name: "rr-reasoning-no-compound",
strategy: "round-robin",
models: ["openai/rr-reasoning-a", "openai/rr-reasoning-b"],
config: { reasoningTokenBufferEnabled: true },
},
handleSingleModel: async (body: Record<string, unknown>, modelStr: string) => {
seen.push({ model: modelStr, maxTokens: body.max_tokens });

View File

@@ -15,7 +15,11 @@ test("createComboContext carries inputs and the body BY REFERENCE", () => {
const body = { model: "auto", messages: [], stream: true };
const combo = { name: "c1", models: ["a", "b"] };
const ctx = createComboContext({ body, combo, log });
assert.equal(ctx.body, body, "body must be the same reference (not copied) for byte-identical pinning");
assert.equal(
ctx.body,
body,
"body must be the same reference (not copied) for byte-identical pinning"
);
assert.equal(ctx.combo, combo);
assert.equal(ctx.settings, null);
assert.equal(ctx.relayOptions, null);
@@ -34,7 +38,11 @@ test("phaseComboSetup resolves strategy/config/stream with pinning OFF (pure, no
assert.equal(setup.effectiveSessionId, null);
assert.equal(setup.clientRequestedStream, true, "body.stream === true");
assert.equal(typeof setup.comboTargetTimeoutMs, "number");
assert.equal(typeof setup.reasoningTokenBufferEnabled, "boolean");
assert.equal(
setup.reasoningTokenBufferEnabled,
false,
"reasoning token buffering is opt-in by default"
);
assert.ok(setup.config && typeof setup.config === "object", "config cascade resolved");
assert.ok(
setup.resilienceSettings && typeof setup.resilienceSettings === "object",