Phase 6 : configuration de l'agent fonctionnelle

Backend :
- agent_config.py : profil persisté (invite système, génération, outils actifs)
  avec valeurs par défaut et fusion robuste
- routes/config.py : GET/PUT /api/config
- db.py : table config clé/valeur (get/set JSON)
- agent.py : run_agent filtre les outils selon enabled_tools
- routes/chat.py : utilise l'invite système, les options de génération et les
  outils actifs issus de la config sauvegardée

Frontend :
- api/client.ts + store : getConfig/saveConfig, état config
- SettingsView : sliders interactifs (température, top-p, top-k, jetons max),
  toggles d'outils réels, éditeur d'invite système, bouton Enregistrer
- ChatPanel : la barre de contexte reflète température et outils actifs réels

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVay7z3y7q2gEe54ByAE6N
This commit is contained in:
MichaelandClaude Opus 4.8 committed 2026-06-29 21:03:14 +00:00
1 parent b6bf4edf97
commit 2db6beea5c
11 files changed
+499 -206

No files matched your search

+7 -12
View File
@@ -14,26 +14,17 @@ from fastapi import APIRouter, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from .. import db
from .. import agent_config, db
from ..agent import run_agent
from ..config import settings
router = APIRouter(prefix="/api", tags=["chat"])
SYSTEM_PROMPT = (
"Tu es Loki, un assistant de développement local agentique. Tu disposes "
"d'outils pour lire, écrire et lister des fichiers dans le workspace. "
"Utilise-les pour accomplir les tâches concrètement, puis réponds de façon "
"concise en français. Après avoir écrit un fichier, propose un aperçu."
)
class ChatRequest(BaseModel):
session_id: str
content: str
model: str | None = None
options: dict | None = None
tools_enabled: bool = True
def _sse(event: str, data: dict) -> str:
@@ -47,6 +38,7 @@ async def chat(req: ChatRequest) -> StreamingResponse:
raise HTTPException(404, "session introuvable")
model = req.model or session.get("model") or settings.default_model
cfg = agent_config.get_config()
# Premier message : titre la session avec un extrait.
if not db.list_messages(req.session_id):
@@ -55,7 +47,7 @@ async def chat(req: ChatRequest) -> StreamingResponse:
db.add_message(req.session_id, "user", req.content, None)
convo = [{"role": "system", "content": SYSTEM_PROMPT}]
convo = [{"role": "system", "content": cfg["system_prompt"]}]
convo += db.list_messages_for_model(req.session_id)
async def event_stream():
@@ -64,7 +56,10 @@ async def chat(req: ChatRequest) -> StreamingResponse:
tools_meta: list[dict] = []
async for ev in run_agent(
model, convo, options=req.options, tools_enabled=req.tools_enabled
model,
convo,
options=agent_config.ollama_options(cfg),
enabled_tools=agent_config.enabled_tool_names(cfg),
):
etype = ev.pop("type")
if etype == "token":
+32
View File
@@ -0,0 +1,32 @@
"""Routes de configuration de l'agent (lecture / mise à jour)."""
from __future__ import annotations
from fastapi import APIRouter
from pydantic import BaseModel
from .. import agent_config
router = APIRouter(prefix="/api/config", tags=["config"])
class ConfigPatch(BaseModel):
system_prompt: str | None = None
temperature: float | None = None
top_p: float | None = None
top_k: int | None = None
max_tokens: int | None = None
tools: dict[str, bool] | None = None
@router.get("")
async def get_config() -> dict:
return {
"config": agent_config.get_config(),
"available_tools": agent_config.AVAILABLE_TOOLS,
}
@router.put("")
async def put_config(patch: ConfigPatch) -> dict:
cfg = agent_config.save_config(patch.model_dump(exclude_none=True))
return {"config": cfg}