Pular para conteúdo

AUR-605 — Provedor reserva (fallback)

Medido

  • llm.Orchestrator já percorria uma cadeia de provedores, mas todos os chamadores (review, perfis, qualidade da base, dependências, changelog) passavam a lista de reservas vazia (NewOrchestrator(p, nil, ...)).
  • Não havia variável, input nem secret para declarar uma reserva. Com o provedor fora do ar a revisão falhava fechada, sem plano B.
  • O limite de tempo do orquestrador era um só por requisição: uma cadeia cujo primeiro provedor esgotasse o limite nunca ouviria a reserva.

O que mudou

arquivo responsabilidade
internal/llm/fallback.go NewFallback (principal sozinho quando não há reserva), Fallback e ToolFallback (só membros que chamam ferramentas recebem rodada com ferramentas); FallbackNotice anuncia cada troca; erro final nomeia cada membro e responde a errors.Is(ErrAllProvidersFailed); TimeoutScaler/callTimeout: um limite por membro.
internal/llm/orchestrator.go, orchestrator_tools.go Limite de tempo por callTimeout(provider); erro de cadeia devolvido sem embrulho duplicado.
internal/llm/provider/profiles/fallback.go FallbacksFromEnv: slots LLM_FALLBACK_1..5_* resolvidos pelo catálogo, URL e chave do slot no lugar das do principal, inclusive as variáveis nativas de chave do perfil, modelo próprio; slot pela metade é erro com as variáveis do slot.
internal/llm/provider/profiles/resolve.go catalogFromEnv compartilhado entre principal e reservas.
cmd/aurumcode/provider_fallback.go withFallbacks monta a cadeia atrás do principal; slotProvider nomeia a reserva pelo slot; aviso no stderr redigido.
cmd/aurumcode/review_cache.go, review_base_quality.go Chave do cache acha a URL atrás da cadeia (llm.As); revisão respondida por reserva (FellBack) não é gravada.
cmd/aurumcode/main.go, profiles.go providerFromEnv usa withFallbacks; o perfil de revisão repassa o limite da cadeia.
.github/workflows/review.yml Inputs fallback_{1,2}_provider/_model, secrets opcionais LLM_FALLBACK_{1,2}_API_KEY/_BASE_URL, nos jobs de revisão e de dependências.
docs/provedores.md, docs/tutorials/provedores.md, demo/tutoriais/provedores Seção "Provedor reserva" e quatro casos executáveis com o provedor falso (rota fora-do-ar responde 503).

Provas

tests/acceptance/AUR-605.sh (cópia de go.mod go.sum cmd internal pkg):

id prova última linha
AC-001 TestAUR605PrimaryFailsFallbackAnswers, TestAUR605HealthyPrimaryAloneIsCalled, TestAUR605ProviderFromEnvFallsBackToTheSlot (servidores HTTP: principal 503, reserva responde com a própria chave; aviso no stderr) AUR-605/AC-001/pass
AC-002 TestAUR605AllFailNamesEveryProvider AUR-605/AC-002/pass
AC-003 TestAUR605NoFallbackIsThePrimaryItself, TestAUR605NoSlotNoFallback AUR-605/AC-003/pass
AC-004 TestAUR605ToolRoundsSkipMembersWithoutTools AUR-605/AC-004/pass
AC-005 TestAUR605ChainTimeoutLeavesTimeForTheFallback (limite de 1 s; principal falha em 0,8 s, reserva responde em 0,5 s) AUR-605/AC-005/pass
AC-006 TestAUR605SlotsResolveInOrderWithTheirOwnKey AUR-605/AC-006/pass
AC-007 TestAUR605UnusableSlotFailsNamingIt, TestAUR605UnusableSlotFailsTheSelection, TestAUR605NativeKeyNeverReachesASlot (OPENAI_API_KEY do ambiente nunca vira chave de reserva) AUR-605/AC-007/pass
AC-009 TestAUR605FallbackAnswerIsMarkedAndURLIsThePrimarys, TestAUR605CacheKeyKeepsThePrimaryURL (revisão respondida por reserva não é gravada no cache; llm.As[baseURLReporter] mantém a URL do principal na chave) AUR-605/AC-009/pass
AC-008 grep no workflow (inputs, secrets, -e) e nas docs (seção, variáveis, saídas do tutorial) AUR-605/AC-008/pass
MUT-001 CallTimeout devolve um limite só AUR-605/MUT-001/rejected (...ChainTimeout...)
MUT-002 slot lê LLM_API_KEY do principal AUR-605/MUT-002/rejected (...UnusableSlotFailsNamingIt)
MUT-003 troca sem aviso AUR-605/MUT-003/rejected (...PrimaryFailsFallbackAnswers)

Tutorial: bash demo/tutoriais/provedores/run.sh all grava os casos reserva-assume, duas-reservas, falha-todas-caem e falha-reserva-sem-chave; run.sh --check termina em CHECK OK.