mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-28 15:45:22 -04:00
4e46e415ea
Upstream bug (present in pewdiepie-archdaemon/odysseus main): the task executor passes task.endpoint_url VERBATIM to the model HTTP call, unlike the chat path which stores build_chat_url(normalize_base(base)) on the session. A task carrying an explicit bare OpenAI-compatible base such as "http://host:11434/v1" therefore POSTs to a 404 ("page not found"); the agent loop swallows the empty body into "The model returned an empty response" and marks the run success, so nothing surfaces the failure. Tasks that omit an endpoint dodge this only because _resolve_defaults() cribs an already-full URL from a recent chat session. The API/token path (e.g. an external client that POSTs /api/tasks with endpoint_url=".../v1") hits it every time. Fix: route every resolved task endpoint through _normalize_chat_endpoint() at the three resolution sites (_execute_llm_task, the persona/research session path, and _execute_research_task). The helper is idempotent (strips any existing chat suffix, re-appends the correct one) and leaves native-Ollama (/api...) and already-concrete URLs untouched, so other providers are unaffected. Proven via isolated repro: ".../v1" -> 404 -> empty; ".../v1/chat/completions" -> 200 -> real gemma4:31b output. Regression test asserts the bare-/v1 -> full-chat-URL mapping, idempotency, and the native-Ollama/empty passthroughs. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.7 KiB
Python
44 lines
1.7 KiB
Python
"""Regression test for the task-path endpoint-URL normalization fix.
|
|
|
|
Bug: the task executor passed ``task.endpoint_url`` verbatim to the model HTTP
|
|
call (unlike the chat path, which normalizes via ``build_chat_url``). A bare
|
|
OpenAI-compatible base such as ``http://host:11434/v1`` POSTed to a 404 and the
|
|
run silently reported "The model returned an empty response".
|
|
|
|
The fix routes every resolved task endpoint through ``_normalize_chat_endpoint``.
|
|
"""
|
|
from src.task_scheduler import _normalize_chat_endpoint
|
|
|
|
|
|
def test_bare_v1_base_gets_chat_completions_suffix():
|
|
# The exact failure case: a bare /v1 base must become a full chat URL.
|
|
assert (
|
|
_normalize_chat_endpoint("http://localhost:11434/v1")
|
|
== "http://localhost:11434/v1/chat/completions"
|
|
)
|
|
|
|
|
|
def test_full_chat_url_is_unchanged_idempotent():
|
|
full = "http://localhost:11434/v1/chat/completions"
|
|
assert _normalize_chat_endpoint(full) == full
|
|
# Idempotent under repeated application.
|
|
assert _normalize_chat_endpoint(_normalize_chat_endpoint(full)) == full
|
|
|
|
|
|
def test_native_ollama_url_left_alone():
|
|
# Native Ollama (/api...) has its own downstream normalizer — don't touch it.
|
|
assert _normalize_chat_endpoint("http://localhost:11434/api") == "http://localhost:11434/api"
|
|
assert _normalize_chat_endpoint("http://localhost:11434/api/chat") == "http://localhost:11434/api/chat"
|
|
|
|
|
|
def test_empty_and_none_are_passthrough():
|
|
assert _normalize_chat_endpoint("") == ""
|
|
assert _normalize_chat_endpoint(None) is None
|
|
|
|
|
|
def test_trailing_slash_base_normalized():
|
|
assert (
|
|
_normalize_chat_endpoint("http://localhost:11434/v1/")
|
|
== "http://localhost:11434/v1/chat/completions"
|
|
)
|