test(auto-reply): accelerate fallback coverage (#107316)

This commit is contained in:
Peter Steinberger
2026-07-14 02:21:21 -07:00
committed by GitHub
parent 275cc7fd8f
commit d87aea2b83
4 changed files with 39 additions and 43 deletions

View File

@@ -41,3 +41,33 @@ export function resolveRunAuthProfile(
workspaceDir: run.workspaceDir,
});
}
/** Applies an auto-fallback probe's pinned auth to its fallback candidate. */
export function resolveFallbackCandidateRun(
run: FollowupRun["run"],
provider: string,
model: string,
): FollowupRun["run"] {
const probe = run.autoFallbackPrimaryProbe;
const isPrimaryProbeCandidate = probe && provider === probe.provider && model === probe.model;
if (
!probe ||
provider !== probe.fallbackProvider ||
isPrimaryProbeCandidate ||
!probe.fallbackAuthProfileId
) {
return run;
}
const candidateRun: FollowupRun["run"] = {
...run,
provider,
model,
authProfileId: probe.fallbackAuthProfileId,
};
if (probe.fallbackAuthProfileIdSource) {
candidateRun.authProfileIdSource = probe.fallbackAuthProfileIdSource;
} else {
delete candidateRun.authProfileIdSource;
}
return candidateRun;
}

View File

@@ -27,6 +27,7 @@ import { getReplyPayloadMetadata } from "../reply-payload.js";
import type { TemplateContext } from "../templating.js";
import { SILENT_REPLY_TOKEN } from "../tokens.js";
import type { GetReplyOptions, ReplyPayload } from "../types.js";
import { resolveFallbackCandidateRun } from "./agent-runner-auth-profile.js";
import {
buildEmptyInteractiveReplyPayload,
buildKnownAgentRunFailureReplyPayload,
@@ -2081,7 +2082,7 @@ describe("runAgentTurnWithFallback", () => {
expect(rechecked.hasAutoFallbackProvenance).toBeUndefined();
});
it("keeps fallback auth available when a primary probe falls back", async () => {
it("keeps fallback auth available when a primary probe falls back", () => {
const probe = {
provider: "anthropic",
model: "claude-sonnet-4-6",
@@ -2096,21 +2097,7 @@ describe("runAgentTurnWithFallback", () => {
followupRun.run.authProfileId = "anthropic:primary";
followupRun.run.authProfileIdSource = "auto";
followupRun.run.autoFallbackPrimaryProbe = probe;
state.runWithModelFallbackMock.mockImplementationOnce(async (params: FallbackRunnerParams) => ({
result: await params.run("google", "gemini-3-pro"),
provider: "google",
model: "gemini-3-pro",
attempts: [{ provider: "anthropic", model: "claude-sonnet-4-6", error: "rate limit" }],
}));
state.runEmbeddedAgentMock.mockResolvedValueOnce({
payloads: [{ text: "fallback" }],
meta: {},
});
const runAgentTurnWithFallback = await getRunAgentTurnWithFallback();
await runAgentTurnWithFallback(createMinimalRunAgentTurnParams({ followupRun }));
expectMockCallArgFields(state.runEmbeddedAgentMock, 0, "embedded run", {
expect(resolveFallbackCandidateRun(followupRun.run, "google", "gemini-3-pro")).toMatchObject({
provider: "google",
model: "gemini-3-pro",
authProfileId: "google:fallback",

View File

@@ -121,7 +121,7 @@ import {
resolveAgentLifecycleTerminalMetadata,
type AgentLifecycleTerminalBackstop,
} from "./agent-lifecycle-terminal.js";
import { resolveRunAuthProfile } from "./agent-runner-auth-profile.js";
import { resolveFallbackCandidateRun, resolveRunAuthProfile } from "./agent-runner-auth-profile.js";
import {
clearDroppedCliSessionBinding,
createCliReasoningStreamBridge,
@@ -1490,30 +1490,6 @@ async function runAgentTurnWithFallbackInternal(
const preserveUserFacingSessionState = shouldPreserveUserFacingSessionStateForInputProvenance(
effectiveRun.inputProvenance,
);
const resolveRunForFallbackCandidate = (provider: string, model: string): FollowupRun["run"] => {
const probe = effectiveRun.autoFallbackPrimaryProbe;
const isPrimaryProbeCandidate = probe && provider === probe.provider && model === probe.model;
if (
probe &&
provider === probe.fallbackProvider &&
!isPrimaryProbeCandidate &&
probe.fallbackAuthProfileId
) {
const candidateRun: FollowupRun["run"] = {
...effectiveRun,
provider,
model,
authProfileId: probe.fallbackAuthProfileId,
};
if (probe.fallbackAuthProfileIdSource) {
candidateRun.authProfileIdSource = probe.fallbackAuthProfileIdSource;
} else {
delete candidateRun.authProfileIdSource;
}
return candidateRun;
}
return effectiveRun;
};
let liveModelSwitchRuntimeEntry:
| Pick<SessionEntry, "agentHarnessId" | "agentRuntimeOverride" | "modelSelectionLocked">
| undefined;
@@ -1945,7 +1921,7 @@ async function runAgentTurnWithFallbackInternal(
queuedUserMessagePersistedAcrossFallback;
const suppressAssistantErrorPersistenceForCandidate =
assistantErrorPersistedAcrossFallback;
const candidateRun = resolveRunForFallbackCandidate(provider, model);
const candidateRun = resolveFallbackCandidateRun(effectiveRun, provider, model);
const candidateThinkLevel = resolveCandidateThinkingLevel({
cfg: runtimeConfig,
provider,

View File

@@ -6752,7 +6752,10 @@ describe("createFollowupRunner messaging delivery and dedupe", () => {
onAgentEvent?: (evt: { stream: string; data: Record<string, unknown> }) => Promise<void>;
}) => {
await args.onAgentEvent?.({ stream: "compaction", data: { phase: "start" } });
return { payloads: [], meta: {} };
return {
payloads: [{ text: DELIVERY_NO_REPLY_RUNTIME_CONTRACT.silentText }],
meta: {},
};
},
);
const runner = createFollowupRunner({