feat: wire hybrid provider into CLI
This commit is contained in:
+116
-1
@@ -1,11 +1,15 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
from javis.config.settings import Settings
|
||||
from javis.core.chat_service import ChatService
|
||||
from javis.interface.cli import run_chat
|
||||
from javis.core.provider_router import HybridProvider
|
||||
from javis.interface.cli import build_runtime, run_chat, run_gemini_configuration
|
||||
from javis.memory.sqlite_store import SQLiteSessionStore
|
||||
from javis.providers.base import ChatMessage
|
||||
from javis.security.privacy import CloudPolicy
|
||||
|
||||
|
||||
class _FakeProvider:
|
||||
@@ -16,6 +20,30 @@ class _FakeProvider:
|
||||
return f"Echo: {messages[-1].content}"
|
||||
|
||||
|
||||
class _FakeHybridProvider(_FakeProvider):
|
||||
name = "hybrid"
|
||||
model = "auto"
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.mode = "auto"
|
||||
self.last_route = None
|
||||
|
||||
def set_mode(self, mode: str) -> None:
|
||||
self.mode = mode
|
||||
|
||||
|
||||
class _LazySecrets:
|
||||
def __init__(self) -> None:
|
||||
self.reads = 0
|
||||
|
||||
def get_gemini_key(self) -> str | None:
|
||||
self.reads += 1
|
||||
return None
|
||||
|
||||
def gemini_key_available(self) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
class CliTests(unittest.TestCase):
|
||||
def test_basic_chat_commands(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
@@ -35,6 +63,93 @@ class CliTests(unittest.TestCase):
|
||||
self.assertTrue(any("Nachrichten" in line for line in output))
|
||||
self.assertEqual(output[-1], "Chat beendet.")
|
||||
|
||||
def test_provider_privacy_and_status_commands_are_sanitized(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
store = SQLiteSessionStore(Path(directory) / "sessions.sqlite3")
|
||||
provider = _FakeHybridProvider()
|
||||
provider.last_route = SimpleNamespace(
|
||||
privacy_policy=CloudPolicy.ASK,
|
||||
provider="ollama",
|
||||
fallback=True,
|
||||
)
|
||||
service = ChatService(store, provider)
|
||||
inputs = iter(
|
||||
[
|
||||
"/provider",
|
||||
"/provider local",
|
||||
"/privacy",
|
||||
"/status",
|
||||
"/exit",
|
||||
]
|
||||
)
|
||||
output: list[str] = []
|
||||
|
||||
result = run_chat(
|
||||
service,
|
||||
input_fn=lambda _prompt: next(inputs),
|
||||
output=output.append,
|
||||
status_fn=lambda: [
|
||||
"Gemini-Schlüssel vorhanden: ja",
|
||||
"Heutige Cloudanfragen: 0",
|
||||
],
|
||||
)
|
||||
|
||||
self.assertEqual(result, 0)
|
||||
self.assertIn("Aktiver Providermodus: auto", output)
|
||||
self.assertIn("Providermodus: local", output)
|
||||
self.assertTrue(any("ask; Provider: ollama; Fallback: ja" in line for line in output))
|
||||
self.assertIn("Gemini-Schlüssel vorhanden: ja", output)
|
||||
|
||||
def test_gemini_configuration_defaults_to_no(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "javis.toml"
|
||||
output: list[str] = []
|
||||
|
||||
result = run_gemini_configuration(
|
||||
path,
|
||||
input_fn=lambda _prompt: "",
|
||||
output=output.append,
|
||||
)
|
||||
|
||||
self.assertEqual(result, 1)
|
||||
self.assertFalse(path.exists())
|
||||
self.assertIn("deaktiviert", output[-1])
|
||||
|
||||
def test_gemini_configuration_requires_both_confirmations(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "javis.toml"
|
||||
answers = iter(["ja", "ja"])
|
||||
|
||||
result = run_gemini_configuration(
|
||||
path,
|
||||
input_fn=lambda _prompt: next(answers),
|
||||
output=lambda _line: None,
|
||||
)
|
||||
|
||||
self.assertEqual(result, 0)
|
||||
self.assertTrue(path.exists())
|
||||
content = path.read_text(encoding="utf-8")
|
||||
self.assertIn("billing_confirmed_disabled = true", content)
|
||||
self.assertNotIn("api_key", content.lower())
|
||||
|
||||
def test_runtime_wires_hybrid_provider_without_loading_key_at_start(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
settings = Settings(data_dir=Path(directory))
|
||||
secrets = _LazySecrets()
|
||||
|
||||
service, _status = build_runtime(
|
||||
settings,
|
||||
input_fn=lambda _prompt: "",
|
||||
output=lambda _line: None,
|
||||
secret_provider=secrets,
|
||||
)
|
||||
session = service.new_session()
|
||||
|
||||
self.assertIsInstance(service.provider, HybridProvider)
|
||||
self.assertEqual(session.provider, "hybrid")
|
||||
self.assertEqual(session.model, "auto")
|
||||
self.assertEqual(secrets.reads, 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user