Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 40 additions & 7 deletions open-sse/services/combo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export {
import {
applyNativeCodexTurnPin,
areAllPinnedTargetsModelScopedUnusable,
canAutoResumeNativeCodexTurn,
createPinnedModelUnavailableResponse,
getNativeCodexTurnPin,
} from "./combo/nativeCodexTurnPin.ts";
Expand Down Expand Up @@ -752,9 +753,10 @@ async function handleComboChatInner({
});
if (runtimeUnitDispatch) return runtimeUnitDispatch;

const activeNativeTurnPin = clientManagedResponsesContext
let activeNativeTurnPin = clientManagedResponsesContext
? getNativeCodexTurnPin(body, combo.name)
: null;
let isAutoResuming = false;

// Route new round-robin turns to the specialized handler. A native Codex
// continuation with an established provider/account pin must use the common
Expand Down Expand Up @@ -832,12 +834,42 @@ async function handleComboChatInner({
isModelAvailable,
});
if (allPinnedUnusable) {
targetResolution.quotaShareRelease?.();
log.warn(
"COMBO",
`Native Codex turn cannot continue: pinned model ${activeNativeTurnPin.modelStr} is unavailable (model-scoped); preserving turn pin and terminating turn`
);
return createPinnedModelUnavailableResponse();
const autoResumeEligibility = await canAutoResumeNativeCodexTurn({
body: body as Record<string, unknown>,
comboName: combo.name,
activePin: activeNativeTurnPin,
allTargets: orderedTargets,
resilienceSettings,
quotaCutoffResetWindowConfig,
isModelAvailable,
log,
});

if (autoResumeEligibility.eligible) {
const selectedAlternate = autoResumeEligibility.selectedTarget;
log.info(
"COMBO",
`Native Codex auto-resume eligible: previous provider/model=${activeNativeTurnPin.provider}/${activeNativeTurnPin.modelStr}, previous logical turn generation=${autoResumeEligibility.previousPin.generation ?? 0}, reason=model_scoped_unavailable`
);
log.info(
"COMBO",
`Native Codex auto-resume started: previous provider/model=${activeNativeTurnPin.provider}/${activeNativeTurnPin.modelStr}, target provider/model=${selectedAlternate.provider}/${selectedAlternate.modelStr}, target generation=${autoResumeEligibility.nextGeneration}`
);
const alternateTargets = orderedTargets.filter(
(t) =>
t.modelStr === selectedAlternate.modelStr && t.provider === selectedAlternate.provider
);
orderedTargets = alternateTargets;
activeNativeTurnPin = null;
isAutoResuming = true;
} else {
targetResolution.quotaShareRelease?.();
log.warn(
"COMBO",
`Native Codex turn cannot continue: pinned model ${activeNativeTurnPin.modelStr} is unavailable (model-scoped); auto-resume rejected (${autoResumeEligibility.reason}); preserving turn pin and terminating turn`
);
return createPinnedModelUnavailableResponse();
}
} else {
orderedTargets = pinnedTargets;
log.info(
Expand Down Expand Up @@ -959,6 +991,7 @@ async function handleComboChatInner({
releaseStickyPinOnFailure,
clearStaleLKGP,
clientManagedResponsesContext,
nativeCodexAutoResume: isAutoResuming,
reasoningTokenBufferEnabled,
stickyWeightedLimit,
getWeightedStepKeyForTarget,
Expand Down
1 change: 1 addition & 0 deletions open-sse/services/combo/attemptLoopTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export type AttemptLoopDeps = {
* gate tests keep compiling; attempt uses defaults when absent.
*/
clientManagedResponsesContext?: boolean;
nativeCodexAutoResume?: boolean;
reasoningTokenBufferEnabled?: boolean;
stickyWeightedLimit?: number;
getWeightedStepKeyForTarget?: (target: ResolvedComboTarget) => string | null;
Expand Down
32 changes: 25 additions & 7 deletions open-sse/services/combo/executeTargetAttempt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ import {
isModelScoped400,
} from "./comboPredicates.ts";
import { applyComboTargetExhaustion } from "./targetExhaustion.ts";
import { pinNativeCodexTurn } from "./nativeCodexTurnPin.ts";
import {
advanceNativeCodexTurnGeneration,
pinNativeCodexTurn,
} from "./nativeCodexTurnPin.ts";
import { recordComboDecision } from "./decisionTrace.ts";
import { recordProviderCooldown } from "../providerCooldownTracker.ts";
import {
Expand Down Expand Up @@ -451,12 +454,27 @@ export async function executeTargetAttempt(opts: {
}

if (Boolean(deps.clientManagedResponsesContext) && effectiveConnectionId) {
pinNativeCodexTurn({
body: deps.body,
comboName: deps.combo.name,
target,
connectionId: effectiveConnectionId,
});
if (deps.nativeCodexAutoResume) {
const nextGen = advanceNativeCodexTurnGeneration(deps.body, deps.combo.name);
deps.log.info(
"COMBO",
`Native Codex auto-resume routed: new provider/model=${target.modelStr} on connection ${effectiveConnectionId.slice(0, 8)} (logical turn generation ${nextGen})`
);
pinNativeCodexTurn({
body: deps.body,
comboName: deps.combo.name,
target,
connectionId: effectiveConnectionId,
generation: nextGen ?? undefined,
});
} else {
pinNativeCodexTurn({
body: deps.body,
comboName: deps.combo.name,
target,
connectionId: effectiveConnectionId,
});
}
}

// Success decay: a healthy response walks the model's lockout failure
Expand Down
Loading
Loading