mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-18 04:42:20 +02:00
Squash Odysseus development history
This commit is contained in:
@@ -6,6 +6,13 @@ from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_clean_repeated_assistant_content_collapses_concatenated_copies():
|
||||
from routes.chat_helpers import clean_repeated_assistant_content
|
||||
|
||||
answer = "The second event starts at 1:00 AM."
|
||||
assert clean_repeated_assistant_content(answer * 3) == answer
|
||||
from fastapi import HTTPException
|
||||
|
||||
import routes.chat_helpers as chat_helpers
|
||||
@@ -13,9 +20,12 @@ from routes.chat_helpers import (
|
||||
_enforce_chat_privileges,
|
||||
_session_is_research_spinoff,
|
||||
auto_name_session,
|
||||
auto_name_session_after_stream,
|
||||
build_chat_context,
|
||||
build_uploaded_file_manifest,
|
||||
clean_repeated_assistant_content,
|
||||
clean_thinking_for_save,
|
||||
fallback_session_title,
|
||||
needs_auto_name,
|
||||
PreprocessedMessage,
|
||||
PresetInfo,
|
||||
@@ -23,6 +33,42 @@ from routes.chat_helpers import (
|
||||
)
|
||||
|
||||
|
||||
def test_clean_repeated_assistant_content_collapses_rejoined_calendar_answer():
|
||||
answer = (
|
||||
"Here's your calendar for the week:\n\n"
|
||||
"- Monday -- Nothing planned\n"
|
||||
"- Tuesday -- Rent payment\n\n"
|
||||
"Nothing else comes up for the week."
|
||||
)
|
||||
dirty = (
|
||||
"ls.\n</think>\n\n"
|
||||
f"{answer}"
|
||||
"ls.\n</think>\n\n"
|
||||
f"{answer}\n"
|
||||
f"{answer}"
|
||||
)
|
||||
|
||||
assert clean_repeated_assistant_content(dirty) == answer
|
||||
|
||||
|
||||
def test_clean_repeated_assistant_content_preserves_single_answer():
|
||||
answer = "Here's your calendar for September:\n\n- Sep 4 -- Lunch with Jon"
|
||||
|
||||
assert clean_repeated_assistant_content(answer) == answer
|
||||
|
||||
|
||||
def test_qwen_thinking_process_uses_last_explicit_final_marker():
|
||||
leaked = (
|
||||
"Thinking Process:\n\n1. Analyze the request.\n\n"
|
||||
"Final Output Generation:\nDraft answer.\n\n"
|
||||
"Wait, check the context again.\n\n"
|
||||
"Final decision:\nThe preceding result says web access was disabled."
|
||||
)
|
||||
visible, metadata = clean_thinking_for_save(leaked)
|
||||
assert visible == "The preceding result says web access was disabled."
|
||||
assert metadata["thinking"].startswith("1. Analyze the request.")
|
||||
|
||||
|
||||
class _AuthManager:
|
||||
def __init__(self, privileges):
|
||||
self._privileges = privileges
|
||||
@@ -301,6 +347,40 @@ def test_needs_auto_name(name, expected):
|
||||
assert needs_auto_name(name) == expected, f"needs_auto_name({name!r}) should be {expected}"
|
||||
|
||||
|
||||
def test_auto_name_after_stream_reloads_session_before_naming(monkeypatch):
|
||||
stale = SimpleNamespace(id="sid", name="kimi-k3 1:23:45 PM", history=[])
|
||||
fresh = SimpleNamespace(
|
||||
id="sid",
|
||||
name="kimi-k3 1:23:45 PM",
|
||||
history=[SimpleNamespace(role="user", content="search the web for Richmond")],
|
||||
)
|
||||
calls = []
|
||||
|
||||
class Manager:
|
||||
def get_session(self, session_id):
|
||||
assert session_id == "sid"
|
||||
return fresh
|
||||
|
||||
async def fake_auto_name(manager, sess):
|
||||
calls.append(sess)
|
||||
|
||||
monkeypatch.setattr(chat_helpers, "_is_session_stream_active", lambda _sid: False)
|
||||
monkeypatch.setattr(chat_helpers, "auto_name_session", fake_auto_name)
|
||||
|
||||
asyncio.run(auto_name_session_after_stream("sid", Manager(), stale))
|
||||
|
||||
assert calls == [fresh]
|
||||
|
||||
|
||||
def test_fallback_session_title_uses_first_prompt_words():
|
||||
assert (
|
||||
fallback_session_title(
|
||||
"Find the answer online and keep it concise: where does alaska the last frontier take place?"
|
||||
)
|
||||
== "Find the answer online and keep"
|
||||
)
|
||||
|
||||
|
||||
def test_clean_thinking_for_save_extracts_gemma4_thought_channel():
|
||||
content, metadata = clean_thinking_for_save(
|
||||
"<|channel>thought\ninternal reasoning<channel|>Final answer.",
|
||||
@@ -342,6 +422,18 @@ def test_clean_thinking_for_save_extracts_thought_tag():
|
||||
assert metadata["thinking"] == "internal reasoning"
|
||||
|
||||
|
||||
def test_clean_thinking_for_save_preserves_interrupted_thinking_only_turn():
|
||||
content, metadata = clean_thinking_for_save(
|
||||
'<think time="2.4">partial reasoning before stop',
|
||||
{"stopped": True, "model": "thinking-model"},
|
||||
)
|
||||
|
||||
assert content == ""
|
||||
assert metadata["thinking"] == "partial reasoning before stop"
|
||||
assert metadata["thinking_time"] == "2.4"
|
||||
assert metadata["thinking_interrupted"] is True
|
||||
|
||||
|
||||
def test_save_assistant_response_incognito_does_not_mutate_session_history():
|
||||
sess = _FakeSession("selected-model")
|
||||
|
||||
@@ -580,3 +672,107 @@ async def test_build_chat_context_keeps_cookie_user_owner_scope(monkeypatch):
|
||||
"preface_owner": "bob",
|
||||
"compact_owner": "bob",
|
||||
}
|
||||
|
||||
|
||||
async def _build_context_web_probe(monkeypatch, *, message, use_web, agent_mode):
|
||||
captured = {"use_web": None}
|
||||
|
||||
async def fake_preprocess(chat_handler, message, att_ids, sess, **kwargs):
|
||||
return PreprocessedMessage(
|
||||
enhanced_message=message,
|
||||
user_content=message,
|
||||
text_for_context=message,
|
||||
youtube_transcripts=[],
|
||||
attachment_meta=[],
|
||||
)
|
||||
|
||||
def fake_extract_preset(chat_handler, preset_id):
|
||||
return PresetInfo(
|
||||
temperature=0.7,
|
||||
max_tokens=1024,
|
||||
system_prompt=None,
|
||||
character_name=None,
|
||||
)
|
||||
|
||||
def fake_build_context_preface(**kwargs):
|
||||
captured["use_web"] = kwargs["use_web"]
|
||||
return [], [], []
|
||||
|
||||
async def fake_maybe_compact(sess, endpoint_url, model, messages, headers, owner=None):
|
||||
return messages, 8192, False
|
||||
|
||||
monkeypatch.setattr(chat_helpers, "preprocess", fake_preprocess)
|
||||
monkeypatch.setattr(chat_helpers, "extract_preset", fake_extract_preset)
|
||||
monkeypatch.setattr(chat_helpers, "load_prefs_for_user", lambda owner: {"memory_enabled": True, "skills_enabled": True})
|
||||
monkeypatch.setattr(chat_helpers, "_normalize_model_id_from_cache", lambda sess: None)
|
||||
monkeypatch.setattr(chat_helpers, "normalize_model_id", lambda endpoint_url, model, **kwargs: None)
|
||||
monkeypatch.setattr(chat_helpers, "maybe_compact", fake_maybe_compact)
|
||||
monkeypatch.setattr(chat_helpers, "trim_for_context", lambda messages, context_length: messages)
|
||||
|
||||
import src.user_time as user_time
|
||||
|
||||
monkeypatch.setattr(
|
||||
user_time,
|
||||
"current_datetime_context_message",
|
||||
lambda now_utc=None: {"role": "user", "content": "[Context - current date/time]"},
|
||||
raising=False,
|
||||
)
|
||||
|
||||
sess = SimpleNamespace(
|
||||
endpoint_url="http://model.local/v1/chat/completions",
|
||||
model="test-model",
|
||||
headers={},
|
||||
history=[],
|
||||
messages=[],
|
||||
)
|
||||
sess.get_context_messages = lambda: list(sess.messages)
|
||||
request = SimpleNamespace(state=SimpleNamespace(api_token=False, current_user="alice"))
|
||||
|
||||
await build_chat_context(
|
||||
sess=sess,
|
||||
request=request,
|
||||
chat_handler=SimpleNamespace(),
|
||||
chat_processor=SimpleNamespace(build_context_preface=fake_build_context_preface),
|
||||
message=message,
|
||||
session_id="session-1",
|
||||
use_web=use_web,
|
||||
incognito=True,
|
||||
agent_mode=agent_mode,
|
||||
)
|
||||
return captured
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_chat_context_treats_use_web_false_string_as_false(monkeypatch):
|
||||
captured = await _build_context_web_probe(
|
||||
monkeypatch,
|
||||
message="latest apple news",
|
||||
use_web="false",
|
||||
agent_mode=False,
|
||||
)
|
||||
|
||||
assert captured["use_web"] is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_chat_context_skips_pre_web_for_agent_calendar_turn(monkeypatch):
|
||||
captured = await _build_context_web_probe(
|
||||
monkeypatch,
|
||||
message="when is my next appointment",
|
||||
use_web="true",
|
||||
agent_mode=True,
|
||||
)
|
||||
|
||||
assert captured["use_web"] is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_chat_context_skips_pre_web_for_agent_notes_turn(monkeypatch):
|
||||
captured = await _build_context_web_probe(
|
||||
monkeypatch,
|
||||
message="show my latest notes",
|
||||
use_web="true",
|
||||
agent_mode=True,
|
||||
)
|
||||
|
||||
assert captured["use_web"] is False
|
||||
|
||||
Reference in New Issue
Block a user