mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 19:43:15 +00:00
* feat: upgrade default agent + reviewer model to Opus 4.8 Replace Opus 4.7 with Opus 4.8 (claude-opus-4-8) as the supported Anthropic model surfaced in the profile editor and used by the main agent and reviewer graphs. Effort levels (low/medium/high/xhigh/max) and the high default are unchanged, matching the official Opus 4.8 docs. Updates eval config comment and tests accordingly. * fix: provider-aware fallback for stale stored model ids Dropping claude-opus-4-7 from the supported set meant persisted profile/team-settings still holding it failed the SUPPORTED_MODEL_IDS check and fell through to default_model_pair() — a cross-provider jump to the OpenAI global default. Add provider_fallback_pair: when a stored id is no longer supported but its provider still has a supported model, resolve to that provider's newest supported model (anthropic:claude-opus-4-7 -> 4.8), preserving effort when valid. Resolution order is now: valid stored pair -> same-provider fallback -> global default_model_pair(). Profile overrides keep deferring to the team default when no model is set or the provider is unknown.
76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
"""Supported models and reasoning efforts surfaced in the profile editor."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TypedDict
|
|
|
|
|
|
class ModelOption(TypedDict):
|
|
id: str
|
|
label: str
|
|
efforts: list[str]
|
|
default_effort: str
|
|
|
|
|
|
SUPPORTED_MODELS: list[ModelOption] = [
|
|
{
|
|
"id": "anthropic:claude-opus-4-8",
|
|
"label": "Opus 4.8",
|
|
"efforts": ["low", "medium", "high", "xhigh", "max"],
|
|
"default_effort": "high",
|
|
},
|
|
{
|
|
"id": "openai:gpt-5.5",
|
|
"label": "GPT-5.5",
|
|
"efforts": ["low", "medium", "high", "xhigh"],
|
|
"default_effort": "xhigh",
|
|
},
|
|
]
|
|
|
|
SUPPORTED_MODEL_IDS: frozenset[str] = frozenset(m["id"] for m in SUPPORTED_MODELS)
|
|
|
|
DEFAULT_MODEL_ID: str = "openai:gpt-5.5"
|
|
DEFAULT_MODEL_EFFORT: str = "medium"
|
|
|
|
|
|
def model_supports_effort(model_id: str, effort: str) -> bool:
|
|
for m in SUPPORTED_MODELS:
|
|
if m["id"] == model_id:
|
|
return effort in m["efforts"]
|
|
return False
|
|
|
|
|
|
def _provider_of(model_id: str) -> str | None:
|
|
provider, _, rest = model_id.partition(":")
|
|
return provider if rest else None
|
|
|
|
|
|
def provider_fallback_pair(model_id: object, effort: object = None) -> tuple[str, str] | None:
|
|
"""Newest supported ``(model_id, effort)`` for the same provider as ``model_id``.
|
|
|
|
Keeps a stored selection on its original provider when its exact id has
|
|
dropped out of the supported set (e.g. an Opus minor-version bump), instead
|
|
of falling through to the cross-provider global default. Preserves ``effort``
|
|
when the fallback model supports it, otherwise uses that model's default
|
|
effort. Returns ``None`` when no supported model shares the provider.
|
|
"""
|
|
if not isinstance(model_id, str):
|
|
return None
|
|
provider = _provider_of(model_id)
|
|
if provider is None:
|
|
return None
|
|
for m in SUPPORTED_MODELS:
|
|
if _provider_of(m["id"]) == provider:
|
|
new_effort = effort if (isinstance(effort, str) and effort in m["efforts"]) else None
|
|
return m["id"], new_effort or m["default_effort"]
|
|
return None
|
|
|
|
|
|
def default_model_pair() -> tuple[str, str]:
|
|
"""Hardcoded fallback (model_id, reasoning_effort) used when no team default is set."""
|
|
if DEFAULT_MODEL_ID in SUPPORTED_MODEL_IDS and model_supports_effort(
|
|
DEFAULT_MODEL_ID, DEFAULT_MODEL_EFFORT
|
|
):
|
|
return DEFAULT_MODEL_ID, DEFAULT_MODEL_EFFORT
|
|
first = SUPPORTED_MODELS[0]
|
|
return first["id"], first["default_effort"]
|