mirror of
https://github.com/usestrix/strix.git
synced 2026-09-28 01:31:44 +00:00
fix: apply assistant-prefill guard to Anthropic models in interactive mode (fixes #416)
When interactive mode is enabled (TUI), the guard that prevents sending a trailing assistant message to the Anthropic API was incorrectly skipped. The Anthropic API rejects such requests with "This model does not support assistant message prefill." regardless of whether the caller is in interactive or non-interactive mode. Updated the condition to also apply the guard when `_is_anthropic()` is true, so Anthropic models are always protected while non-Anthropic models that may support assistant prefill continue to be unaffected in interactive mode. Added three unit tests covering all three branches of the new condition. Co-Authored-By: Octopus <liyuan851277048@icloud.com>
This commit is contained in:
parent
8e25743c44
commit
da472ca0d5
2 changed files with 53 additions and 1 deletions
|
|
@ -239,7 +239,9 @@ class LLM:
|
|||
conversation_history.extend(compressed)
|
||||
messages.extend(compressed)
|
||||
|
||||
if messages[-1].get("role") == "assistant" and not self.config.interactive:
|
||||
if messages[-1].get("role") == "assistant" and (
|
||||
not self.config.interactive or self._is_anthropic()
|
||||
):
|
||||
messages.append({"role": "user", "content": "<meta>Continue the task.</meta>"})
|
||||
|
||||
if self._is_anthropic() and self.config.enable_prompt_caching:
|
||||
|
|
|
|||
50
tests/llm/test_prepare_messages.py
Normal file
50
tests/llm/test_prepare_messages.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
"""Tests for LLM._prepare_messages trailing-assistant-message handling."""
|
||||
from strix.llm.config import LLMConfig
|
||||
from strix.llm.llm import LLM
|
||||
|
||||
|
||||
def _make_llm(monkeypatch, model_name: str, interactive: bool) -> LLM:
|
||||
monkeypatch.setenv("STRIX_LLM", model_name)
|
||||
config = LLMConfig(model_name=model_name, interactive=interactive, enable_prompt_caching=False)
|
||||
return LLM(config, agent_name=None)
|
||||
|
||||
|
||||
def _history_ending_with_assistant() -> list[dict]:
|
||||
return [
|
||||
{"role": "user", "content": "Scan this target."},
|
||||
{"role": "assistant", "content": "I found a vulnerability."},
|
||||
]
|
||||
|
||||
|
||||
def test_non_interactive_anthropic_adds_user_message(monkeypatch) -> None:
|
||||
"""Non-interactive mode always appends a user message when history ends with assistant."""
|
||||
llm = _make_llm(monkeypatch, "claude-sonnet-4-6", interactive=False)
|
||||
history = _history_ending_with_assistant()
|
||||
messages = llm._prepare_messages(history)
|
||||
assert messages[-1]["role"] == "user"
|
||||
assert messages[-1]["content"] == "<meta>Continue the task.</meta>"
|
||||
|
||||
|
||||
def test_interactive_anthropic_adds_user_message(monkeypatch) -> None:
|
||||
"""Interactive mode with Anthropic model must also append a user message.
|
||||
|
||||
Anthropic API rejects messages where the last entry has role 'assistant'
|
||||
(no assistant prefill support). This should hold regardless of interactive mode.
|
||||
"""
|
||||
llm = _make_llm(monkeypatch, "claude-sonnet-4-6", interactive=True)
|
||||
history = _history_ending_with_assistant()
|
||||
messages = llm._prepare_messages(history)
|
||||
assert messages[-1]["role"] == "user"
|
||||
assert messages[-1]["content"] == "<meta>Continue the task.</meta>"
|
||||
|
||||
|
||||
def test_interactive_non_anthropic_does_not_add_user_message(monkeypatch) -> None:
|
||||
"""Interactive mode with a non-Anthropic model keeps the trailing assistant message.
|
||||
|
||||
Non-Anthropic models may support assistant prefill; in interactive mode the
|
||||
caller (TUI) is responsible for appending the next user message.
|
||||
"""
|
||||
llm = _make_llm(monkeypatch, "openai/gpt-5.4", interactive=True)
|
||||
history = _history_ending_with_assistant()
|
||||
messages = llm._prepare_messages(history)
|
||||
assert messages[-1]["role"] == "assistant"
|
||||
Loading…
Add table
Reference in a new issue