




















@@ -650,6 +650,35 @@ function setupModelSwitchRetry(switchOptions: ModelSwitchOptions) {
650650});
651651}
652652653+function requireRecord(value: unknown, label: string): Record<string, unknown> {
654+if (!value || typeof value !== "object") {
655+throw new Error(`expected ${label} to be an object`);
656+}
657+return value as Record<string, unknown>;
658+}
659+660+function requireArray(value: unknown, label: string): unknown[] {
661+if (!Array.isArray(value)) {
662+throw new Error(`expected ${label} to be an array`);
663+}
664+return value;
665+}
666+667+function mockCallArg(mock: ReturnType<typeof vi.fn>, callIndex = 0, argIndex = 0): unknown {
668+const call = mock.mock.calls[callIndex] as unknown[] | undefined;
669+if (!call) {
670+throw new Error(`expected mock call ${callIndex}`);
671+}
672+return call[argIndex];
673+}
674+675+function expectRecordFields(value: unknown, expected: Record<string, unknown>): void {
676+const actual = requireRecord(value, "record");
677+for (const [key, expectedValue] of Object.entries(expected)) {
678+expect(actual[key]).toEqual(expectedValue);
679+}
680+}
681+653682async function runBasicAgentCommand() {
654683await agentCommand({
655684message: "hello",
@@ -660,10 +689,10 @@ async function runBasicAgentCommand() {
660689661690function expectFallbackOverrideCalls(first: boolean, second: boolean) {
662691expect(state.resolveEffectiveModelFallbacksMock).toHaveBeenCalledTimes(2);
663-expect(state.resolveEffectiveModelFallbacksMock.mock.calls[0][0]).toMatchObject({
692+expectRecordFields(mockCallArg(state.resolveEffectiveModelFallbacksMock, 0), {
664693hasSessionModelOverride: first,
665694});
666-expect(state.resolveEffectiveModelFallbacksMock.mock.calls[1][0]).toMatchObject({
695+expectRecordFields(mockCallArg(state.resolveEffectiveModelFallbacksMock, 1), {
667696hasSessionModelOverride: second,
668697});
669698}
@@ -785,20 +814,19 @@ describe("agentCommand – LiveSessionModelSwitchError retry", () => {
785814thinking: "xhigh",
786815});
787816788-expect(state.isThinkingLevelSupportedMock).toHaveBeenCalledWith(
789-expect.objectContaining({
790-provider: "gmn",
791-model: "gpt-5.4",
792-level: "xhigh",
793-catalog: [
794-expect.objectContaining({
795-provider: "gmn",
796-id: "gpt-5.4",
797-compat: { supportedReasoningEfforts: ["low", "medium", "high", "xhigh"] },
798-}),
799-],
800-}),
817+const thinkingArgs = requireRecord(
818+mockCallArg(state.isThinkingLevelSupportedMock),
819+"thinking args",
801820);
821+expect(thinkingArgs.provider).toBe("gmn");
822+expect(thinkingArgs.model).toBe("gpt-5.4");
823+expect(thinkingArgs.level).toBe("xhigh");
824+const catalog = requireArray(thinkingArgs.catalog, "thinking catalog");
825+expectRecordFields(catalog[0], {
826+provider: "gmn",
827+id: "gpt-5.4",
828+compat: { supportedReasoningEfforts: ["low", "medium", "high", "xhigh"] },
829+});
802830});
803831804832it("validates explicit thinking against allowlisted configured model compat when manifest catalog is empty", async () => {
@@ -846,20 +874,19 @@ describe("agentCommand – LiveSessionModelSwitchError retry", () => {
846874});
847875848876expect(state.loadManifestModelCatalogMock).toHaveBeenCalled();
849-expect(state.isThinkingLevelSupportedMock).toHaveBeenCalledWith(
850-expect.objectContaining({
851-provider: "gmn",
852-model: "gpt-5.4",
853-level: "xhigh",
854-catalog: [
855-expect.objectContaining({
856-provider: "gmn",
857-id: "gpt-5.4",
858-compat: { supportedReasoningEfforts: ["low", "medium", "high", "xhigh"] },
859-}),
860-],
861-}),
877+const thinkingArgs = requireRecord(
878+mockCallArg(state.isThinkingLevelSupportedMock),
879+"thinking args",
862880);
881+expect(thinkingArgs.provider).toBe("gmn");
882+expect(thinkingArgs.model).toBe("gpt-5.4");
883+expect(thinkingArgs.level).toBe("xhigh");
884+const catalog = requireArray(thinkingArgs.catalog, "thinking catalog");
885+expectRecordFields(catalog[0], {
886+provider: "gmn",
887+id: "gpt-5.4",
888+compat: { supportedReasoningEfforts: ["low", "medium", "high", "xhigh"] },
889+});
863890});
864891865892it("records fallback steps to the session trajectory runtime", async () => {
@@ -884,17 +911,16 @@ describe("agentCommand – LiveSessionModelSwitchError retry", () => {
884911885912await runBasicAgentCommand();
886913887-expect(state.trajectoryRecordEventMock).toHaveBeenCalledWith(
888-"model.fallback_step",
889-expect.objectContaining({
890-fallbackStepType: "fallback_step",
891-fallbackStepFromModel: "ollama/llama3",
892-fallbackStepToModel: "openai/gpt-5.4",
893-fallbackStepFromFailureReason: "overloaded",
894-fallbackStepChainPosition: 1,
895-fallbackStepFinalOutcome: "next_fallback",
896-}),
897-);
914+expect(state.trajectoryRecordEventMock).toHaveBeenCalledTimes(1);
915+expect(state.trajectoryRecordEventMock.mock.calls[0]?.[0]).toBe("model.fallback_step");
916+expectRecordFields(state.trajectoryRecordEventMock.mock.calls[0]?.[1], {
917+fallbackStepType: "fallback_step",
918+fallbackStepFromModel: "ollama/llama3",
919+fallbackStepToModel: "openai/gpt-5.4",
920+fallbackStepFromFailureReason: "overloaded",
921+fallbackStepChainPosition: 1,
922+fallbackStepFinalOutcome: "next_fallback",
923+});
898924expect(state.trajectoryFlushMock).toHaveBeenCalled();
899925});
900926@@ -1102,7 +1128,7 @@ describe("agentCommand – LiveSessionModelSwitchError retry", () => {
11021128const attemptParams = state.runAgentAttemptMock.mock.calls[0]?.[0] as
11031129| { skillsSnapshot?: Record<string, unknown> }
11041130| undefined;
1105-expect(attemptParams?.skillsSnapshot).toMatchObject({
1131+expectRecordFields(attemptParams?.skillsSnapshot, {
11061132prompt: "persisted prompt",
11071133skills: [{ name: "cli-skill" }],
11081134skillFilter: ["cli-skill"],
@@ -1145,30 +1171,28 @@ describe("agentCommand – LiveSessionModelSwitchError retry", () => {
1145117111461172await runBasicAgentCommand();
114711731148-expect(observedClassification).toMatchObject({
1174+expectRecordFields(observedClassification, {
11491175reason: "format",
11501176code: "empty_result",
11511177});
11521178expect(state.runAgentAttemptMock).toHaveBeenCalledTimes(2);
1153-expect(state.runAgentAttemptMock.mock.calls[1]?.[0]).toMatchObject({
1179+expectRecordFields(state.runAgentAttemptMock.mock.calls[1]?.[0], {
11541180providerOverride: "openai",
11551181modelOverride: "gpt-5.4",
11561182isFallbackRetry: true,
11571183});
1158-expect(state.deliverAgentCommandResultMock.mock.calls[0]?.[0]).toMatchObject({
1159-result: {
1160-meta: {
1161-agentMeta: {
1162-fallbackAttempts: [
1163-expect.objectContaining({
1164-provider: "anthropic",
1165-model: "claude",
1166-reason: "format",
1167-}),
1168-],
1169-},
1170-},
1171-},
1184+const deliveryParams = requireRecord(
1185+state.deliverAgentCommandResultMock.mock.calls[0]?.[0],
1186+"delivery params",
1187+);
1188+const result = requireRecord(deliveryParams.result, "delivery result");
1189+const meta = requireRecord(result.meta, "delivery result meta");
1190+const agentMeta = requireRecord(meta.agentMeta, "delivery agent meta");
1191+const fallbackAttempts = requireArray(agentMeta.fallbackAttempts, "fallback attempts");
1192+expectRecordFields(fallbackAttempts[0], {
1193+provider: "anthropic",
1194+model: "claude",
1195+reason: "format",
11721196});
11731197});
11741198此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。