9.8 KiB
Impl: Worktree launch default → LLM max via Vercel AI Gateway
Status: rascunho Atualizado em: 2026-08-23 Issue: #784 Intenção: docs/plans/worktree-launch-default-llm-max-gateway.md Appetite restante: ~0,5–1 dia (ajustado da intenção: mudança é config-only, sem migration, sem code além da constante)
Leitura da intenção
- Outcome: o default de launch do worktree opencode (
pnpm worktree next/plan/new) passa a rotear o DeepSeek pela rota do Vercel AI Gateway (vercel/deepseek/deepseek-v4-flash— cache/estabilidade/failover) em vez da rota direta atual (deepseek/deepseek-v4-flash), o provider fica exposto noopencode.jsondo repo e as variantes low/high/max ficam disponíveis — verificável pela linha de launch emitida pelo preset e pelos testes unitários atualizados. - O que NÃO negociar: anti-goals da intenção — NÃO mudar o cardápio de execução de Issues (
work-issue.md/plan-issue.mdnem o pin deopencodeCommands.unit.spec.ts); NÃO tocar no~/.config/opencode/opencode.jsoncglobal do humano; NÃO editar docs históricos (docs/plans,docs/CHANGELOG-AGENTS.md:208,212congelado). Fix de variantes é config-only emopencode.json— sem migration, sem code. - O que reavaliar: a hipótese de produto "a sessão abre com a variante max". Verificação ao vivo (opencode 1.18.21): o TUI (
opencode <dir> --model X --auto) não tem flag--variant(sóopencode runtem;--modelaceita estritamenteprovider/model, sem sufixo de variante). A variante não é forçável na linha de launch — ela é selecionável no TUI (keybind variant_cycle) e sticky por model key (~/.local/state/opencode/model.json), com fallback paramodel.request.variantdo catálogo. A intenção é atendida expondo as variantes no override + roteando o preset pelo gateway; a linha de launch é a verificação primária aceita.
Abordagem recomendada
flowchart LR
P["pnpm worktree next/plan/new"] --> L["scripts/lib/worktree.mjs\nOPENCODE_PRESET_MODEL = vercel/deepseek/deepseek-v4-flash"]
L --> D["opencodeLaunchDirective (scripts/lib/worktree.mjs:145)\nlinha de launch --model vercel/deepseek/deepseek-v4-flash"]
D --> T["TUI opencode"]
C["opencode.json\nprovider.vercel + variants low/high/max"] --> T
T -->|"max (sticky via model.json)"| G["Vercel AI Gateway\ncache / estabilidade / failover"]
Opções consideradas: A | B | C
Recomendação: B — mudar a constante single-source do preset para a rota do gateway (vercel/deepseek/deepseek-v4-flash) e expor as variantes low/high/max via override do model config no opencode.json do projeto (bloco provider.vercel.models["deepseek/deepseek-v4-flash"].variants, max com reasoningEffort: "max"). É a única opção que atende o outcome dentro das capacidades reais do TUI, preserva o cardápio de execução intacto, é verificável (linha de launch + testes unit) e cabe no appetite (config-only). O override foi validado ao vivo (opencode debug config mostra o override; opencode run --model vercel/deepseek/deepseek-v4-flash --variant max funciona).
Rejeitadas:
- A — agente default com
variant: max(model.agent/default): muda o comportamento de launch de todas as sessões do repo e força a variante por fora do TUI, arriscando o cardápio de execução de Issues (que pinamodel: deepseek/deepseek-v4-flashno frontmatter dos comandos) e o próprio modelo de descoberta no TUI. Rejeitada porque é mais intrusiva do que a intenção pede e fere o "config-only" (variante no default muda a experiência de todo mundo, não só o preset). - C — flag
--variantna linha de launch (--model ...:maxou--variant max): o TUI do opencode não suporta (tui.tssó expõe--model; formato estritamenteprovider/model). Verificado ao vivo (erro de servidor em:max). Rejeitada por impossibilidade técnica upstream.
Componentes / mudanças
OPENCODE_PRESET_MODEL(scripts/lib/worktree.mjs:28): valor →'vercel/deepseek/deepseek-v4-flash'; comentário:23-26atualizado para "preset → rota do Vercel AI Gateway". É a única fonte da string (OPS26); emitida emopencodeLaunchDirective(:145) — nenhum outro código lê/duplica o literal.opencode.json(:10-34): adicionar o providervercelao lado decheapest-inference(não substituir) com override do model config:
(variantes exatamente como no fix de variantes da intenção; o provider"vercel": { "models": { "deepseek/deepseek-v4-flash": { "variants": { "low": { "reasoningEffort": "low" }, "high": { "reasoningEffort": "high" }, "max": { "reasoningEffort": "max" } } } } }vercelé built-in/models.dev, credencial do gateway já no ambiente — sem npm/options adicionais.)tests/unit/worktree.unit.spec.ts(:151,159,165,171,177,180,185,196): atualizar os 8 literais da linha de launch paravercel/deepseek/deepseek-v4-flash;:185pina a constante (OPENCODE_PRESET_MODEL) — trocar o literal esperado. NÃO mexer emtests/unit/opencodeCommands.unit.spec.ts:36-38(pina o frontmatter dos comandos de execução — anti-goal).- Textos (string atualizada, sentido OPS26 preservado — "preset é constante em
scripts/lib/worktree.mjs"):scripts/worktree.mjs:27(docblock) e:778(help console.log).agents/shell/worktree.sh:10(comentário header).agents/skills/worktree-next-issue/SKILL.md:34(texto do skill)
- Migration: sem migration — config/tooling apenas; nenhum schema de Payload muda,
pnpm migrate/migrate:createnão se aplicam. - Access / Consent: N/A — não há collection nem dado de cidadão envolvido; não afeta login de campanha nem LGPD.
- UI: N/A — TUI do opencode é consumidor, não produto deste plano (nenhum componente Next/Payload do repo muda).
Dados → forma (se aplicável)
N/A — tooling. Não há dado de negócio sendo modelado: a mudança é uma constante de config + bloco de provider no opencode.json. (Perguntas de data-presentation não se aplicam.)
Fases verificáveis
- Constante + opencode.json + testes —
scripts/lib/worktree.mjs:23-28,opencode.json(blocoprovider.vercel),tests/unit/worktree.unit.spec.ts(8 literais + pin:185). Quota: maior parte do appetite. - Textos —
scripts/worktree.mjs:27,:778,.agents/shell/worktree.sh:10,.agents/skills/worktree-next-issue/SKILL.md:34. Quota: resto do appetite. - Gates —
pnpm test:unit(foco emtests/unit/worktree.unit.spec.ts, opcionalmente com-tno spec);pnpm gate:fast(lint + typecheck + test:unit); validação manual:opencode debug configmostra o providervercel+ variants do override, e um launch real de teste (pnpm worktree nextem branch descartável) emite--model vercel/deepseek/deepseek-v4-flashe responde; push viapnpm push→ CI PR (checks).
Rabbit holes / Não escopo (engenharia)
- NÃO mudar
.opencode/commands/work-issue.md:3/plan-issue.md:3(frontmattermodel: deepseek/deepseek-v4-flash) nem o pin detests/unit/opencodeCommands.unit.spec.ts:36-38— o cardápio de execução de Issues fica intacto (anti-goal). - NÃO forçar a variante via agente default (opção A rejeitada) — variante fica selecionável e sticky no TUI, não imposta.
- NÃO tocar no
~/.config/opencode/opencode.jsoncglobal do humano — o provider vive noopencode.jsondo repo. - NÃO editar
docs/CHANGELOG-AGENTS.md:208,212nem outros docs históricos (docs/plans, changelogs) — congelados. - NÃO criar provider duplicado/renomear
cheapest-inference—vercelentra ao lado. - Não inventar flag
--variantno launch do preset (TUI não suporta) nem sufixo:maxno--model(formato inválido).
Riscos e mitigação
- O TUI não força a variante na linha de launch (sem
--variant;--modelé estritamenteprovider/model) → a sessão pode abrir comrequest.variantdo catálogo (não o max). Mitigação: variantes low/high/max expostas pelo override e cicláveis no TUI com sticky persistente (~/.local/state/opencode/model.json); o aceite de produto foi ajustado — a linha de launch emitida pelo preset (--model vercel/deepseek/deepseek-v4-flash) é a verificação primária. - Override rejeitado pelo config loader do opencode (model config v1 não é setável via user config em todas as versões) → mitigação: validar
opencode debug config(mostra o override) eopencode run --model vercel/deepseek/deepseek-v4-flash --variant maxno PR, antes de marcar aprovado; documentar no plano se versões futuras mudarem o formato. - String duplicada em textos fora da constante → mitigação: os 4 pontos de texto são atualizados na mesma mudança (Fase 2) e os testes unit pínam a linha de launch, então qualquer deriva volta a aparecer na CI.
- Erro de digitação no valor da constante (rota do gateway) → mitigação: testes unit comparam a linha emitida com o literal esperado;
:185pina a própria constante.
Aceite de engenharia
- Aceite de produto da intenção coberto: preset emite
--model vercel/deepseek/deepseek-v4-flash; variantes low/high/max expostas noopencode.json(max comreasoningEffort: "max"); verificável pela linha de launch + testes unit atualizados. - Anti-goals preservados:
work-issue.md/plan-issue.mdeopencodeCommands.unit.spec.tsintactos;~/.config/opencode/opencode.jsoncintacto;docs/CHANGELOG-AGENTS.mde docs históricos intactos; config-only (sem migration, sem code além da constante). - Invariantes AGENTS/engineering-standards: constante single-source mantida (OPS26), provider adicionado ao lado (sem twinning), testes de domínio atualizados onde o literal muda.
pnpm test:unitverde (specworktree.unit.spec.ts) epnpm gate:fastverde;opencode debug configvalidado no PR.