Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions src/__tests__/debate-engine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,32 +407,30 @@ describe("resolveProviderContent", () => {
expect(result).toBe("Option A is the better choice.")
})

it("substitutes EN snack-break fallback when server flags empty", () => {
it("substitutes EN empty-response fallback when server flags empty", () => {
const result = resolveProviderContent("", true, "en", "gemini")
expect(result).toBe("Gemini stepped out for a snack break. Back soon.")
expect(result).toBe("Gemini couldn't reply this round.")
})

it("substitutes KO snack-break fallback when server flags empty", () => {
it("substitutes KO empty-response fallback when server flags empty", () => {
const result = resolveProviderContent("", true, "ko", "gemini")
expect(result).toBe("Gemini 잠깐 간식 먹으러 갔어요. 곧 돌아올게요.")
expect(result).toBe("Gemini가 이번 라운드에 답하지 못했어요.")
})

it("substitutes fallback when raw content is whitespace only", () => {
const result = resolveProviderContent(" \n\t ", false, "en", "claude")
expect(result).toBe("Claude stepped out for a snack break. Back soon.")
expect(result).toBe("Claude couldn't reply this round.")
})

it("substitutes fallback when cleanResponse strips content to nothing", () => {
// cleanResponse removes citation markers and horizontal rules; if that's
// all the model returned we should still surface the fallback.
const result = resolveProviderContent("[1][2][3]", false, "en", "perplexity")
expect(result).toBe("Perplexity stepped out for a snack break. Back soon.")
expect(result).toBe("Perplexity couldn't reply this round.")
})

it("uses provider display name in the fallback", () => {
expect(resolveProviderContent("", true, "en", "gpt")).toBe(
"GPT stepped out for a snack break. Back soon."
)
expect(resolveProviderContent("", true, "en", "gpt")).toBe("GPT couldn't reply this round.")
})

it("does not call fallback when content has any real text", () => {
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useDebateEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export const SYSTEM_MESSAGES = {
: "The AI hit a temporary rate limit. Wait a few seconds and send again.",
emptyResponse: (locale: Locale, provider: Provider) =>
locale === "ko"
? `${DISPLAY_NAMES[provider]} 잠깐 간식 먹으러 갔어요. 곧 돌아올게요.`
: `${DISPLAY_NAMES[provider]} stepped out for a snack break. Back soon.`,
? `${DISPLAY_NAMES[provider]}가 이번 라운드에 답하지 못했어요.`
: `${DISPLAY_NAMES[provider]} couldn't reply this round.`,
missingApiKey: (locale: Locale, provider: Provider) => getMissingApiKeyMessage(provider, locale),
missingConsensusKey: (locale: Locale) =>
locale === "ko"
Expand Down Expand Up @@ -485,7 +485,7 @@ export function useDebateEngine(config: {
updatePlaceholder(msg)
return null
}
// Covers transport errors and the route's {error} channel. Raw upstream errors are unactionable in a bubble - show the snack-break fallback and keep detail in logDebate (console.error would pop the dev overlay on a handled rejection).
// Covers transport errors and the route's {error} channel. Raw upstream errors are unactionable in a bubble - show a short fallback and keep detail in logDebate.
const errorMsg = err instanceof Error ? err.message : "Unknown error"
logDebate("callModel:error", { provider, error: errorMsg })
clearTypingIfCurrentSession()
Expand Down
Loading