feat(opencode): provider cheapestinference global + presets de worktree

- Move o provider Cheapest Inference para a config global (~/.config/opencode/opencode.jsonc) sob o id correto `cheapestinference` (sem hífen), com variants low/high/max para deepseek-v4-flash e mimo-v2.5; remove o provider duplicado `cheapest-inference` do opencode.json do repo (só o MCP penpot permanece).
- OPENCODE_PRESET_MODEL (`scripts/lib/worktree.mjs`) agora usa `cheapestinference/deepseek-v4-flash`; variante default `max` persistida em ~/.local/state/opencode/model.json (o TUI não tem flag --variant).
- Atualiza a diretiva `launch opencode --model …` em AGENTS.md, .agents/shell/worktree.sh, skill worktree-next-issue e frontmatter dos comandos /work-issue e /plan-issue.
- Ajusta os guards de unidade: tests/unit/worktree.unit.spec.ts e tests/unit/opencodeCommands.unit.spec.ts para o novo preset (2445/2445 passando).
This commit is contained in:
Francisco Solla 2026-08-20 17:30:11 -03:00
parent be47027112
commit 4a9cdf08c8
10 changed files with 26 additions and 43 deletions

View file

@ -7,7 +7,7 @@
# shell que o chamou.
#
# No terminal (esta função), o script também imprime a diretiva `launch
# opencode <dir> --model deepseek/deepseek-v4-flash --auto [--prompt "…"]` (OPS26):
# opencode <dir> --model cheapestinference/deepseek-v4-flash --auto [--prompt "…"]` (OPS26):
# a função executa o cd e então a linha (tokenizada por xargs — honra as aspas
# do prompt, nunca eval), e o TUI do opencode abre no worktree — `next` com
# `/work-issue --issue <N>` já enviado (OPS33: a Issue claimada vai no prompt),

View file

@ -31,7 +31,7 @@ No opencode, isso é o comando **`/worktree next`** / **`/worktree kill`** (`.op
**Default-go:** `next`, `plan` e `new` imprimem `cd <dir>` na última linha **por padrão**; `--stay` suprime; `--go` explícito continua aceito como no-op. No terminal interativo, use a função `worktree()` de **`.agents/shell/worktree.sh`** (uma linha de `source` no profile) para o `cd` ser aplicado de verdade no shell que te chamou — node não consegue mudar o cwd do shell pai. `kill` também imprime `cd <main>` no fim (a sessão nunca fica num diretório destruído).
**Launch do opencode (OPS26 + OPS33 + OPS31):** só a função shell marca `TEQO_WORKTREE_TERMINAL=1`; com o marcador, `next`/`plan`/`new` imprimem também a diretiva `launch opencode <dir> --model deepseek/deepseek-v4-flash --auto [--prompt "/work-issue --issue <N>"]` **antes** do `cd`, e a função a executa depois do cd — `next` abre o TUI com `/work-issue --issue <N>` já enviado (a Issue claimada vai no prompt; a skill lê o resto do Forgejo); `plan` abre com `/plan-issue` já enviado (OPS31: o TUI já cai no fluxo de planejamento); `new` abre sem `--prompt` ("apenas conversar"). Sem `exec`: sair do opencode volta ao shell no worktree. Presets são constantes em `scripts/lib/worktree.mjs`. **O comando `/worktree` do opencode (e qualquer automação sem o marcador) nunca lança o TUI.**
**Launch do opencode (OPS26 + OPS33 + OPS31):** só a função shell marca `TEQO_WORKTREE_TERMINAL=1`; com o marcador, `next`/`plan`/`new` imprimem também a diretiva `launch opencode <dir> --model cheapestinference/deepseek-v4-flash --auto [--prompt "/work-issue --issue <N>"]` **antes** do `cd`, e a função a executa depois do cd — `next` abre o TUI com `/work-issue --issue <N>` já enviado (a Issue claimada vai no prompt; a skill lê o resto do Forgejo); `plan` abre com `/plan-issue` já enviado (OPS31: o TUI já cai no fluxo de planejamento); `new` abre sem `--prompt` ("apenas conversar"). Sem `exec`: sair do opencode volta ao shell no worktree. Presets são constantes em `scripts/lib/worktree.mjs`. **O comando `/worktree` do opencode (e qualquer automação sem o marcador) nunca lança o TUI.**
## Fluxo quando invocado como skill (agentes que não têm opencode)

View file

@ -1,6 +1,6 @@
---
description: Transforma ideias humanas em Issues GitHub + planos de intenção em docs/plans/ (com gate e registro)
model: deepseek/deepseek-v4-flash
model: cheapestinference/deepseek-v4-flash
---
Carregue a skill `plan-issue` (ferramenta de skills, nome exato) e siga o fluxo dela de ponta a ponta. A fonte canônica é `.agents/skills/plan-issue/SKILL.md` — não a transcreva nem recrie o fluxo.

View file

@ -1,6 +1,6 @@
---
description: Executa uma Issue já claimada de ponta a ponta com supervisão humana (plano de implementação → pausa → execução → simplify → débitos → PR)
model: deepseek/deepseek-v4-flash
model: cheapestinference/deepseek-v4-flash
---
Carregue a skill `work-issue` (ferramenta de skills, nome exato) e siga o fluxo dela de ponta a ponta. A fonte canônica é `.agents/skills/work-issue/SKILL.md` — não a transcreva nem recrie o fluxo.

File diff suppressed because one or more lines are too long

View file

@ -6,30 +6,5 @@
"url": "https://design.penpot.app/mcp/stream?userToken={file:.opencode/secrets/penpot-token}",
"enabled": true
}
},
"provider": {
"cheapest-inference": {
"npm": "@ai-sdk/openai-compatible",
"name": "Cheapest Inference",
"options": {
"baseURL": "https://api.cheapestinference.com/v1"
},
"models": {
"deepseek-v4-flash": {
"name": "DeepSeek V4 Flash",
"limit": {
"context": 1000000,
"output": 384000
}
},
"mimo-v2.5": {
"name": "MiMo v2.5",
"limit": {
"context": 1000000,
"output": 128000
}
}
}
}
}
}

View file

@ -19,8 +19,16 @@ export const PLAN_BRANCH_PREFIX = 'plans/plan-issue'
/** Env var the interactive-terminal `worktree()` function sets to request the opencode launch. */
export const WORKTREE_TERMINAL_ENV = 'TEQO_WORKTREE_TERMINAL'
/** Preset model for the opencode launch — change the preset by editing this constant. */
export const OPENCODE_PRESET_MODEL = 'deepseek/deepseek-v4-flash'
/**
* Preset model for the opencode launch — change the preset by editing this
* constant. Provider `cheapestinference` (Cheapest Inference, global config
* in ~/.config/opencode/opencode.jsonc; auth key via `opencode auth login
* cheapestinference`). The `max` variant is the default because opencode's
* TUI has no `--variant` flag — the per-model variant is persisted in
* ~/.local/state/opencode/model.json (`variant["cheapestinference/deepseek-v4-flash"]
* = "max"`), applied automatically when the TUI opens with this model.
*/
export const OPENCODE_PRESET_MODEL = 'cheapestinference/deepseek-v4-flash'
/**
* Skill command sent as the launch's initial message per purpose. `next`

View file

@ -24,7 +24,7 @@
* Chamado do terminal interativo (com
* `TEQO_WORKTREE_TERMINAL=1`, que só a função shell
* seta), imprime também a diretiva `launch
* opencode <dir> --model deepseek/deepseek-v4-flash
* opencode <dir> --model cheapestinference/deepseek-v4-flash
* --auto --prompt "/work-issue --issue <N>"` ANTES
* do `cd` — a função shell executa o cd e então a
* linha, e o TUI do opencode abre no worktree com
@ -775,7 +775,7 @@ if (!subcommand) {
console.log(' opencode command, ou a função `worktree()` de .agents/shell/worktree.sh);')
console.log(' no terminal (TEQO_WORKTREE_TERMINAL=1) imprime também a diretiva')
console.log(' `launch opencode … --prompt "/work-issue --issue <N>"` (OPS26+OPS33:')
console.log(' abre o TUI com deepseek/deepseek-v4-flash + auto + a Issue claimada já')
console.log(' abre o TUI com cheapestinference/deepseek-v4-flash + auto + a Issue claimada já')
console.log(' informada); --stay suprime cd e launch (o claim ainda acontece); --go')
console.log(' explícito continua aceito como no-op; --no-migrate pula migrations e o')
console.log(' seed mínimo (db:seed:minimal) nos bancos novos (OPS28: paridade com a CI)')

View file

@ -34,7 +34,7 @@ describe('opencode commands couple to their skill by exact name', () => {
/^description: .+$/m,
)
expect(frontmatter![1], 'frontmatter must pin the preference model').toMatch(
/^model: deepseek\/deepseek-v4-flash$/m,
/^model: cheapestinference\/deepseek-v4-flash$/m,
)
})
})

View file

@ -148,7 +148,7 @@ describe('opencodeLaunchDirective (terminal-only opencode launch, OPS26 + OPS33)
it('next launches with the preset model, --auto and the /work-issue command sent (value always quoted)', () => {
expect(opencodeLaunchDirective({ dir, purpose: 'next', terminal: true })).toBe(
`launch opencode ${dir} --model deepseek/deepseek-v4-flash --auto --prompt "/work-issue"`,
`launch opencode ${dir} --model cheapestinference/deepseek-v4-flash --auto --prompt "/work-issue"`,
)
})
@ -156,33 +156,33 @@ describe('opencodeLaunchDirective (terminal-only opencode launch, OPS26 + OPS33)
expect(
opencodeLaunchDirective({ dir, purpose: 'next', terminal: true, issueNumber: 595 }),
).toBe(
`launch opencode ${dir} --model deepseek/deepseek-v4-flash --auto --prompt "/work-issue --issue 595"`,
`launch opencode ${dir} --model cheapestinference/deepseek-v4-flash --auto --prompt "/work-issue --issue 595"`,
)
})
it('plan launches with the same presets and /plan-issue sent (OPS31, value quoted)', () => {
expect(opencodeLaunchDirective({ dir, purpose: 'plan', terminal: true })).toBe(
`launch opencode ${dir} --model deepseek/deepseek-v4-flash --auto --prompt "/plan-issue"`,
`launch opencode ${dir} --model cheapestinference/deepseek-v4-flash --auto --prompt "/plan-issue"`,
)
})
it('new launches prompt-less too — "apenas conversar", no skill sent', () => {
expect(opencodeLaunchDirective({ dir, purpose: 'new', terminal: true })).toBe(
`launch opencode ${dir} --model deepseek/deepseek-v4-flash --auto`,
`launch opencode ${dir} --model cheapestinference/deepseek-v4-flash --auto`,
)
})
it('plan/new ignore the issueNumber — only next carries the claimed issue', () => {
expect(opencodeLaunchDirective({ dir, purpose: 'plan', terminal: true, issueNumber: 7 })).toBe(
`launch opencode ${dir} --model deepseek/deepseek-v4-flash --auto --prompt "/plan-issue"`,
`launch opencode ${dir} --model cheapestinference/deepseek-v4-flash --auto --prompt "/plan-issue"`,
)
expect(opencodeLaunchDirective({ dir, purpose: 'new', terminal: true, issueNumber: 7 })).toBe(
`launch opencode ${dir} --model deepseek/deepseek-v4-flash --auto`,
`launch opencode ${dir} --model cheapestinference/deepseek-v4-flash --auto`,
)
})
it('pins the preset constants — changing the model is editing a constant', () => {
expect(OPENCODE_PRESET_MODEL).toBe('deepseek/deepseek-v4-flash')
expect(OPENCODE_PRESET_MODEL).toBe('cheapestinference/deepseek-v4-flash')
expect(WORKTREE_TERMINAL_ENV).toBe('TEQO_WORKTREE_TERMINAL')
expect(OPENCODE_SKILL_COMMAND_BY_PURPOSE).toEqual({
next: '/work-issue',
@ -193,7 +193,7 @@ describe('opencodeLaunchDirective (terminal-only opencode launch, OPS26 + OPS33)
it('an unknown purpose degrades to a prompt-less launch (fail-safe direction)', () => {
expect(opencodeLaunchDirective({ dir, purpose: 'bogus', terminal: true })).toBe(
`launch opencode ${dir} --model deepseek/deepseek-v4-flash --auto`,
`launch opencode ${dir} --model cheapestinference/deepseek-v4-flash --auto`,
)
})
})