diff --git a/.env.example b/.env.example index d90f8d07..e0d6daed 100644 --- a/.env.example +++ b/.env.example @@ -78,7 +78,7 @@ CEREBRAS_API_KEY= # Cerebras API key (cloud.cerebras.ai). Use with GOOGLE_API_KEY= # Google AI API key (aistudio.google.com). Use with model: google_genai:gemini-2.5-flash MAX_TOKENS=2048 # Max output tokens for OpenRouter requests (default: 2048) LANGGRAPH_RECURSION_LIMIT=500 # LangGraph/DeepAgents max ReAct steps per turn (lib default: 25; raised to 500 — PM fan-out to 6+ reports + synthesis routinely exceeds 100) -MODEL_PROVIDER=anthropic:claude-sonnet-4-6 # Format: provider:model. Providers: anthropic, openai, openrouter, groq, cerebras, google_genai, ollama +MODEL_PROVIDER=anthropic:claude-opus-4-7 # Format: provider:model. Providers: anthropic, openai, openrouter, groq, cerebras, google_genai, ollama # ---- Workspace tier resource limits (issue #14) ---- # Per-tier memory/CPU caps applied to each workspace Docker container. diff --git a/infra/litellm_config.yml b/infra/litellm_config.yml index 998daf3f..d14499dd 100644 --- a/infra/litellm_config.yml +++ b/infra/litellm_config.yml @@ -30,6 +30,11 @@ model_list: model: anthropic/claude-sonnet-4-6 api_key: ${ANTHROPIC_API_KEY} + - model_name: claude-opus-4-7 + litellm_params: + model: anthropic/claude-opus-4-7 + api_key: ${ANTHROPIC_API_KEY} + # ── OpenAI ───────────────────────────────────────────────────────────────── - model_name: gpt-4o litellm_params: diff --git a/platform/internal/handlers/org.go b/platform/internal/handlers/org.go index d74ab01f..7d2c54d0 100644 --- a/platform/internal/handlers/org.go +++ b/platform/internal/handlers/org.go @@ -338,7 +338,7 @@ func (h *OrgHandler) createWorkspaceTree(ws OrgWorkspace, parentID *string, defa if runtime == "claude-code" { model = "sonnet" } else { - model = "anthropic:claude-sonnet-4-6" + model = "anthropic:claude-opus-4-7" } } tier := ws.Tier diff --git a/platform/internal/handlers/org_test.go b/platform/internal/handlers/org_test.go index 556f1611..7af674b2 100644 --- a/platform/internal/handlers/org_test.go +++ b/platform/internal/handlers/org_test.go @@ -192,7 +192,7 @@ func TestOrgDefaults_Model_FallbackClaudeCode(t *testing.T) { if runtime == "claude-code" { model = "sonnet" } else { - model = "anthropic:claude-sonnet-4-6" + model = "anthropic:claude-opus-4-7" } } if model != "sonnet" { @@ -214,11 +214,11 @@ func TestOrgDefaults_Model_FallbackDeepAgents(t *testing.T) { if runtime == "claude-code" { model = "sonnet" } else { - model = "anthropic:claude-sonnet-4-6" + model = "anthropic:claude-opus-4-7" } } - if model != "anthropic:claude-sonnet-4-6" { - t.Errorf("deepagents with empty model should get 'anthropic:claude-sonnet-4-6', got %q", model) + if model != "anthropic:claude-opus-4-7" { + t.Errorf("deepagents with empty model should get 'anthropic:claude-opus-4-7', got %q", model) } } @@ -230,11 +230,11 @@ func TestOrgDefaults_Model_FallbackLangGraph(t *testing.T) { if runtime == "claude-code" { model = "sonnet" } else { - model = "anthropic:claude-sonnet-4-6" + model = "anthropic:claude-opus-4-7" } } - if model != "anthropic:claude-sonnet-4-6" { - t.Errorf("langgraph with empty model should get 'anthropic:claude-sonnet-4-6', got %q", model) + if model != "anthropic:claude-opus-4-7" { + t.Errorf("langgraph with empty model should get 'anthropic:claude-opus-4-7', got %q", model) } } diff --git a/platform/internal/handlers/workspace_provision.go b/platform/internal/handlers/workspace_provision.go index b7cea43d..b5d5ef97 100644 --- a/platform/internal/handlers/workspace_provision.go +++ b/platform/internal/handlers/workspace_provision.go @@ -417,7 +417,7 @@ func (h *WorkspaceHandler) ensureDefaultConfig(workspaceID string, payload model if runtime == "claude-code" { model = "sonnet" } else { - model = "anthropic:claude-sonnet-4-6" + model = "anthropic:claude-opus-4-7" } } diff --git a/platform/internal/handlers/workspace_provision_test.go b/platform/internal/handlers/workspace_provision_test.go index b9ef372f..3dafa96f 100644 --- a/platform/internal/handlers/workspace_provision_test.go +++ b/platform/internal/handlers/workspace_provision_test.go @@ -215,7 +215,7 @@ func TestEnsureDefaultConfig_LangGraph(t *testing.T) { if !contains(content, "tier: 1") { t.Errorf("config.yaml missing tier, got:\n%s", content) } - if !contains(content, `model: "anthropic:claude-sonnet-4-6"`) { + if !contains(content, `model: "anthropic:claude-opus-4-7"`) { t.Errorf("config.yaml should use default langgraph model, got:\n%s", content) } } @@ -354,7 +354,7 @@ func TestEnsureDefaultConfig_EmptyRuntimeDefaultsToLangGraph(t *testing.T) { if !contains(configYAML, "runtime: langgraph") { t.Errorf("empty runtime should default to langgraph, got:\n%s", configYAML) } - if !contains(configYAML, `model: "anthropic:claude-sonnet-4-6"`) { + if !contains(configYAML, `model: "anthropic:claude-opus-4-7"`) { t.Errorf("langgraph default model should be anthropic (quoted), got:\n%s", configYAML) } } diff --git a/workspace-template/config.py b/workspace-template/config.py index beeebb18..12408524 100644 --- a/workspace-template/config.py +++ b/workspace-template/config.py @@ -197,7 +197,7 @@ class WorkspaceConfig: description: str = "" version: str = "1.0.0" tier: int = 1 - model: str = "anthropic:claude-sonnet-4-6" + model: str = "anthropic:claude-opus-4-7" runtime: str = "langgraph" # langgraph | claude-code | codex | ollama | custom runtime_config: RuntimeConfig = field(default_factory=RuntimeConfig) initial_prompt: str = "" @@ -251,7 +251,7 @@ def load_config(config_path: Optional[str] = None) -> WorkspaceConfig: raw = yaml.safe_load(f) or {} # Override model from env if provided - model = os.environ.get("MODEL_PROVIDER", raw.get("model", "anthropic:claude-sonnet-4-6")) + model = os.environ.get("MODEL_PROVIDER", raw.get("model", "anthropic:claude-opus-4-7")) runtime = raw.get("runtime", "langgraph") runtime_raw = raw.get("runtime_config", {}) diff --git a/workspace-template/tests/test_config.py b/workspace-template/tests/test_config.py index fce8761e..786bc8b7 100644 --- a/workspace-template/tests/test_config.py +++ b/workspace-template/tests/test_config.py @@ -52,7 +52,7 @@ def test_load_config_defaults(tmp_path): assert cfg.description == "" assert cfg.version == "1.0.0" assert cfg.tier == 1 - assert cfg.model == "anthropic:claude-sonnet-4-6" + assert cfg.model == "anthropic:claude-opus-4-7" assert cfg.skills == [] assert cfg.tools == [] assert cfg.prompt_files == []