diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bd4c0a1b..8aae0dc3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -104,6 +104,7 @@ - Telegram: send GIF media as animations (auto-play) and improve filename sniffing. - Bash tool: inherit gateway PATH so Nix-provided tools resolve during commands. Thanks @joshp123 for PR #202. - Delivery chunking: keep Markdown fenced code blocks valid when splitting long replies (close + reopen fences). +- Auth: prefer OAuth profiles over API keys during round-robin selection (prevents OAuth “lost after one message” when both are configured). ### Maintenance - Agent: add `skipBootstrap` config option. Thanks @onutc for PR #292. diff --git a/src/agents/auth-profiles.test.ts b/src/agents/auth-profiles.test.ts index 3b19dd8d5..f7fecba89 100644 --- a/src/agents/auth-profiles.test.ts +++ b/src/agents/auth-profiles.test.ts @@ -145,7 +145,7 @@ describe("resolveAuthProfileOrder", () => { }, provider: "anthropic", }); - expect(order).toEqual(["anthropic:b", "anthropic:a", "anthropic:c"]); + expect(order).toEqual(["anthropic:a", "anthropic:b", "anthropic:c"]); }); it("pushes cooldown profiles to the end, ordered by cooldown expiry", () => { diff --git a/src/agents/auth-profiles.ts b/src/agents/auth-profiles.ts index 8722de5e5..8b0b31866 100644 --- a/src/agents/auth-profiles.ts +++ b/src/agents/auth-profiles.ts @@ -500,7 +500,7 @@ function orderProfilesByMode( } // Sort available profiles by lastUsed (oldest first = round-robin) - // Then by type (oauth preferred over api_key) + // Then by lastUsed (oldest first = round-robin within type) const scored = available.map((profileId) => { const type = store.profiles[profileId]?.type; const typeScore = type === "oauth" ? 0 : type === "api_key" ? 1 : 2; @@ -508,14 +508,14 @@ function orderProfilesByMode( return { profileId, typeScore, lastUsed }; }); - // Primary sort: lastUsed (oldest first for round-robin) - // Secondary sort: type preference (oauth > api_key) + // Primary sort: type preference (oauth > api_key). + // Secondary sort: lastUsed (oldest first for round-robin within type). const sorted = scored .sort((a, b) => { - // First by lastUsed (oldest first) - if (a.lastUsed !== b.lastUsed) return a.lastUsed - b.lastUsed; - // Then by type - return a.typeScore - b.typeScore; + // First by type (oauth > api_key) + if (a.typeScore !== b.typeScore) return a.typeScore - b.typeScore; + // Then by lastUsed (oldest first) + return a.lastUsed - b.lastUsed; }) .map((entry) => entry.profileId);