mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 19:35:28 -06:00
test(auto-reply): prove prepared ownership through queue params
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user