Skip to content

feat: 分页获取分支 & 修复分支选择器宽度 & 修复 payload 解析失败 & 修复 Opus 4.8 兼容性#26

Open
Bluestar-coder wants to merge 4 commits into
larlarua:mainfrom
Bluestar-coder:main
Open

feat: 分页获取分支 & 修复分支选择器宽度 & 修复 payload 解析失败 & 修复 Opus 4.8 兼容性#26
Bluestar-coder wants to merge 4 commits into
larlarua:mainfrom
Bluestar-coder:main

Conversation

@Bluestar-coder

@Bluestar-coder Bluestar-coder commented Jul 9, 2026

Copy link
Copy Markdown

变更说明

✨ 功能改进

GitHub 分支列表支持分页获取backend/app/services/scanner.py

原实现仅请求一页(最多 100 条),对于分支数量超过 100 的大型仓库会导致分支列表不完整。现改为循环分页拉取,直到获取全部分支后返回,解决分支丢失问题。

🐛 Bug 修复

分支选择器下拉框宽度异常frontend/src/components/ui/branch-selector.tsx

原来使用 w-[--radix-popover-trigger-width] 会导致下拉框宽度随触发按钮宽度变化而过窄,改为 min-w-[280px] max-w-[400px],保证分支名称完整展示。

运行时会话未返回可解析 payload 时任务崩溃

LLM 未调用终止工具(如 FinalizeTriageBatch)时,_ensure_payload() 因缺少兜底逻辑直接抛出错误,导致任务失败:

Runtime session ended without a machine-parseable payload for the requested continuation.

修复涉及三处:

  • backend/app/services/agent_runtime/specs.py:新增 _triage_fallback_payloadbuild_triage_runtime_spec()fallback_payload_builderNone 改为该函数
  • backend/app/api/v1/endpoints/agent_tasks.pycontinue_session_until_report_payload 调用补充 fallback_payload_builder=lambda _: None
  • backend/app/services/finding_runtime/bridge.py:删除 _default_finalizer_prompts() 中永远不可达的死代码块

Opus 4.8 不支持 temperature 参数及 assistant prefill(fix issue #22

  • backend/app/services/llm/factory.py:Claude 模型支持列表新增 claude-opus-4-8
  • backend/app/services/llm/adapters/anthropic_adapter.py:新增 _is_thinking_model(),对 extended thinking 模型(opus-4-8、claude-3-7-sonnet)自动跳过 temperature 参数并移除末尾 assistant 消息(prefill 不兼容)
  • backend/app/services/llm/adapters/litellm_adapter.py:同类模型跳过 temperature 传递

🔧 依赖更新

  • httpx 升级为 httpx[socks],支持通过 SOCKS 代理访问 GitHub API

⚙️ 本地开发配置

  • docker-compose.override.yml 改为高端口映射方案,避免与本机服务端口冲突

测试说明

  • 分支数量 > 100 的仓库可正确获取全部分支
  • 分支选择器下拉框在各分支名称长度下展示正常
  • triage 任务在 LLM 未调用 FinalizeTriageBatch 时不再崩溃
  • 使用 claude-opus-4-8 模型时不再报 temperature 参数错误
  • 使用 extended thinking 模型时不再报 assistant prefill 不支持错误

Summary by CodeRabbit

  • New Features
    • Branch lists now load completely, even when there are more than 100 branches.
    • Added support for an additional Claude model option.
  • Bug Fixes
    • Improved AI request handling for certain models to avoid incompatible settings.
    • Finalization and triage flows are now more resilient when output is incomplete.
    • Enabled the code-security finding binding to improve security coverage.
  • Chores
    • Updated local development port mappings to reduce conflicts.
    • Adjusted the branch selector dropdown width for better display.

- scanner.py: fetch all branches with pagination (was capped at 100)
- branch-selector.tsx: use min/max-width instead of trigger-width for dropdown
- pyproject.toml / requirements-lock.txt: dependency updates
- docker-compose.override.yml: local dev config adjustments
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 129e7d5f-a302-42c6-bc23-196930dca0e7

📥 Commits

Reviewing files that changed from the base of the PR and between 51509af and 5bae89e.

📒 Files selected for processing (1)
  • backend/app/services/finding_runtime/bridge.py

Walkthrough

GitHub branch listing now paginates through all pages, backend runtime fallback handling and finalizer behavior changed, LLM adapters special-case extended-thinking models, compose ports were remapped, the branch selector width changed, and code-security binding entries were enabled.

Changes

GitHub Branch Pagination and SOCKS Proxy Support

Layer / File(s) Summary
Paginated branch fetching and SOCKS dependency
backend/app/services/scanner.py, backend/pyproject.toml, backend/requirements-lock.txt
get_github_branches now paginates through GitHub branch pages and accumulates results; httpx gains the socks extra and socksio is pinned in the lockfile.

Backend Runtime Fallback and Prompt Changes

Layer / File(s) Summary
Triage fallback payload spec
backend/app/services/agent_runtime/specs.py
build_triage_runtime_spec() now uses a fallback payload builder that returns a triage-incomplete retry payload.
Report continuation fallback wiring
backend/app/api/v1/endpoints/agent_tasks.py
continue_session_until_report_payload(...) now receives a fallback payload builder that returns None.
Auto-finalizer prompt text
backend/app/services/finding_runtime/bridge.py
The default finalizer prompt now instructs the model to continue tool-based verification instead of ending immediately with a strict JSON-only response, and the finalizer gate now allows INCOMPLETE completion mode.

LLM Adapter Thinking-Model Handling

Layer / File(s) Summary
Anthropic payload adjustments
backend/app/services/llm/adapters/anthropic_adapter.py
Anthropic payload building now detects thinking models, strips trailing assistant prefill messages, and omits temperature for those models.
LiteLLM model handling
backend/app/services/llm/adapters/litellm_adapter.py, backend/app/services/llm/factory.py
LiteLLM skips temperature for specific Claude thinking models, and the available Claude model list adds claude-opus-4-8.

Docker Compose Port Overrides

Layer / File(s) Summary
Port override configuration
docker-compose.override.yml
Comments update the override usage note; host ports are remapped for db, redis, backend, and frontend; adminer is reduced to a ports-only override.

Branch Selector Popover Width

Layer / File(s) Summary
Popover width classes
frontend/src/components/ui/branch-selector.tsx
PopoverContent now uses min-w-[280px] and max-w-[400px] instead of trigger-width sizing.

Skill Library Binding Updates

Layer / File(s) Summary
Enable code-security finding binding and timestamps
skill_library/agents/finding/bindings.json, skill_library/code-security/bindings.json, skill_library/.runtime/installed_skills.json
enabled is set to true for code-security / finding:code-security, and updated_at timestamps are refreshed for several skills in the runtime registry.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Poem

I’m a rabbit with a twitchy nose,
I sniffed out pages, ports, and those
Fine model tweaks that dodge the heat,
And skills that finally stood on feet.
Hop-hop—this patch feels tidy, clear, and neat 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main branch pagination, UI width, payload fallback, and Opus 4.8 compatibility changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app/services/scanner.py`:
- Around line 181-193: The pagination loop in scanner.py can run without a hard
stop, so add a defensive maximum page cap to the branch-fetching logic in the
branch scanning function that contains the current while True loop. Update the
loop condition or add an explicit break using a max page constant before calling
github_api, and keep the existing per_page/len(branches_data) termination checks
so pagination still stops normally when fewer items are returned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78f91323-9b60-4dba-a323-d529372d892c

📥 Commits

Reviewing files that changed from the base of the PR and between 97ce141 and 5265c3f.

📒 Files selected for processing (8)
  • backend/app/services/scanner.py
  • backend/pyproject.toml
  • backend/requirements-lock.txt
  • docker-compose.override.yml
  • frontend/src/components/ui/branch-selector.tsx
  • skill_library/.runtime/installed_skills.json
  • skill_library/agents/finding/bindings.json
  • skill_library/code-security/bindings.json

Comment on lines +181 to +193
while True:
branches_url = f"https://api.github.com/repos/{owner}/{repo}/branches?per_page={per_page}&page={page}"
branches_data = await github_api(branches_url, token)

if not branches_data:
break

all_branches.extend([b["name"] for b in branches_data])

if len(branches_data) < per_page:
break

page += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add a safety cap on the number of pages fetched.

The pagination loop has no upper bound on the number of pages. If a repository has an extremely large number of branches, or if the GitHub API returns exactly per_page items on every page due to a quirk, the loop will continue making API calls indefinitely or until the rate limit is exhausted. GitHub's API itself caps at 30 pages for most endpoints, but the code should enforce its own limit as a defensive measure.

🔒️ Proposed fix: add a max page limit
     all_branches = []
     page = 1
     per_page = 100
+    max_pages = 30  # GitHub API caps at 30 pages (3000 branches)

-    while True:
+    while page <= max_pages:
         branches_url = f"https://api.github.com/repos/{owner}/{repo}/branches?per_page={per_page}&page={page}"
         branches_data = await github_api(branches_url, token)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
while True:
branches_url = f"https://api.github.com/repos/{owner}/{repo}/branches?per_page={per_page}&page={page}"
branches_data = await github_api(branches_url, token)
if not branches_data:
break
all_branches.extend([b["name"] for b in branches_data])
if len(branches_data) < per_page:
break
page += 1
all_branches = []
page = 1
per_page = 100
max_pages = 30 # GitHub API caps at 30 pages (3000 branches)
while page <= max_pages:
branches_url = f"https://api.github.com/repos/{owner}/{repo}/branches?per_page={per_page}&page={page}"
branches_data = await github_api(branches_url, token)
if not branches_data:
break
all_branches.extend([b["name"] for b in branches_data])
if len(branches_data) < per_page:
break
page += 1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/scanner.py` around lines 181 - 193, The pagination loop
in scanner.py can run without a hard stop, so add a defensive maximum page cap
to the branch-fetching logic in the branch scanning function that contains the
current while True loop. Update the loop condition or add an explicit break
using a max page constant before calling github_api, and keep the existing
per_page/len(branches_data) termination checks so pagination still stops
normally when fewer items are returned.

- agent_runtime/specs.py:为 build_triage_runtime_spec 添加
  _triage_fallback_payload,LLM 未调用 FinalizeTriageBatch 时
  不再抛 ValueError,改为返回标记 requires_retry=True 的不完整 payload

- agent_tasks.py:continue_session_until_report_payload 调用补充
  fallback_payload_builder=lambda _: None,报告生成失败时替换为
  更清晰的 'did not return a report bundle' 错误

- finding_runtime/bridge.py:删除 _default_finalizer_prompts 中
  第一个 return 后永远不可达的死代码块

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app/services/agent_runtime/specs.py`:
- Around line 57-64: The fallback payload in _triage_fallback_payload is
hardcoding runtime_completion_mode as the uppercase string, but downstream logic
expects the enum value format. Update this function to use
RuntimeCompletionMode.INCOMPLETE.value instead of the raw string so the payload
matches the lowercase completion mode used elsewhere and is recognized
consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fc56f10b-aad4-4a91-9f88-557e1af1eb9f

📥 Commits

Reviewing files that changed from the base of the PR and between 5265c3f and 4dec116.

📒 Files selected for processing (3)
  • backend/app/api/v1/endpoints/agent_tasks.py
  • backend/app/services/agent_runtime/specs.py
  • backend/app/services/finding_runtime/bridge.py
💤 Files with no reviewable changes (1)
  • backend/app/services/finding_runtime/bridge.py

Comment on lines +57 to +64
def _triage_fallback_payload(snapshot: Any) -> dict[str, Any]:
return {
"findings": [],
"summary": "Triage batch did not complete - FinalizeTriageBatch was not called.",
"runtime_completion_mode": "INCOMPLETE",
"is_partial": True,
"requires_retry": True,
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify RuntimeCompletionMode enum value and is_partial usage in triage context
rg -nC3 'RuntimeCompletionMode' backend/app/services/agent_runtime/specs.py
rg -nC3 'is_partial' backend/app/services/ --type=python
rg -nC3 'is_final' backend/app/services/ --type=python
rg -nC3 'class RuntimeCompletionMode' backend/

Repository: larlarua/AutoCVE

Length of output: 760


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## specs.py relevant slice\n'
nl -ba backend/app/services/agent_runtime/specs.py | sed -n '1,140p'

printf '\n## bridge.py relevant slice\n'
nl -ba backend/app/services/finding_runtime/bridge.py | sed -n '1,220p'

printf '\n## search for is_partial / is_final in backend/app/services\n'
rg -nC2 'is_partial|is_final' backend/app/services -g '*.py'

printf '\n## RuntimeCompletionMode definition and uses\n'
rg -nC2 'class RuntimeCompletionMode|RuntimeCompletionMode\.' backend/app/services -g '*.py'

Repository: larlarua/AutoCVE

Length of output: 222


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## specs.py relevant slice\n'
sed -n '1,160p' backend/app/services/agent_runtime/specs.py

printf '\n## bridge.py relevant slice\n'
sed -n '1,260p' backend/app/services/finding_runtime/bridge.py

printf '\n## search for is_partial / is_final in backend/app/services\n'
grep -RInE --include='*.py' 'is_partial|is_final' backend/app/services || true

printf '\n## RuntimeCompletionMode definition and uses\n'
grep -RInE --include='*.py' 'class RuntimeCompletionMode|RuntimeCompletionMode\.' backend/app/services || true

Repository: larlarua/AutoCVE

Length of output: 19385


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## RuntimeCompletionMode definition\n'
sed -n '1,120p' backend/app/services/finding_runtime/models.py

printf '\n## finding_runtime/bridge.py around fallback payload\n'
sed -n '940,990p' backend/app/services/finding_runtime/bridge.py

printf '\n## search for triage payload/schema and is_partial across repo\n'
grep -RInE --include='*.py' 'is_partial|triage.*payload|FinalizeTriageBatch|runtime_completion_mode' backend | sed -n '1,220p'

printf '\n## agent_runtime usage of fallback builder\n'
grep -RInE --include='*.py' 'fallback_payload_builder|_triage_fallback_payload|build_triage_runtime_spec' backend/app/services | sed -n '1,200p'

Repository: larlarua/AutoCVE

Length of output: 17949


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## agent_tasks.py runtime_completion_mode handling\n'
sed -n '360,430p' backend/app/api/v1/endpoints/agent_tasks.py

printf '\n## any lowercase/uppercase incomplete comparisons in backend/app/services and backend/app/api\n'
grep -RInE --include='*.py' 'runtime_completion_mode[^\n]*incomplete|== "incomplete"|== "INCOMPLETE"|RuntimeCompletionMode\.INCOMPLETE' backend/app backend/tests | sed -n '1,240p'

Repository: larlarua/AutoCVE

Length of output: 5575


Use RuntimeCompletionMode.INCOMPLETE.value here
runtime_completion_mode is consumed as lowercase "incomplete" elsewhere, so the raw "INCOMPLETE" string will not match downstream checks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/agent_runtime/specs.py` around lines 57 - 64, The
fallback payload in _triage_fallback_payload is hardcoding
runtime_completion_mode as the uppercase string, but downstream logic expects
the enum value format. Update this function to use
RuntimeCompletionMode.INCOMPLETE.value instead of the raw string so the payload
matches the lowercase completion mode used elsewhere and is recognized
consistently.

@Bluestar-coder Bluestar-coder changed the title feat: GitHub 分支列表支持分页 & 修复分支选择器下拉宽度 feat: GitHub 分支列表支持分页 & 修复分支选择器下拉宽度 & 修复运行时 payload 解析失败崩溃 Jul 9, 2026
- factory.py:Claude 模型支持列表新增 claude-opus-4-8

- anthropic_adapter.py:
  新增 _is_thinking_model() 辅助函数(匹配 opus-4-8 / claude-3-7-sonnet)
  _build_payload 对 extended thinking 模型跳过 temperature 参数
  _build_payload 对 extended thinking 模型自动移除末尾 assistant 消息(prefill 不支持)

- litellm_adapter.py:
  内联 extended thinking 模型检测,跳过 temperature 参数传递

修复 issue larlarua#22
@Bluestar-coder Bluestar-coder changed the title feat: GitHub 分支列表支持分页 & 修复分支选择器下拉宽度 & 修复运行时 payload 解析失败崩溃 feat: 分页获取分支 & 修复分支选择器宽度 & 修复 payload 解析失败 & 修复 Opus 4.8 兼容性 Jul 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
backend/app/services/llm/adapters/anthropic_adapter.py (2)

207-218: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Cache the _is_thinking_model result to avoid redundant calls.

_is_thinking_model(self.config.model) is invoked twice with the same argument on lines 208 and 218. Compute once and reuse.

♻️ Suggested refactor
     def _build_payload(self, request: LLMRequest, *, stream: bool) -> dict[str, Any]:
         messages, system = self._normalize_messages([msg.to_dict() for msg in request.messages])
-        # Extended thinking models do not support assistant prefill (trailing assistant message)
-        if messages and messages[-1]["role"] == "assistant" and _is_thinking_model(self.config.model):
+        thinking = _is_thinking_model(self.config.model)
+        # Extended thinking models do not support assistant prefill (trailing assistant message)
+        if thinking and messages and messages[-1]["role"] == "assistant":
             messages = messages[:-1]
         payload: dict[str, Any] = {
             "model": self.config.model,
             "messages": messages,
             "max_tokens": request.max_tokens if request.max_tokens is not None else self.config.max_tokens,
             "stream": stream,
         }
         temperature = request.temperature if request.temperature is not None else self.config.temperature
         # Extended thinking models do not accept the temperature parameter
-        if temperature is not None and not _is_thinking_model(self.config.model):
+        if temperature is not None and not thinking:
             payload["temperature"] = temperature
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/llm/adapters/anthropic_adapter.py` around lines 207 -
218, The `_is_thinking_model(self.config.model)` check is repeated with the same
argument in the Anthropic adapter request path. In `anthropic_adapter.py`,
compute the result once in the surrounding method before building the payload,
store it in a local variable, and reuse that value for both the trailing
assistant-message handling and the temperature gate so the logic stays identical
while avoiding redundant calls.

32-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

DRY: thinking-model detection logic is duplicated across adapters.

_is_thinking_model() is defined here in anthropic_adapter.py but the same substring-matching logic is inlined in litellm_adapter.py lines 227-230. If the set of thinking models changes, both must be updated in sync. Extract this into a shared utility (e.g., in a common module or base adapter) and import it in both adapters.

Also applies to: 227-230

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/llm/adapters/anthropic_adapter.py` around lines 32 - 37,
The thinking-model detection logic is duplicated between anthropic_adapter.py
and litellm_adapter.py, so extract the shared substring check into a common
helper or base adapter and reuse it from both _is_thinking_model() and the
litellm adapter’s inline model check. Keep the existing behavior for matching
model names like opus-4-8 and claude-3-7-sonnet, but centralize the
implementation so future model updates only need one change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/app/services/llm/adapters/litellm_adapter.py`:
- Around line 227-230: The streaming path in stream_complete still
unconditionally sets temperature, which breaks thinking models that do not
accept it. Mirror the model guard already used in _send_request by checking
self.config.model before adding kwargs["temperature"] in stream_complete, and
ensure the same opus-4-8 / claude-3-7-sonnet exclusion applies to streaming
requests.

---

Nitpick comments:
In `@backend/app/services/llm/adapters/anthropic_adapter.py`:
- Around line 207-218: The `_is_thinking_model(self.config.model)` check is
repeated with the same argument in the Anthropic adapter request path. In
`anthropic_adapter.py`, compute the result once in the surrounding method before
building the payload, store it in a local variable, and reuse that value for
both the trailing assistant-message handling and the temperature gate so the
logic stays identical while avoiding redundant calls.
- Around line 32-37: The thinking-model detection logic is duplicated between
anthropic_adapter.py and litellm_adapter.py, so extract the shared substring
check into a common helper or base adapter and reuse it from both
_is_thinking_model() and the litellm adapter’s inline model check. Keep the
existing behavior for matching model names like opus-4-8 and claude-3-7-sonnet,
but centralize the implementation so future model updates only need one change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 476e1207-1e9e-4441-a0e7-729f7b3bd957

📥 Commits

Reviewing files that changed from the base of the PR and between 4dec116 and 51509af.

📒 Files selected for processing (3)
  • backend/app/services/llm/adapters/anthropic_adapter.py
  • backend/app/services/llm/adapters/litellm_adapter.py
  • backend/app/services/llm/factory.py
✅ Files skipped from review due to trivial changes (1)
  • backend/app/services/llm/factory.py

Comment on lines +227 to +230
# Extended thinking models (opus-4-8, claude-3-7-sonnet) do not accept the temperature parameter
_m = (self.config.model or "").lower()
if "opus-4-8" not in _m and "claude-3-7-sonnet" not in _m:
kwargs["temperature"] = request.temperature if request.temperature is not None else self.config.temperature

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

stream_complete still sends temperature for thinking models.

The guard added here in _send_request is missing from stream_complete (line 362), which unconditionally sets kwargs["temperature"]. If a thinking model like claude-opus-4-8 is used with streaming, the API will receive an unsupported temperature parameter and may reject the request. Apply the same guard to the streaming path.

🐛 Proposed fix for `stream_complete`
         kwargs = {
             "model": self._litellm_model,
             "messages": messages,
-            "temperature": request.temperature if request.temperature is not None else self.config.temperature,
             "max_tokens": request.max_tokens if request.max_tokens is not None else self.config.max_tokens,
             "stream": True,
         }
+
+        # Extended thinking models do not accept the temperature parameter
+        _m = (self.config.model or "").lower()
+        if "opus-4-8" not in _m and "claude-3-7-sonnet" not in _m:
+            kwargs["temperature"] = request.temperature if request.temperature is not None else self.config.temperature
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/app/services/llm/adapters/litellm_adapter.py` around lines 227 - 230,
The streaming path in stream_complete still unconditionally sets temperature,
which breaks thinking models that do not accept it. Mirror the model guard
already used in _send_request by checking self.config.model before adding
kwargs["temperature"] in stream_complete, and ensure the same opus-4-8 /
claude-3-7-sonnet exclusion applies to streaming requests.

…tion

_should_attempt_finalizer 之前对 INCOMPLETE 直接返回 False,导致
RUNTIME_FINALIZATION_PROMPT 这条最终兜底的 continuation 从未被执行:
即使模型已完成审计、因超出 nudge 次数而结束,系统也不会给模型最后
一次机会通过 FinalizeFinding 提交结构化结果。

修复方案:
- 仅对 FINALIZE_TOOL(已成功提交)返回 False
- INCOMPLETE 状态也允许进入 finalizer prompts 循环,先尝试
  RUNTIME_FINALIZATION_PROMPT;若仍未提交则回退至
  _default_fallback_payload
- 同步移除对 RuntimeTerminalAction 的引用(相关检查已不再需要),
  清理未使用导入
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant