Skip to content

feat: add free model resolution#21907

Open
caretak3r wants to merge 1 commit intoanomalyco:devfrom
caretak3r:feat/free-model-resolution
Open

feat: add free model resolution#21907
caretak3r wants to merge 1 commit intoanomalyco:devfrom
caretak3r:feat/free-model-resolution

Conversation

@caretak3r
Copy link
Copy Markdown

@caretak3r caretak3r commented Apr 10, 2026

Issue for this PR

Closes #21863

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds Provider.resolveSelection() which resolves --model free to a random free opencode-provider model. With --variant any, a random variant is chosen from that model's available variants (and falls through cleanly when the model has none).

Selection logic (packages/opencode/src/provider/provider.ts:1742-1780):

// Eligible iff providerID === opencode AND every cost field is zero
//   AND (id === "big-pickle" || id.endsWith("-free"))
isFree(model) && isListed(model)

The providerID === opencode gate excludes OpenRouter :free models. The isListed gate excludes any opencode-provider model that happens to have zero declared cost but isn't actually meant to be in the free pool (e.g. gpt-5-nano).

Integration points:

  • cli/cmd/run.ts — resolves before prompting / sending command
  • cli/cmd/tui/thread.ts — resolves before launching the TUI
  • cli/cmd/tui/app.tsx + context/args.tsx — store the resolved variant in local state

How did you verify your code works?

Workspace gates (run locally on this branch, all green):

Check Result
bun turbo typecheck 13/13 packages pass
bun test (the 3 affected files) 88 / 88 pass, 238 expectations
Pre-push husky hook (typecheck) passes

Named tests covering this feature

In packages/opencode/test/provider/provider.test.ts:

  • resolveModel picks only valid opencode free listings — proves the filter admits only (providerID = opencode) ∩ (cost = 0) ∩ (id = big-pickle | endsWith("-free")), and explicitly rejects gpt-5-nano and OpenRouter free-router.
  • resolveSelection picks a variant from the chosen free modelMath.random is mocked to land on a model with variants; the picked variant comes from that model's own variant set.
  • resolveSelection keeps explicit variants unchanged--variant max (literal) is preserved verbatim, not re-randomized.
  • resolveSelection falls back to no variant when the chosen free model has none — graceful degrade for models that have no variants.

In packages/opencode/test/cli/cmd/run.test.ts:

  • resolves free before prompting
  • passes the resolved model to command sessions
  • passes the resolved any variant to sessions

In packages/opencode/test/cli/tui/thread.test.ts:

  • resolves the free model alias before launching the tui
  • passes the resolved any variant before launching the tui

Negative cases verified--model free excludes:

  • OpenRouter :free / -free aliases (different providerID)
  • opencode/gpt-5-nano (zero cost but not in isListed whitelist)
  • Any model with non-zero cost.input, cost.output, cost.cache.read, cost.cache.write, or experimentalOver200K

Manual sanity — Explicit model passthrough (--model opencode/big-pickle) is unchanged because resolveSelection short-circuits when the model is not literally "free". --variant any without --model free is also short-circuited.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@caretak3r
Copy link
Copy Markdown
Author

@rekram1-node @adamdotdevin Anything for me to do here, looks like other changes were pushed here? Thank you!

@caretak3r caretak3r force-pushed the feat/free-model-resolution branch 2 times, most recently from bc990dd to 0e22efe Compare May 1, 2026 00:27
  Resolves --model free to a random free opencode model before
  prompting. Supports --variant any for random variant selection.

  Closes anomalyco#21863
@caretak3r caretak3r force-pushed the feat/free-model-resolution branch 2 times, most recently from 7a6e936 to ae63741 Compare May 2, 2026 00:20
@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels May 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 2, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

[FEATURE]: Allow --model free to randomly select free models

1 participant