feat: add local chat provider and CLI

This commit is contained in:
2026-07-30 17:00:37 +02:00
parent 10d7cd7662
commit ec9b2f94ad
7 changed files with 704 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
"""Chat orchestration without interface or provider-specific details."""
from __future__ import annotations
from dataclasses import dataclass
from javis.memory.sqlite_store import ChatSession, SQLiteSessionStore
from javis.providers.base import ChatMessage, LocalModelProvider
class SessionProviderMismatchError(RuntimeError):
"""The active provider cannot safely continue the stored session."""
@dataclass(frozen=True, slots=True)
class LoadedSession:
session: ChatSession
messages: list[ChatMessage]
class ChatService:
def __init__(
self,
store: SQLiteSessionStore,
provider: LocalModelProvider,
) -> None:
self.store = store
self.provider = provider
def new_session(self) -> ChatSession:
return self.store.create_session(self.provider.name, self.provider.model)
def list_sessions(self) -> list[ChatSession]:
return self.store.list_sessions()
def load_session(self, session_id: str) -> LoadedSession:
session = self.store.get_session(session_id)
if session.provider != self.provider.name or session.model != self.provider.model:
raise SessionProviderMismatchError(
"Die Sitzung verwendet "
f"{session.provider}/{session.model}, aktiv ist "
f"{self.provider.name}/{self.provider.model}."
)
return LoadedSession(session, self.store.get_messages(session_id))
def send(self, session_id: str, text: str) -> str:
normalized = text.strip()
if not normalized:
raise ValueError("Eine leere Nachricht wird nicht gesendet.")
loaded = self.load_session(session_id)
messages = [*loaded.messages, ChatMessage("user", normalized)]
response = self.provider.chat(messages)
self.store.append_exchange(session_id, normalized, response)
return response
def clear_session(self, session_id: str) -> None:
self.store.clear_messages(session_id)