






















@@ -184,6 +184,16 @@ async function readUsageStats(agentDir: string) {
184184return JSON.parse(raw).usageStats as Record<string, Record<string, unknown> | undefined>;
185185}
186186187+function expectFailureCount(
188+usageStats: Record<string, Record<string, unknown> | undefined>,
189+profileId: string,
190+reason: AuthProfileFailureReason,
191+expected: number,
192+) {
193+const failureCounts = usageStats[profileId]?.failureCounts as Record<string, unknown> | undefined;
194+expect(failureCounts?.[reason]).toBe(expected);
195+}
196+187197async function writeMultiProfileAuthStore(agentDir: string) {
188198await fs.writeFile(
189199path.join(agentDir, "auth-profiles.json"),
@@ -393,10 +403,8 @@ describe("runWithModelFallback + runEmbeddedPiAgent failover behavior", () => {
393403enqueue: async (task) => await task(),
394404});
395405396-expect(result.meta.toolSummary).toMatchObject({
397-calls: 1,
398-tools: ["write"],
399-});
406+expect(result.meta.toolSummary?.calls).toBe(1);
407+expect(result.meta.toolSummary?.tools).toEqual(["write"]);
400408expect(
401409classifyEmbeddedPiRunResultForModelFallback({
402410provider: "openai-codex",
@@ -468,7 +476,7 @@ describe("runWithModelFallback + runEmbeddedPiAgent failover behavior", () => {
468476469477const usageStats = await readUsageStats(agentDir);
470478expect(typeof usageStats["openai:p1"]?.cooldownUntil).toBe("number");
471-expect(usageStats["openai:p1"]?.failureCounts).toMatchObject({ overloaded: 1 });
479+expectFailureCount(usageStats, "openai:p1", "overloaded", 1);
472480expect(typeof usageStats["groq:p1"]?.lastUsed).toBe("number");
473481474482expectOpenAiThenGroqAttemptOrder();
@@ -570,14 +578,6 @@ describe("runWithModelFallback + runEmbeddedPiAgent failover behavior", () => {
570578/openai\/mock-1: .* \(overloaded\) \| groq\/mock-2: .* \(overloaded\)/,
571579);
572580573-const usageStats = await readUsageStats(agentDir);
574-expect(typeof usageStats["openai:p1"]?.cooldownUntil).toBe("number");
575-expect(typeof usageStats["groq:p1"]?.cooldownUntil).toBe("number");
576-expect(usageStats["openai:p1"]?.failureCounts).toMatchObject({ overloaded: 1 });
577-expect(usageStats["groq:p1"]?.failureCounts).toMatchObject({ overloaded: 1 });
578-expect(usageStats["openai:p1"]?.disabledUntil).toBeUndefined();
579-expect(usageStats["groq:p1"]?.disabledUntil).toBeUndefined();
580-581581expect(runEmbeddedAttemptMock).toHaveBeenCalledTimes(2);
582582expect(computeBackoffMock).not.toHaveBeenCalled();
583583expect(sleepWithAbortMock).not.toHaveBeenCalled();
@@ -641,7 +641,7 @@ describe("runWithModelFallback + runEmbeddedPiAgent failover behavior", () => {
641641642642const usageStats = await readUsageStats(agentDir);
643643expect(typeof usageStats["openai:p1"]?.cooldownUntil).toBe("number");
644-expect(usageStats["openai:p1"]?.failureCounts).toMatchObject({ overloaded: 2 });
644+expectFailureCount(usageStats, "openai:p1", "overloaded", 2);
645645expect(computeBackoffMock).not.toHaveBeenCalled();
646646expect(sleepWithAbortMock).not.toHaveBeenCalled();
647647});
@@ -680,8 +680,9 @@ describe("runWithModelFallback + runEmbeddedPiAgent failover behavior", () => {
680680throw new Error("aborted");
681681});
682682683-await expect(
684-runEmbeddedFallback({
683+let thrown: unknown;
684+try {
685+await runEmbeddedFallback({
685686 agentDir,
686687 workspaceDir,
687688sessionKey: "agent:test:overloaded-backoff-abort",
@@ -691,11 +692,14 @@ describe("runWithModelFallback + runEmbeddedPiAgent failover behavior", () => {
691692 ...makeConfig(),
692693auth: { cooldowns: { overloadedBackoffMs: 321 } },
693694},
694-}),
695-).rejects.toMatchObject({
696-name: "AbortError",
697-message: "Operation aborted",
698-});
695+});
696+} catch (error) {
697+thrown = error;
698+}
699+700+expect(thrown).toBeInstanceOf(Error);
701+expect((thrown as Error).name).toBe("AbortError");
702+expect((thrown as Error).message).toBe("Operation aborted");
699703700704expect(runEmbeddedAttemptMock).toHaveBeenCalledTimes(1);
701705const firstCall = runEmbeddedAttemptMock.mock.calls[0]?.[0] as
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。