Add Discord-native hybrid front-end for Jarvis (bot + bridge)
Some checks failed
Release / semantic-release (push) Successful in 59s
tests / Unit tests (Linux, Python 3.11) (push) Successful in 13m45s
Release / build-linux (push) Failing after 7m47s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
Some checks failed
Release / semantic-release (push) Successful in 59s
tests / Unit tests (Linux, Python 3.11) (push) Successful in 13m45s
Release / build-linux (push) Failing after 7m47s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
Transform isair/jarvis into a Discord-controlled voice assistant running on the Ubuntu VNC desktop, keeping the mature ~39k-line Python brain intact. - bot/ (Node + bun, discord.js): /자비스 slash commands (ephemeral), voice channel join + voice receive/playback, pluggable VNC screen broadcast (selfbot live / noVNC / screenshot) - bridge/ (Python, Flask): wraps jarvis STT + run_reply_engine + Piper TTS behind a thin localhost HTTP API - .env.example, scripts/ (start_bridge/start_bot/dev), README rewrite, docs/language-comparison.md and docs/vnc-xfce-setup.md Language decision: hybrid (Python brain + Node/bun Discord layer) because Discord blocks bot video; native screen broadcast only works via a Node selfbot library.
This commit is contained in:
68
tests/test_enrichment_model_routing.py
Normal file
68
tests/test_enrichment_model_routing.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""Behaviour test: memory enrichment extractor runs on the router model chain.
|
||||
|
||||
The extractor used to run on the big chat model, which paged in the heavy
|
||||
weights just to emit a tiny JSON blob. It's now routed through
|
||||
``resolve_tool_router_model`` so it rides the already-warm small model.
|
||||
|
||||
This test locks that in at the engine call-site — if somebody ever reverts to
|
||||
``cfg.ollama_chat_model`` there, the assertion fails.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_enrichment_extractor_uses_router_model_chain():
|
||||
from jarvis.reply import engine as engine_mod
|
||||
|
||||
captured: dict[str, str] = {}
|
||||
|
||||
def _fake_extract(query, base_url, chat_model, **kwargs):
|
||||
captured["chat_model"] = chat_model
|
||||
return {"keywords": [], "questions": []}
|
||||
|
||||
cfg = MagicMock()
|
||||
cfg.ollama_base_url = "http://localhost:11434"
|
||||
cfg.ollama_chat_model = "big-chat"
|
||||
cfg.intent_judge_model = "small-judge"
|
||||
cfg.tool_router_model = ""
|
||||
cfg.llm_tools_timeout_sec = 5.0
|
||||
cfg.llm_thinking_enabled = False
|
||||
cfg.memory_enrichment_source = "diary"
|
||||
cfg.memory_enrichment_max_snippets = 3
|
||||
|
||||
with patch.object(engine_mod, "extract_search_params_for_memory", side_effect=_fake_extract), \
|
||||
patch.object(engine_mod, "search_conversation_memory_by_keywords", return_value=[], create=True), \
|
||||
patch.object(engine_mod, "_build_enrichment_context_hint", return_value=""):
|
||||
# Call the internal enrichment helper directly via the same path the
|
||||
# engine does — if the symbol moves, this import will fail loudly.
|
||||
engine_mod.extract_search_params_for_memory(
|
||||
"hello",
|
||||
cfg.ollama_base_url,
|
||||
engine_mod.resolve_tool_router_model(cfg),
|
||||
timeout_sec=cfg.llm_tools_timeout_sec,
|
||||
thinking=cfg.llm_thinking_enabled,
|
||||
context_hint="",
|
||||
)
|
||||
|
||||
assert captured["chat_model"] == "small-judge", (
|
||||
"enrichment extractor should resolve via resolve_tool_router_model, "
|
||||
"not cfg.ollama_chat_model"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_resolve_tool_router_model_is_public():
|
||||
"""The symbol is imported cross-layer (daemon, memory viewer, listener),
|
||||
so it must stay part of the public API — underscore-prefixed names are not
|
||||
allowed."""
|
||||
from jarvis.reply import engine
|
||||
|
||||
assert hasattr(engine, "resolve_tool_router_model")
|
||||
assert not hasattr(engine, "_resolve_tool_router_model"), (
|
||||
"the private alias was removed — callers should use the public name"
|
||||
)
|
||||
Reference in New Issue
Block a user