diff --git a/README.md b/README.md index da2fab2..03088d6 100644 --- a/README.md +++ b/README.md @@ -49,10 +49,10 @@ Choose between [OpenAI](https://developers.openai.com/) or [Anthropic](https://w | Provider | Default Model | Default PR Review Model | API Key | | --------- | ----------------- | ----------------------- | ------------------- | -| OpenAI | `gpt-5.6-luna` | `gpt-5.6-terra` | `openai_api_key` | +| OpenAI | `gpt-5.6-luna` | `gpt-5.6-luna` | `openai_api_key` | | Anthropic | `claude-sonnet-5` | `claude-opus-5` | `anthropic_api_key` | -The provider is auto-detected based on which API key you provide, and PR reviews default to a stronger model than the other AI features. Override with the `model` input, or use `review_model` to override PR review only. +The provider is auto-detected based on which API key you provide. Override with the `model` input, or use `review_model` to override PR review only. ### 🛠️ How It Works diff --git a/README.zh-CN.md b/README.zh-CN.md index 812c4f0..7ef5dab 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -49,10 +49,10 @@ | 提供商 | 默认模型 | 默认 PR Review 模型 | API Key | | --------- | ----------------- | ------------------- | ------------------- | -| OpenAI | `gpt-5.6-luna` | `gpt-5.6-terra` | `openai_api_key` | +| OpenAI | `gpt-5.6-luna` | `gpt-5.6-luna` | `openai_api_key` | | Anthropic | `claude-sonnet-5` | `claude-opus-5` | `anthropic_api_key` | -提供商会根据提供的 API key 自动检测,PR review 默认使用比其他 AI 功能更强的模型。可通过 `model` 输入覆盖默认模型,也可使用 `review_model` 仅覆盖 PR review 模型。 +提供商会根据提供的 API key 自动检测。可通过 `model` 输入覆盖默认模型,也可使用 `review_model` 仅覆盖 PR review 模型。 ### 🛠️ 工作方式 diff --git a/action.yml b/action.yml index 92cc730..85c3ab1 100644 --- a/action.yml +++ b/action.yml @@ -79,7 +79,7 @@ inputs: description: "AI Model - defaults to gpt-5.6-luna or claude-sonnet-5 based on API key" required: false review_model: - description: "AI Model for PR reviews (optional, defaults to gpt-5.6-terra or claude-opus-5 based on API key)" + description: "AI Model for PR reviews (optional, defaults to gpt-5.6-luna or claude-opus-5 based on API key)" required: false first_issue_response: description: "Example response to a new issue" diff --git a/actions/__init__.py b/actions/__init__.py index 37c36ca..b289f9a 100644 --- a/actions/__init__.py +++ b/actions/__init__.py @@ -28,4 +28,4 @@ # ├── test_summarize_pr.py # └── ... -__version__ = "0.2.45" +__version__ = "0.2.46" diff --git a/actions/review_pr.py b/actions/review_pr.py index 664bcfe..e7a79e6 100644 --- a/actions/review_pr.py +++ b/actions/review_pr.py @@ -546,7 +546,7 @@ def generate_pr_review( messages, text_format={"format": {"type": "json_schema", "name": "pr_review", "strict": True, "schema": schema}}, model=review_model, - reasoning_effort="medium", + reasoning_effort="high", tools=tools, tool_handlers=tool_handlers, max_turns=MAX_AGENT_TURNS, diff --git a/actions/utils/openai_utils.py b/actions/utils/openai_utils.py index 0f6183b..b4135c5 100644 --- a/actions/utils/openai_utils.py +++ b/actions/utils/openai_utils.py @@ -24,7 +24,7 @@ WEB_SEARCH_CALL_COST = 0.01 # $10 per 1K calls # Default models (single source of truth) OPENAI_MODEL_DEFAULT = "gpt-5.6-luna" ANTHROPIC_MODEL_DEFAULT = "claude-sonnet-5" -OPENAI_REVIEW_MODEL_DEFAULT = "gpt-5.6-terra" +OPENAI_REVIEW_MODEL_DEFAULT = "gpt-5.6-luna" ANTHROPIC_REVIEW_MODEL_DEFAULT = "claude-opus-5" MODEL_COSTS = { # (input, output) per 1M tokens @@ -38,8 +38,8 @@ MODEL_COSTS = { # (input, output) per 1M tokens "gpt-5.5": (5.00, 30.00), "gpt-5.4": (2.50, 15.00), "gpt-5.6-sol": (5.00, 30.00), - "gpt-5.6-terra": (2.50, 15.00), - "gpt-5.6-luna": (1.00, 6.00), + "gpt-5.6-terra": (2.00, 12.00), + "gpt-5.6-luna": (0.20, 1.20), "gpt-5-nano-2025-08-07": (0.05, 0.40), "gpt-5-mini-2025-08-07": (0.25, 2.00), # Anthropic Claude models @@ -431,7 +431,7 @@ def get_agent_response( "context_management": [{"type": "compaction", "compact_threshold": 200_000}], } if "gpt-5" in model: - base_data["reasoning"] = {"effort": reasoning_effort or "low"} + base_data["reasoning"] = {"effort": reasoning_effort or "medium"} if text_format: base_data["text"] = text_format @@ -578,7 +578,7 @@ def get_response( if background: data["background"] = True if "gpt-5" in model: - data["reasoning"] = {"effort": reasoning_effort or "low"} + data["reasoning"] = {"effort": reasoning_effort or "medium"} if text_format: data["text"] = text_format if tools: diff --git a/tests/test_first_interaction.py b/tests/test_first_interaction.py index cd43e8e..d985f5d 100644 --- a/tests/test_first_interaction.py +++ b/tests/test_first_interaction.py @@ -174,7 +174,7 @@ def test_generate_pr_review_uses_synchronous_response(mock_get_agent_response, m } assert kwargs["max_turns"] == review_pr.MAX_AGENT_TURNS assert kwargs["max_cost"] == review_pr.REVIEW_COST_SOFT_LIMIT - assert kwargs["reasoning_effort"] == "medium" + assert kwargs["reasoning_effort"] == "high" assert kwargs["request_timeout"] == (30, 120) assert "FULL FILE CONTENTS" not in mock_get_agent_response.call_args.args[0][1]["content"] assert ( diff --git a/tests/test_openai_utils.py b/tests/test_openai_utils.py index fd4ae8b..46dd15b 100644 --- a/tests/test_openai_utils.py +++ b/tests/test_openai_utils.py @@ -24,7 +24,7 @@ from actions.utils.openai_utils import ( def test_default_models(): """Test canonical default models are priced so max_cost budgets stay enforceable.""" assert OPENAI_MODEL_DEFAULT == "gpt-5.6-luna" - assert OPENAI_REVIEW_MODEL_DEFAULT == "gpt-5.6-terra" + assert OPENAI_REVIEW_MODEL_DEFAULT == "gpt-5.6-luna" assert ANTHROPIC_MODEL_DEFAULT == "claude-sonnet-5" assert ANTHROPIC_REVIEW_MODEL_DEFAULT == "claude-opus-5" for model in ( @@ -35,8 +35,8 @@ def test_default_models(): ): assert model in MODEL_COSTS # unpriced models disable max_cost budgets and misreport cost telemetry assert MODEL_COSTS["gpt-5.6-sol"] == (5.00, 30.00) - assert MODEL_COSTS["gpt-5.6-terra"] == (2.50, 15.00) - assert MODEL_COSTS["gpt-5.6-luna"] == (1.00, 6.00) + assert MODEL_COSTS["gpt-5.6-terra"] == (2.00, 12.00) + assert MODEL_COSTS["gpt-5.6-luna"] == (0.20, 1.20) def test_gpt_56_cost_includes_cache_write_and_long_context_rates(): @@ -52,8 +52,8 @@ def test_gpt_56_cost_includes_cache_write_and_long_context_rates(): expected = ((272001 - 200 * 0.9 + 300 * 0.25) * 5.00 * 2 + 100 * 30.00 * 1.5) / 1e6 assert _openai_usage_cost(usage, "gpt-5.6-sol") == expected turns = [{"input_tokens": 150000, "output_tokens": 0}] * 2 - assert sum(_openai_usage_cost(turn, "gpt-5.6-luna") for turn in turns) == 0.3 - assert _openai_usage_cost({"input_tokens": 300000, "output_tokens": 0}, "gpt-5.6-luna") == 0.6 + assert sum(_openai_usage_cost(turn, "gpt-5.6-luna") for turn in turns) == 0.06 + assert _openai_usage_cost({"input_tokens": 300000, "output_tokens": 0}, "gpt-5.6-luna") == 0.12 old_model_expected = ((1000 - 200 * 0.9) * 5.00 + 100 * 30.00) / 1e6 assert _openai_usage_cost({**usage, "input_tokens": 1000}, "gpt-5.5") == old_model_expected @@ -292,7 +292,7 @@ def test_get_agent_response_calls_function_tools(mock_post): first_payload = mock_post.call_args_list[0].kwargs["json"] assert first_payload["store"] is True assert first_payload["service_tier"] == "default" - assert first_payload["reasoning"] == {"effort": "low"} + assert first_payload["reasoning"] == {"effort": "medium"} assert first_payload["context_management"] == [{"type": "compaction", "compact_threshold": 200_000}] assert first_payload["prompt_cache_key"].startswith("agent-run:") assert "include" not in first_payload