Skip to content

feat(review): always show the OpenCode model in review output#7

Merged
JohnnyVicious merged 1 commit intomainfrom
feat/show-model-in-output
Apr 12, 2026
Merged

feat(review): always show the OpenCode model in review output#7
JohnnyVicious merged 1 commit intomainfrom
feat/show-model-in-output

Conversation

@JohnnyVicious
Copy link
Copy Markdown
Owner

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/foo was indistinguishable from using the default. Closes the visibility gap raised in conversation.

How

OpenCode's API already returns the resolved model on every message:

POST /session/{id}/message  ->
{
  "info": { "model": { "providerID": "openrouter", "modelID": "minimax/minimax-m2.5:free" }, ... },
  "parts": [...]
}

(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:

**Model:** `openrouter/minimax/minimax-m2.5:free`

## Review Verdict: PASS
…

The header is intentionally outside renderReview's structured-JSON path so it also shows up when the review comes back as free-text and tryParseJson fails.

Changes

  • lib/render.mjs: new exports

    • extractResponseModel(response) — returns {providerID, modelID} or null. Defensive against missing info, missing model, 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):

    • Import extractResponseModel and formatModelHeader
    • After sendPrompt, extract the model and prepend the header to rendered
    • Also expose the model on the returned result object for any future caller
  • tests/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 --check clean for both modified .mjs files
  • OPENCODE_TEST_PORT=14096 npm test74 tests, 0 failures (was 62 → +12 new)
  • Manual: /opencode:review --wait --model openrouter/anthropic/claude-haiku-4-5 and verify output starts with **Model:** \openrouter/anthropic/claude-haiku-4-5``
  • Manual: /opencode:review --wait (no --model) and verify the header still shows whatever default OpenCode picked

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.
@JohnnyVicious JohnnyVicious merged commit 15d9278 into main Apr 12, 2026
1 check passed
@JohnnyVicious JohnnyVicious deleted the feat/show-model-in-output branch April 12, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant