Tasks 12 + 13: worker node agent + Phi-4-mini query triage

Task 12 — node_agent/agent.py: standalone AMQP worker agent
  config reader, model discovery, registration publisher,
  ping/pong handler, model swap with systemctl + health poll
  (14 tests)

Task 13 — triage.py: query classification + cluster node selection
  classify_query() routes to Phi-4-mini at :8083
  select_node() picks best worker by model affinity
  get_inference_url() replaces hardcoded LLAMA_SERVER_BASE
  cluster.py stores node ip for URL construction
  (6 tests + 5 existing chat tests mocked for triage)

168 tests passing (+20 new)
This commit is contained in:
gramps
2026-07-07 07:30:30 -07:00
parent 90d2cf8326
commit fb0ff576d3
12 changed files with 1005 additions and 9 deletions
@@ -9,9 +9,16 @@ import app
import config
import db
import routers.chat
import triage
from security import SESSIONS, PIN_ATTEMPTS, RATE_EVENTS
def _mock_triage_url(monkeypatch, url: str = config.LLAMA_SERVER_BASE):
async def fake_url(query: str) -> str:
return url
monkeypatch.setattr(routers.chat, "_get_inference_url", fake_url)
def make_client(tmp_path: Path) -> TestClient:
os.environ["CAIC_ADMIN_PIN"] = "1234"
db.DB_PATH = tmp_path / "caic-streaming.db"
@@ -53,6 +60,7 @@ def _stream_json_lines(events: list[dict]) -> list[str]:
def test_chat_stream_emits_tokens_and_done(tmp_path: Path, monkeypatch):
_mock_triage_url(monkeypatch)
with make_client(tmp_path) as client:
sid = client.post("/api/auth/guest", headers={"Origin": "http://testserver"}).json()[
"session_id"
@@ -88,6 +96,7 @@ def test_chat_stream_emits_tokens_and_done(tmp_path: Path, monkeypatch):
def test_chat_auto_search_trigger_emits_search_events(tmp_path: Path, monkeypatch):
_mock_triage_url(monkeypatch)
with make_client(tmp_path) as client:
sid = client.post("/api/auth/guest", headers={"Origin": "http://testserver"}).json()[
"session_id"
@@ -142,6 +151,7 @@ def test_chat_auto_search_trigger_emits_search_events(tmp_path: Path, monkeypatc
def test_chat_with_upload_context_id_injects_document(tmp_path: Path, monkeypatch):
_mock_triage_url(monkeypatch)
captured_payload = {}
def stream_stub(self, method, url, json=None, timeout=None):
@@ -173,6 +183,7 @@ def test_chat_with_upload_context_id_injects_document(tmp_path: Path, monkeypatc
def test_chat_with_expired_upload_context_id_silent(tmp_path: Path, monkeypatch):
_mock_triage_url(monkeypatch)
captured_payload = {}
def stream_stub(self, method, url, json=None, timeout=None):
@@ -205,6 +216,7 @@ def test_chat_with_expired_upload_context_id_silent(tmp_path: Path, monkeypatch)
def test_memory_command_paths_remember_and_forget(tmp_path: Path, monkeypatch):
_mock_triage_url(monkeypatch)
with make_client(tmp_path) as client:
sid = client.post("/api/auth/guest", headers={"Origin": "http://testserver"}).json()[
"session_id"