Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 86 additions & 1 deletion .github/workflows/opencode-review-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3761,6 +3761,91 @@ jobs:
"context": 200000,
"output": 32000
}
},
"hy3-free": {
"name": "Hy3 Free",
"tool_call": true,
"reasoning": true,
"options": {
"reasoningEffort": "high"
},
"variants": {
"high": {
"reasoningEffort": "high"
}
},
"limit": {
"context": 190000,
"output": 64000
}
},
"minimax-m3-free": {
"name": "MiniMax-M3 Free",
"tool_call": true,
"reasoning": true,
"options": {
"reasoningEffort": "high"
},
"variants": {
"high": {
"reasoningEffort": "high"
}
},
"limit": {
"context": 200000,
"output": 32000
}
},
"glm-5-free": {
"name": "GLM-5 Free",
"tool_call": true,
"reasoning": true,
"options": {
"reasoningEffort": "high"
},
"variants": {
"high": {
"reasoningEffort": "high"
}
},
"limit": {
"context": 204800,
"output": 131072
}
},
"kimi-k2.5-free": {
"name": "Kimi K2.5 Free",
"tool_call": true,
"reasoning": true,
"options": {
"reasoningEffort": "high"
},
"variants": {
"high": {
"reasoningEffort": "high"
}
},
"limit": {
"context": 262144,
"output": 262144
}
},
"qwen3.6-plus-free": {
"name": "Qwen3.6 Plus Free",
"tool_call": true,
"reasoning": true,
"options": {
"reasoningEffort": "high"
},
"variants": {
"high": {
"reasoningEffort": "high"
}
},
"limit": {
"context": 262144,
"output": 65536
}
}
}
},
Expand Down Expand Up @@ -4222,7 +4307,7 @@ jobs:
# cost-efficient tier, cheaper than the legacy gpt-5 it replaced
# ($1/$6 vs $1.25/$10 per 1M tokens) so the org OpenAI budget
# stretches further between top-ups.
OPENCODE_MODEL_CANDIDATES: "${{ needs.validate-pr-metadata.outputs.is_private == 'false' && 'nvidia-nim/nvidia/llama-3.3-nemotron-super-49b-v1.5 nvidia-nim/nvidia/llama-3.1-nemotron-ultra-253b-v1 nvidia-nim/nvidia/nemotron-3-super-120b-a12b nvidia-nim/nvidia/nemotron-3-ultra-550b-a55b nvidia-nim/meta/llama-3.3-70b-instruct nvidia-nim/deepseek-ai/deepseek-v4-pro nvidia-nim/mistralai/codestral-22b-instruct-v0.1 opencode-free/nemotron-3-ultra-free opencode-free/deepseek-v4-flash-free opencode-free/north-mini-code-free opencode-free/laguna-s-2.1-free opencode-free/ling-3.0-flash-free opencode-free/big-pickle opencode-free/mimo-v2.5-free ' || '' }}opencode/gpt-5.6-terra github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/deepseek/deepseek-v3.2 openrouter/qwen/qwen3-coder github-models/openai/gpt-4.1 github-models/openai/gpt-5 github-models/openai/gpt-5-chat github-models/openai/o3 github-models/deepseek/deepseek-r1-0528 github-models/deepseek/deepseek-r1"
OPENCODE_MODEL_CANDIDATES: "${{ needs.validate-pr-metadata.outputs.is_private == 'false' && 'nvidia-nim/nvidia/llama-3.3-nemotron-super-49b-v1.5 nvidia-nim/nvidia/llama-3.1-nemotron-ultra-253b-v1 nvidia-nim/nvidia/nemotron-3-super-120b-a12b nvidia-nim/nvidia/nemotron-3-ultra-550b-a55b nvidia-nim/meta/llama-3.3-70b-instruct nvidia-nim/deepseek-ai/deepseek-v4-pro nvidia-nim/mistralai/codestral-22b-instruct-v0.1 opencode-free/nemotron-3-ultra-free opencode-free/deepseek-v4-flash-free opencode-free/north-mini-code-free opencode-free/laguna-s-2.1-free opencode-free/ling-3.0-flash-free opencode-free/big-pickle opencode-free/mimo-v2.5-free opencode-free/hy3-free opencode-free/minimax-m3-free opencode-free/glm-5-free opencode-free/kimi-k2.5-free opencode-free/qwen3.6-plus-free ' || '' }}opencode/gpt-5.6-terra github-models/deepseek/deepseek-v3-0324 openai/gpt-5.6-luna openrouter/deepseek/deepseek-v3.2 openrouter/qwen/qwen3-coder github-models/openai/gpt-4.1 github-models/openai/gpt-5 github-models/openai/gpt-5-chat github-models/openai/o3 github-models/deepseek/deepseek-r1-0528 github-models/deepseek/deepseek-r1"
# One attempt per model, then fall through to the next model. Retrying
# the SAME model 5x let a rate-limited/hung leader consume the whole
# step, so the pool never reached a healthy fallback model.
Expand Down
36 changes: 33 additions & 3 deletions tests/test_opencode_agent_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,12 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():
"opencode-free/laguna-s-2.1-free "
"opencode-free/ling-3.0-flash-free "
"opencode-free/big-pickle "
"opencode-free/mimo-v2.5-free ' || '' }}"
"opencode-free/mimo-v2.5-free "
"opencode-free/hy3-free "
"opencode-free/minimax-m3-free "
"opencode-free/glm-5-free "
"opencode-free/kimi-k2.5-free "
"opencode-free/qwen3.6-plus-free ' || '' }}"
)
candidates_text = candidates_match.group(1)
assert candidates_text.startswith(conditional_public_candidate)
Expand All @@ -124,6 +129,11 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():
"opencode-free/ling-3.0-flash-free",
"opencode-free/big-pickle",
"opencode-free/mimo-v2.5-free",
"opencode-free/hy3-free",
"opencode-free/minimax-m3-free",
"opencode-free/glm-5-free",
"opencode-free/kimi-k2.5-free",
"opencode-free/qwen3.6-plus-free",
*candidates_text.removeprefix(conditional_public_candidate).split(),
]
candidate_pairs = [candidate.split("/", 1) for candidate in candidates]
Expand Down Expand Up @@ -162,6 +172,11 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():
["opencode-free", "ling-3.0-flash-free"],
["opencode-free", "big-pickle"],
["opencode-free", "mimo-v2.5-free"],
["opencode-free", "hy3-free"],
["opencode-free", "minimax-m3-free"],
["opencode-free", "glm-5-free"],
["opencode-free", "kimi-k2.5-free"],
["opencode-free", "qwen3.6-plus-free"],
["opencode", "gpt-5.6-terra"],
["github-models", "deepseek/deepseek-v3-0324"],
["openai", "gpt-5.6-luna"],
Expand Down Expand Up @@ -240,6 +255,11 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():
"ling-3.0-flash-free",
"big-pickle",
"mimo-v2.5-free",
"hy3-free",
"minimax-m3-free",
"glm-5-free",
"kimi-k2.5-free",
"qwen3.6-plus-free",
}
assert set(paid_zen_models) == {"gpt-5.6-terra"}
terra_model = paid_zen_models["gpt-5.6-terra"]
Expand Down Expand Up @@ -276,6 +296,11 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():
"output": 32000,
}
for model_name, model_config in free_models.items():
# Every free-pool candidate must declare tool_call support: the reviewer
# drives CodeGraph/web-search tooling, so a non-tool_call model in the
# pool cannot produce a structured review and would burn its failover
# slot before yielding. Guard the whole pool, not just a hand-picked few.
assert model_config["tool_call"] is True, model_name
if model_config.get("reasoning") is True:
assert model_config["options"]["reasoningEffort"] == "high", model_name
assert model_config["variants"]["high"]["reasoningEffort"] == "high", (
Expand Down Expand Up @@ -469,7 +494,7 @@ def test_opencode_target_coverage_materializes_only_after_authorized_dispatch():
assert "id-token: write" not in coverage_job
assert "Report coverage source materialization failure" in coverage_job
assert (
"actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131"
"actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c"
in coverage_job
)

Expand Down Expand Up @@ -1519,7 +1544,12 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent():
"opencode-free/laguna-s-2.1-free "
"opencode-free/ling-3.0-flash-free "
"opencode-free/big-pickle "
"opencode-free/mimo-v2.5-free ' || ''"
"opencode-free/mimo-v2.5-free "
"opencode-free/hy3-free "
"opencode-free/minimax-m3-free "
"opencode-free/glm-5-free "
"opencode-free/kimi-k2.5-free "
"opencode-free/qwen3.6-plus-free ' || ''"
) in workflow
assert (
"opencode/gpt-5.6-terra "
Expand Down
Loading