test(auto-reply): prove prepared ownership through queue params

This commit is contained in:
joshavant
2026-08-10 19:59:32 -05:00
committed by Josh Avant
parent 375df347c4
commit 3d6028da4c
3 changed files with 64 additions and 43 deletions
@@ -802,6 +802,7 @@ export async function loadRunOverflowCompactionHarness(): Promise<{
prepareProviderRuntimeAuth: mockedPrepareProviderRuntimeAuth,
resolveProviderCapabilitiesWithPlugin: vi.fn(() => ({})),
resolveProviderAuthProfileId: vi.fn(() => undefined),
resolveProviderReasoningOutputModeWithPlugin: vi.fn(() => undefined),
shouldPreferProviderRuntimeResolvedModel: vi.fn(() => false),
prepareProviderExtraParams: vi.fn(async () => ({})),
wrapProviderStreamFn: vi.fn((_cfg: unknown, _model: unknown, fn: unknown) => fn),
@@ -950,7 +951,10 @@ export async function loadRunOverflowCompactionHarness(): Promise<{
redactRunIdentifier: vi.fn((value?: string) => value ?? ""),
}));
vi.doMock("../embedded-agent-helpers.js", () => ({
vi.doMock("../embedded-agent-helpers.js", async () => ({
...(await vi.importActual<typeof import("../embedded-agent-helpers.js")>(
"../embedded-agent-helpers.js",
)),
formatBillingErrorMessage: mockedFormatBillingErrorMessage,
classifyFailoverReason: mockedClassifyFailoverReason,
classifyAssistantFailoverReason: mockedClassifyAssistantFailoverReason,
@@ -1058,10 +1062,12 @@ export async function loadRunOverflowCompactionHarness(): Promise<{
DEFAULT_PROVIDER: "anthropic",
}));
vi.doMock("../failover-error.js", () => ({
vi.doMock("../failover-error.js", async () => ({
...(await vi.importActual<typeof import("../failover-error.js")>("../failover-error.js")),
FailoverError: MockedFailoverError,
coerceToFailoverError: mockedCoerceToFailoverError,
describeFailoverError: mockedDescribeFailoverError,
isFailoverError: (error: unknown) => error instanceof MockedFailoverError,
resolveFailoverStatus: mockedResolveFailoverStatus,
}));
@@ -13,6 +13,7 @@ import {
import { createTestUserTurnTranscriptTarget } from "../../sessions/user-turn-transcript.test-support.js";
import type { TemplateContext } from "../templating.js";
import type { GetReplyOptions, ReplyPayload } from "../types.js";
import type { buildEmbeddedRunExecutionParams } from "./agent-runner-utils.js";
import type { FollowupRun } from "./queue.js";
import type { ReplyOperation } from "./reply-run-registry.js";
import type { TypingSignaler } from "./typing-mode.js";
@@ -61,6 +62,9 @@ const state = vi.hoisted(() => ({
updateSessionStoreMock: vi.fn(),
resolveCurrentTurnImagesMock: vi.fn(),
peekSessionMcpRuntimeMock: vi.fn(),
productionBuildEmbeddedRunExecutionParams: undefined as
| typeof buildEmbeddedRunExecutionParams
| undefined,
}));
export const GENERIC_RUN_FAILURE_TEXT =
@@ -245,46 +249,38 @@ vi.mock("./current-turn-images.js", () => ({
}));
vi.mock("./agent-runner-utils.js", () => ({
buildEmbeddedRunExecutionParams: (params: {
provider: string;
model: string;
run: Record<string, unknown> & {
provider?: string;
thinkLevel?: string;
authProfileId?: string;
authProfileIdSource?: "auto" | "user";
agentAccountId?: string;
chatType?: string;
};
replyRoute?: {
originatingChannel?: string;
originatingTo?: string;
originatingAccountId?: string;
originatingChatType?: string;
};
sessionCtx: { AccountId?: string; ChatType?: string };
}) => ({
embeddedContext: {
...params.run,
messageProvider: params.replyRoute?.originatingChannel,
messageTo: params.replyRoute?.originatingTo,
agentAccountId:
params.replyRoute?.originatingAccountId ??
params.sessionCtx.AccountId ??
params.run.agentAccountId,
chatType:
params.replyRoute?.originatingChatType ?? params.sessionCtx.ChatType ?? params.run.chatType,
},
senderContext: {},
runBaseParams: {
provider: params.provider,
model: params.model,
thinkLevel: params.run.thinkLevel,
authProfileId: params.provider === params.run.provider ? params.run.authProfileId : undefined,
authProfileIdSource:
params.provider === params.run.provider ? params.run.authProfileIdSource : undefined,
},
}),
buildEmbeddedRunExecutionParams: (
params: Parameters<typeof buildEmbeddedRunExecutionParams>[0],
) =>
// Most execution tests isolate fallback policy from config/channel discovery. Ownership
// regressions opt into the production builder so queue metadata must cross the real boundary.
state.productionBuildEmbeddedRunExecutionParams
? state.productionBuildEmbeddedRunExecutionParams(params)
: {
embeddedContext: {
...params.run,
messageProvider: params.replyRoute?.originatingChannel,
messageTo: params.replyRoute?.originatingTo,
agentAccountId:
params.replyRoute?.originatingAccountId ??
params.sessionCtx.AccountId ??
params.run.agentAccountId,
chatType:
params.replyRoute?.originatingChatType ??
params.sessionCtx.ChatType ??
params.run.chatType,
},
senderContext: {},
runBaseParams: {
provider: params.provider,
model: params.model,
thinkLevel: params.run.thinkLevel,
authProfileId:
params.provider === params.run.provider ? params.run.authProfileId : undefined,
authProfileIdSource:
params.provider === params.run.provider ? params.run.authProfileIdSource : undefined,
},
},
resolveQueuedReplyRuntimeConfig: <T>(config: T) => config,
resolveModelFallbackOptions: vi.fn(
(run: { provider?: string; model?: string; config?: unknown; agentDir?: string }) => ({
@@ -342,6 +338,12 @@ export async function getExecuteAgentTurnForTest() {
};
}
export async function useProductionEmbeddedRunExecutionParamsForTest(): Promise<void> {
const actual =
await vi.importActual<typeof import("./agent-runner-utils.js")>("./agent-runner-utils.js");
state.productionBuildEmbeddedRunExecutionParams = actual.buildEmbeddedRunExecutionParams;
}
export async function loadActualRunCliAgentForTest(): Promise<RunCliAgent> {
return (
await vi.importActual<typeof import("../../agents/cli-runner.js")>("../../agents/cli-runner.js")
@@ -689,6 +691,7 @@ export function setupAgentRunnerExecutionTestState() {
state.updateSessionStoreMock.mockReset();
state.resolveCurrentTurnImagesMock.mockReset();
state.peekSessionMcpRuntimeMock.mockReset();
state.productionBuildEmbeddedRunExecutionParams = undefined;
state.peekSessionMcpRuntimeMock.mockReturnValue(undefined);
state.resolveCurrentTurnImagesMock.mockImplementation(
async (params: { images?: unknown[]; imageOrder?: unknown[] }) => ({
@@ -17,6 +17,7 @@ import {
getExecuteAgentTurnForTest,
setupAgentRunnerExecutionTestState,
type FallbackRunnerParams,
useProductionEmbeddedRunExecutionParamsForTest,
} from "./agent-runner-execution.test-support.js";
import { emptyConfig, sessionStoreMocks } from "./dispatch-from-config.shared.test-harness.js";
import {
@@ -58,7 +59,18 @@ describe("prepared harness source delivery", () => {
expectedPartials: 0,
expectedFinals: 0,
},
{
name: "keeps prepared tool ownership after a failed CLI primary",
failsCliPrimary: true,
preliminaryVisibleReplies: "automatic" as const,
preparedVisibleReplies: "message_tool" as const,
expectedTransitions: ["message_tool_only", "message_tool_only"],
expectedDeliveries: 0,
expectedPartials: 0,
expectedFinals: 0,
},
])("$name", async (testCase) => {
await useProductionEmbeddedRunExecutionParamsForTest();
const { runEmbeddedAgent, registerPreparedAgentHarness } =
await loadRunOverflowCompactionHarness();
mockedGlobalHookRunner.hasHooks.mockImplementation(
@@ -219,7 +231,6 @@ describe("prepared harness source delivery", () => {
expect.any(Object),
);
expect(emittedStreamingCallbacks).toEqual(["partial", "block"]);
expect(modeTransitions).toEqual(testCase.expectedTransitions);
expect(onPartialReply).toHaveBeenCalledTimes(testCase.expectedPartials);
expect(result.queuedFinal).toBe(testCase.expectedDeliveries === 1);
if (testCase.expectedDeliveries === 1) {
@@ -238,5 +249,6 @@ describe("prepared harness source delivery", () => {
final: testCase.expectedFinals,
});
expect(dispatcher.getFailedCounts()).toEqual({ tool: 0, block: 0, final: 0 });
expect(modeTransitions).toEqual(testCase.expectedTransitions);
});
});