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
20 changes: 14 additions & 6 deletions .github/workflows/opencode-review-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3361,6 +3361,14 @@ jobs:
"baseURL": "https://opencode.ai/zen/v1"
},
"models": {
"nemotron-3-ultra-free": {
"name": "Nemotron 3 Ultra Free",
"tool_call": true,
"limit": {
"context": 1000000,
"output": 128000
}
},
"deepseek-v4-flash-free": {
"name": "DeepSeek V4 Flash Free",
"tool_call": true,
Expand Down Expand Up @@ -3702,11 +3710,11 @@ jobs:
NPM_CONFIG_IGNORE_SCRIPTS: "true"
NO_COLOR: "1"
# High-sensitivity review candidates only. Public repositories first
# use OpenCode Zen's anonymous DeepSeek V4 Flash Free endpoint, then
# North Mini Code Free as fallback. During their free periods,
# DeepSeek data may be used for improvement and North data may be
# retained and used for improvement, so private repositories never
# include either candidate. The pool then falls through to
# use OpenCode Zen's anonymous Nemotron 3 Ultra, DeepSeek V4 Flash,
# and North Mini Code free endpoints. Their trial/free-period data
# may be logged, retained, or used for product/model improvement, so
# private repositories never include them. The pool then falls
# through to
# DeepSeek V3, the direct GPT-5.6 Luna slot, pinned PAID
# OpenRouter coder models (free-tier candidates hit the shared
# free-models-per-day cap and hung for the full candidate timeout,
Expand All @@ -3717,7 +3725,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' && 'opencode-free/deepseek-v4-flash-free opencode-free/north-mini-code-free ' || '' }}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' && 'opencode-free/nemotron-3-ultra-free opencode-free/deepseek-v4-flash-free opencode-free/north-mini-code-free ' || '' }}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
5 changes: 4 additions & 1 deletion scripts/ci/materialize_base_python_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@

def _is_candidate_lock_name(name: str) -> bool:
"""Return whether a file name is a possible pip requirements lock."""
return name == "requirements.lock" or fnmatch.fnmatch(name, "requirements*.txt")
return name == "requirements.lock" or (
fnmatch.fnmatch(name, "requirements*.txt")
and not fnmatch.fnmatch(name, "requirements-*-ci-hashes.txt")
)


def _requirement_lines(content: bytes) -> list[str]:
Expand Down
3 changes: 3 additions & 0 deletions tests/test_materialize_base_python_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def test_lock_name_candidates_are_pip_requirements_files() -> None:
assert materializer._is_candidate_lock_name("requirements.lock")
assert materializer._is_candidate_lock_name("requirements-dev.txt")
assert materializer._is_candidate_lock_name("requirements.txt")
assert not materializer._is_candidate_lock_name(
"requirements-opencode-review-ci-hashes.txt"
)
assert not materializer._is_candidate_lock_name("uv.lock")
assert not materializer._is_candidate_lock_name("pyproject.toml")

Expand Down
12 changes: 10 additions & 2 deletions tests/test_opencode_agent_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():
assert candidates_match is not None
conditional_public_candidate = (
"${{ needs.validate-pr-metadata.outputs.is_private == 'false' "
"&& 'opencode-free/deepseek-v4-flash-free "
"&& 'opencode-free/nemotron-3-ultra-free "
"opencode-free/deepseek-v4-flash-free "
"opencode-free/north-mini-code-free ' || '' }}"
)
candidates_text = candidates_match.group(1)
assert candidates_text.startswith(conditional_public_candidate)
candidates = [
"opencode-free/nemotron-3-ultra-free",
"opencode-free/deepseek-v4-flash-free",
"opencode-free/north-mini-code-free",
*candidates_text.removeprefix(conditional_public_candidate).split(),
Expand All @@ -117,6 +119,7 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():

assert candidate_pairs
assert candidate_pairs == [
["opencode-free", "nemotron-3-ultra-free"],
["opencode-free", "deepseek-v4-flash-free"],
["opencode-free", "north-mini-code-free"],
["github-models", "deepseek/deepseek-v3-0324"],
Expand Down Expand Up @@ -146,8 +149,12 @@ def test_opencode_model_pool_sets_high_effort_for_capable_candidates():
assert generated_config_match is not None
generated_config = json.loads(generated_config_match.group(1))
free_models = generated_config["provider"]["opencode-free"]["models"]
nemotron_model = free_models["nemotron-3-ultra-free"]
deepseek_model = free_models["deepseek-v4-flash-free"]
north_model = free_models["north-mini-code-free"]
assert nemotron_model["tool_call"] is True
assert nemotron_model["limit"] == {"context": 1000000, "output": 128000}
assert "response_format" not in nemotron_model.get("options", {})
assert deepseek_model["tool_call"] is True
assert "response_format" not in deepseek_model.get("options", {})
assert north_model["tool_call"] is True
Expand Down Expand Up @@ -1229,7 +1236,8 @@ def test_workflow_provisions_sandbox_tool_and_reviewer_agent():
)
assert (
"needs.validate-pr-metadata.outputs.is_private == 'false' && "
"'opencode-free/deepseek-v4-flash-free "
"'opencode-free/nemotron-3-ultra-free "
"opencode-free/deepseek-v4-flash-free "
"opencode-free/north-mini-code-free ' || ''"
) in workflow
assert (
Expand Down
Loading