mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-22 04:35:29 -04:00
CI test fixes for dev sync
This commit is contained in:
@@ -2005,6 +2005,7 @@ async def stream_agent_loop(
|
||||
and (_casual_low_signal_turn or not active_email)
|
||||
and (_casual_low_signal_turn or not workspace)
|
||||
and not forced_tools
|
||||
and not relevant_tools
|
||||
)
|
||||
# Tool retrieval uses the latest message by default. It may inherit recent
|
||||
# user turns only for explicit continuations ("yes", "do it", "1").
|
||||
|
||||
@@ -43,7 +43,8 @@ def test_background_session_sort_uses_owner_task_endpoint():
|
||||
def test_scheduler_fallbacks_and_research_headers_are_owner_scoped():
|
||||
src = _src("src/task_scheduler.py")
|
||||
|
||||
assert "resolve_utility_fallback_candidates(owner=task.owner or None)" in src
|
||||
assert "resolve_task_candidates(" in src
|
||||
assert "owner=task.owner or None" in src
|
||||
assert 'resolve_endpoint(\n "research",' in src
|
||||
assert "owner=task.owner or None" in src
|
||||
assert "headers_from_resolver = False" in src
|
||||
|
||||
@@ -51,23 +51,19 @@ class _Db:
|
||||
self.closed = True
|
||||
|
||||
|
||||
def _resolver_spy(monkeypatch, utility_result=("", "", {}), default_result=("http://llm", "model", {})):
|
||||
from src import endpoint_resolver
|
||||
def _resolver_spy(monkeypatch, candidates=None):
|
||||
from src import task_endpoint
|
||||
|
||||
calls = []
|
||||
fallback_calls = []
|
||||
|
||||
def fake_resolve(kind, *args, **kwargs):
|
||||
calls.append((kind, kwargs.get("owner")))
|
||||
return utility_result if kind == "utility" else default_result
|
||||
def fake_candidates(*args, **kwargs):
|
||||
calls.append(kwargs.get("owner"))
|
||||
if candidates is None:
|
||||
return [("http://llm", "model", {})]
|
||||
return list(candidates)
|
||||
|
||||
def fake_fallbacks(*args, **kwargs):
|
||||
fallback_calls.append(kwargs.get("owner"))
|
||||
return []
|
||||
|
||||
monkeypatch.setattr(endpoint_resolver, "resolve_endpoint", fake_resolve)
|
||||
monkeypatch.setattr(endpoint_resolver, "resolve_utility_fallback_candidates", fake_fallbacks)
|
||||
return calls, fallback_calls
|
||||
monkeypatch.setattr(task_endpoint, "resolve_task_candidates", fake_candidates)
|
||||
return calls
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -88,7 +84,7 @@ async def test_classify_events_resolves_llm_for_task_owner(monkeypatch):
|
||||
location="",
|
||||
)
|
||||
db = _Db({FakeCalendarEvent: [event]})
|
||||
calls, _fallback_calls = _resolver_spy(monkeypatch, utility_result=("http://llm", "model", {}))
|
||||
calls = _resolver_spy(monkeypatch)
|
||||
|
||||
monkeypatch.setattr(database, "CalendarEvent", FakeCalendarEvent)
|
||||
monkeypatch.setattr(database, "SessionLocal", lambda: db)
|
||||
@@ -97,7 +93,7 @@ async def test_classify_events_resolves_llm_for_task_owner(monkeypatch):
|
||||
|
||||
assert ok is True
|
||||
assert "Scanned 1 upcoming event" in message
|
||||
assert calls == [("utility", "alice")]
|
||||
assert calls == ["alice"]
|
||||
assert db.closed is True
|
||||
|
||||
|
||||
@@ -122,7 +118,7 @@ async def test_learn_sender_signatures_resolves_llm_for_task_owner(monkeypatch):
|
||||
def logout(self):
|
||||
return None
|
||||
|
||||
calls, _fallback_calls = _resolver_spy(monkeypatch, utility_result=("", "", {}), default_result=("", "", {}))
|
||||
calls = _resolver_spy(monkeypatch, candidates=[])
|
||||
imap_owners = []
|
||||
|
||||
def fake_imap_connect(_account_id=None, owner=""):
|
||||
@@ -135,14 +131,14 @@ async def test_learn_sender_signatures_resolves_llm_for_task_owner(monkeypatch):
|
||||
|
||||
assert ok is False
|
||||
assert message == "No LLM endpoint available"
|
||||
assert calls == [("utility", "alice"), ("default", "alice")]
|
||||
assert calls == ["alice"]
|
||||
assert imap_owners == ["alice"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_learn_sender_signatures_writes_owner_scoped_cache(monkeypatch, tmp_path):
|
||||
from routes import email_helpers
|
||||
from src import endpoint_resolver, llm_core
|
||||
from src import llm_core, task_endpoint
|
||||
from src.builtin_actions import action_learn_sender_signatures
|
||||
|
||||
db_path = tmp_path / "scheduled_emails.db"
|
||||
@@ -205,15 +201,15 @@ async def test_learn_sender_signatures_writes_owner_scoped_cache(monkeypatch, tm
|
||||
|
||||
monkeypatch.setattr(email_helpers, "_imap_connect", fake_imap_connect)
|
||||
monkeypatch.setattr(
|
||||
endpoint_resolver,
|
||||
"resolve_endpoint",
|
||||
lambda kind, *args, **kwargs: ("http://llm", "alice-model", {}),
|
||||
task_endpoint,
|
||||
"resolve_task_candidates",
|
||||
lambda *args, **kwargs: [("http://llm", "alice-model", {})],
|
||||
)
|
||||
|
||||
async def fake_llm_call_async(**_kwargs):
|
||||
async def fake_llm_call_async(_candidates, **_kwargs):
|
||||
return "Writer Example\nExample Co.\nwriter@example.com"
|
||||
|
||||
monkeypatch.setattr(llm_core, "llm_call_async", fake_llm_call_async)
|
||||
monkeypatch.setattr(llm_core, "llm_call_async_with_fallback", fake_llm_call_async)
|
||||
|
||||
message, ok = await action_learn_sender_signatures("alice")
|
||||
|
||||
@@ -253,7 +249,7 @@ async def test_check_email_urgency_resolves_llm_candidates_for_task_owner(monkey
|
||||
from_address = _Column()
|
||||
|
||||
db = _Db({FakeEmailAccount: []})
|
||||
calls, fallback_calls = _resolver_spy(monkeypatch, utility_result=("http://llm", "model", {}))
|
||||
calls = _resolver_spy(monkeypatch)
|
||||
|
||||
monkeypatch.chdir(tmp_path)
|
||||
monkeypatch.setattr(database, "EmailAccount", FakeEmailAccount)
|
||||
@@ -262,6 +258,5 @@ async def test_check_email_urgency_resolves_llm_candidates_for_task_owner(monkey
|
||||
with pytest.raises(TaskNoop, match="no email accounts configured"):
|
||||
await action_check_email_urgency("alice")
|
||||
|
||||
assert calls == [("utility", "alice")]
|
||||
assert fallback_calls == ["alice"]
|
||||
assert calls == ["alice"]
|
||||
assert db.closed is True
|
||||
|
||||
@@ -29,8 +29,8 @@ def _read_memories(data_dir):
|
||||
@pytest.mark.asyncio
|
||||
async def test_consolidate_memory_empty_owner_treats_each_owner_separately(monkeypatch, tmp_path):
|
||||
from src import constants
|
||||
from src import endpoint_resolver
|
||||
from src import llm_core
|
||||
from src import task_endpoint
|
||||
action_consolidate_memory = _import_consolidate_action()
|
||||
|
||||
long_alice_text = "Alice private project context. " + ("A" * 2200)
|
||||
@@ -44,11 +44,15 @@ async def test_consolidate_memory_empty_owner_treats_each_owner_separately(monke
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(constants, "DATA_DIR", str(data_dir))
|
||||
monkeypatch.setattr(endpoint_resolver, "resolve_endpoint", lambda *args, **kwargs: ("http://llm", "model", {}))
|
||||
monkeypatch.setattr(
|
||||
task_endpoint,
|
||||
"resolve_task_candidates",
|
||||
lambda *args, **kwargs: [("http://llm", "model", {})],
|
||||
)
|
||||
|
||||
prompts = []
|
||||
|
||||
async def fake_llm_call_async(**kwargs):
|
||||
async def fake_llm_call_async(_candidates, **kwargs):
|
||||
prompt = kwargs["messages"][0]["content"]
|
||||
prompts.append(prompt)
|
||||
if "alice-long" in prompt:
|
||||
@@ -71,7 +75,7 @@ async def test_consolidate_memory_empty_owner_treats_each_owner_separately(monke
|
||||
}
|
||||
)
|
||||
|
||||
monkeypatch.setattr(llm_core, "llm_call_async", fake_llm_call_async)
|
||||
monkeypatch.setattr(llm_core, "llm_call_async_with_fallback", fake_llm_call_async)
|
||||
|
||||
message, ok = await action_consolidate_memory("")
|
||||
|
||||
|
||||
@@ -29,24 +29,24 @@ class _FakeMM:
|
||||
|
||||
def test_omitted_memory_survives_only_explicit_drop(monkeypatch):
|
||||
import src.memory
|
||||
import src.endpoint_resolver
|
||||
import src.llm_core
|
||||
import src.task_endpoint
|
||||
|
||||
_FakeMM.saved = None
|
||||
monkeypatch.setattr(src.memory, "MemoryManager", _FakeMM)
|
||||
monkeypatch.setattr(
|
||||
src.endpoint_resolver, "resolve_endpoint",
|
||||
lambda kind, owner=None: ("http://x/v1", "model", {}),
|
||||
src.task_endpoint, "resolve_task_candidates",
|
||||
lambda owner=None: [("http://x/v1", "model", {})],
|
||||
)
|
||||
|
||||
async def fake_llm(**kwargs):
|
||||
async def fake_llm(_candidates, **kwargs):
|
||||
# Model keeps 'a', drops 'b', and OMITS 'c' entirely.
|
||||
return json.dumps({
|
||||
"keep": [{"id": "a", "text": "Likes dark roast coffee", "category": "preference"}],
|
||||
"drop": [{"id": "b", "reason": "duplicate of a"}],
|
||||
})
|
||||
|
||||
monkeypatch.setattr(src.llm_core, "llm_call_async", fake_llm)
|
||||
monkeypatch.setattr(src.llm_core, "llm_call_async_with_fallback", fake_llm)
|
||||
|
||||
msg, ok = asyncio.run(ba.action_consolidate_memory("alice"))
|
||||
|
||||
|
||||
@@ -68,18 +68,18 @@ def test_vllm_blank_swap_omits_swap_space_flag():
|
||||
def test_serve_preflight_uses_selected_server_not_stale_env_host():
|
||||
text = SERVE_SRC.read_text(encoding="utf-8")
|
||||
|
||||
assert "const _selectedServeTarget = (() => {" in text
|
||||
assert "const _hostStr = _selectedServeTarget.host || '';" in text
|
||||
assert "function _selectedServeTarget(panel) {" in text
|
||||
assert "const _hostStr = launchTarget.host || '';" in text
|
||||
assert "(t.remoteHost || '') === _hostStr" in text
|
||||
assert "const _probeHost = (_selectedServeTarget.host || '').trim();" in text
|
||||
assert "const _portHost = (_selectedServeTarget.host || '').trim();" in text
|
||||
assert "const _probeHost = (launchTarget.host || '').trim();" in text
|
||||
assert "const _portHost = (launchTarget.host || '').trim();" in text
|
||||
|
||||
|
||||
def test_vllm_route_strips_swap_space_when_runtime_rejects_it():
|
||||
text = ROUTES_SRC.read_text(encoding="utf-8")
|
||||
|
||||
assert "Removing --swap-space 0; off is represented by omitting the vLLM flag." in text
|
||||
assert "vLLM serve does not support --swap-space; removing it" in text
|
||||
assert "Setting vLLM --swap-space 0 so the runtime does not reserve CPU swap per GPU." in text
|
||||
assert "vLLM serve does not expose --swap-space; removing the flag and patching the runtime default to 0." in text
|
||||
assert "ODYSSEUS_VLLM_HELP_CMD" in text
|
||||
assert "print(shlex.join(parts[:serve_i + 1] + [\"--help\"]))" in text
|
||||
assert "eval \"$ODYSSEUS_VLLM_HELP_CMD\" 2>&1 | grep -q -- \"--swap-space\"" in text
|
||||
|
||||
@@ -348,7 +348,7 @@ def test_serve_pip_install_normalizes_llama_cpp_alias_and_adds_wheel_index():
|
||||
src = (pathlib.Path(__file__).resolve().parent.parent
|
||||
/ "routes" / "cookbook_routes.py").read_text(encoding="utf-8")
|
||||
|
||||
assert "re.sub(r\"(?<![A-Za-z0-9_.-])llama_cpp(?![A-Za-z0-9_.-])\", \"llama-cpp-python[server]\", req.cmd)" in src
|
||||
assert "re.sub(r\"(?<![A-Za-z0-9_.\\-/])llama_cpp(?![A-Za-z0-9_.\\-/])\", \"llama-cpp-python[server]\", req.cmd)" in src
|
||||
assert "if \"llama-cpp-python\" in req.cmd and \"--extra-index-url\" not in req.cmd:" in src
|
||||
assert "https://abetlen.github.io/llama-cpp-python/whl/cpu" in src
|
||||
|
||||
@@ -626,7 +626,7 @@ def test_llama_cpp_linux_bootstrap_prefers_rocm_before_cuda():
|
||||
script = "\n".join(runner_lines)
|
||||
|
||||
assert "mkdir -p ~/bin" in script
|
||||
assert script.index("mkdir -p ~/bin") < script.index("cd ~/llama.cpp && rm -rf build")
|
||||
assert script.index("mkdir -p ~/bin") < script.index("cd ~/llama.cpp")
|
||||
assert 'command -v hipconfig &>/dev/null || [ -d /opt/rocm ] || [ -n "$ROCM_PATH" ] || [ -n "$HIP_PATH" ]' in script
|
||||
assert 'cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_HIP=ON' in script
|
||||
assert 'cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON' in script
|
||||
@@ -676,7 +676,7 @@ def test_llama_cpp_linux_bootstrap_nvcc_without_cudart_warns_and_falls_back():
|
||||
# outer else that handles no-GPU-toolchain). Verify it appears at least once
|
||||
# before the outer "no HIP/CUDA toolchain" warning.
|
||||
cpu_cmake = 'cmake -B build -DCMAKE_BUILD_TYPE=Release &&'
|
||||
no_toolchain_warn = 'WARNING: no HIP/CUDA toolchain found'
|
||||
no_toolchain_warn = 'WARNING: no HIP/CUDA/Vulkan toolchain found'
|
||||
assert cpu_cmake in script
|
||||
assert script.index(cpu_cmake) < script.index(no_toolchain_warn)
|
||||
|
||||
@@ -693,8 +693,8 @@ def test_llama_cpp_linux_bootstrap_keeps_cpu_fallback_when_no_gpu_toolchain():
|
||||
_append_llama_cpp_linux_accel_build_lines(runner_lines)
|
||||
script = "\n".join(runner_lines)
|
||||
|
||||
assert 'WARNING: no HIP/CUDA toolchain found — building llama-server for CPU only.' in script
|
||||
assert 'Install ROCm for AMD GPUs or vLLM/CUDA tooling for NVIDIA' in script
|
||||
assert 'WARNING: no HIP/CUDA/Vulkan toolchain found — building llama-server for CPU only.' in script
|
||||
assert 'Install Vulkan (libvulkan-dev) / ROCm for AMD GPUs or CUDA tooling for NVIDIA' in script
|
||||
|
||||
|
||||
def test_llama_cpp_rebuild_cmd_clears_cached_build_paths():
|
||||
|
||||
@@ -50,14 +50,14 @@ def test_serve_launch_preflights_use_selected_target_and_port():
|
||||
assert "if (launchTarget.port) _probeParams.set('ssh_port', launchTarget.port);" in SERVE
|
||||
assert "const _portHost = (launchTarget.host || '').trim();" in SERVE
|
||||
assert "StrictHostKeyChecking=no ${_sshPrefix(launchTarget.port)}${_portHost}" in SERVE
|
||||
assert "let serveHost = launchTarget.host || '';" in SERVE
|
||||
assert "const serveHost = launchTarget.host || '';" in SERVE
|
||||
assert SERVE.index(launch_target) < SERVE.index("const _runningMod = await import('./cookbookRunning.js');")
|
||||
|
||||
|
||||
def test_running_tab_resolves_profile_key_not_first_host():
|
||||
assert "_serverByVal(_envState.remoteServerKey || _tHost)" in RUNNING
|
||||
assert "_serverByVal(_targetKey)" in RUNNING
|
||||
assert "_serverByVal(_envState.remoteServerKey || _host)" in RUNNING
|
||||
assert "_serverByVal(_envState.remoteServerKey || host)" in RUNNING
|
||||
assert "_serverByVal(savedKey)" in RUNNING
|
||||
assert "_serverByVal = shared._serverByVal;" in RUNNING
|
||||
assert "_selectedServer = shared._selectedServer;" in RUNNING
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ def test_docker_entrypoint_does_not_resolve_root_commands_from_app_local_path():
|
||||
path_export = script.index('export PATH="/app/.local/bin:$PATH"')
|
||||
gosu_capture = script.index('GOSU_BIN="$(command -v gosu)"')
|
||||
python_capture = script.index('PYTHON_BIN="$(command -v python)"')
|
||||
setup_call = script.index('"$GOSU_BIN" "$PUID:$PGID" "$PYTHON_BIN" /app/setup.py')
|
||||
final_exec = script.index('exec "$GOSU_BIN" "$PUID:$PGID" "$@"')
|
||||
setup_call = script.index('"$GOSU_BIN" "$ODY_USER" "$PYTHON_BIN" /app/setup.py')
|
||||
final_exec = script.index('exec "$GOSU_BIN" "$ODY_USER" "$@"')
|
||||
|
||||
assert gosu_capture < path_export < setup_call
|
||||
assert python_capture < path_export < setup_call
|
||||
|
||||
Reference in New Issue
Block a user