feat(review): always show the OpenCode model in review output#7
Merged
JohnnyVicious merged 1 commit intomainfrom Apr 12, 2026
Merged
feat(review): always show the OpenCode model in review output#7JohnnyVicious merged 1 commit intomainfrom
JohnnyVicious merged 1 commit intomainfrom
Conversation
Previously the review output dropped you straight into the verdict
with no indication of which model produced it. With OpenCode's default
model resolved from `~/.config/opencode/opencode.json` or whatever
`/plugin install` defaulted to, it was impossible to tell from the
output whether `--model openrouter/foo` actually took effect or whether
you were silently getting the default.
OpenCode's API already returns the resolved model on every message:
POST /session/{id}/message ->
{ info: { model: { providerID, modelID }, ... }, parts: [...] }
This change extracts that and prepends a `**Model:** ...` header to the
rendered review output for both `/opencode:review` and
`/opencode:adversarial-review`. The header is intentionally outside
`renderReview` (the structured-JSON path) so it also shows up when the
review comes back as free-text and `tryParseJson` fails.
Implementation:
* `lib/render.mjs#extractResponseModel(response)` returns
`{ providerID, modelID }` or `null`. Defensive against missing
`info`, missing `model`, non-string fields, empty strings, and
null/undefined input.
* `lib/render.mjs#formatModelHeader(model)` returns the markdown
header (with trailing blank line so it concatenates cleanly), or
empty string when the model is unknown so callers can prepend
unconditionally.
* Both review handlers extract the model from the response and prepend
the header to whatever they were going to render. They also expose
the model on the returned `result` object for any future caller that
wants it.
* 12 new unit tests in `tests/render.test.mjs` covering both helpers:
well-formed input, missing/empty/non-string fields, null/undefined.
Test count: 62 -> 74. All passing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Surface the model OpenCode actually used at the top of every review. Previously the output dropped straight into the verdict with no indication of which model produced it, so passing
--model openrouter/foowas indistinguishable from using the default. Closes the visibility gap raised in conversation.How
OpenCode's API already returns the resolved model on every message:
(verified against a live opencode 1.4.3 server before writing the code)
This PR extracts that and prepends a header to the rendered review output:
The header is intentionally outside
renderReview's structured-JSON path so it also shows up when the review comes back as free-text andtryParseJsonfails.Changes
lib/render.mjs: new exportsextractResponseModel(response)— returns{providerID, modelID}ornull. Defensive against missinginfo, missingmodel, non-string fields, empty strings, null/undefined.formatModelHeader(model)— returns the markdown header with trailing blank line so it concatenates cleanly, or empty string when the model is unknown.opencode-companion.mjs(handleReview+handleAdversarialReview):extractResponseModelandformatModelHeadersendPrompt, extract the model and prepend the header torenderedresultobject for any future callertests/render.test.mjs: 12 new unit tests covering both helpers (well-formed input, missing/empty/non-string fields, null/undefined, trailing-blank-line invariant)Test plan
node --checkclean for both modified.mjsfilesOPENCODE_TEST_PORT=14096 npm test— 74 tests, 0 failures (was 62 → +12 new)/opencode:review --wait --model openrouter/anthropic/claude-haiku-4-5and verify output starts with**Model:** \openrouter/anthropic/claude-haiku-4-5``/opencode:review --wait(no--model) and verify the header still shows whatever default OpenCode picked