feat(session): adapter HTTP OpenAI-compatible pour profils locaux/LAN (#14)

Ajoute un adapter de session HTTP OpenAI-compatible, purement additif,
permettant d'intégrer des modèles locaux/LAN comme profils IdeA canoniques
avec parité tool-calling/MCP.

- domain: extension du profil et des ports pour l'adapter OpenAI-compatible
- infrastructure: adapter openai_compat + routage factory
- app-tauri: mapping des outils OpenAI (openai_tools) + wiring state/lib
- application: catalogue d'agents + tests de use-cases profils

Validé QA (backend GO): round-trip byte-identique Claude/Codex, mapping
erreurs, dégradation tools, conversation_id None, conformance un seul Final,
routage factory. Suites vertes domain 467 / application 530 /
infrastructure 523 / app-tauri 247, 0 échec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 22:09:16 +02:00
parent cb20fabdf4
commit aab4bcafb6
14 changed files with 1794 additions and 25 deletions

View File

@ -25,6 +25,7 @@
use std::sync::Arc;
use async_trait::async_trait;
use serde_json::Value;
use thiserror::Error;
use crate::agent::AgentManifest;
@ -368,6 +369,48 @@ pub enum ReplyEvent {
/// clôt le flux ; deltas, activités et heartbeats sont tous non terminaux.
pub type ReplyStream = Box<dyn Iterator<Item = ReplyEvent> + Send>;
/// Description pure d'un outil exposé à un modèle OpenAI-compatible.
#[derive(Debug, Clone, PartialEq)]
pub struct ToolSpec {
/// Nom stable de l'outil (ex. `idea_ask_agent`).
pub name: String,
/// Description destinée au modèle.
pub description: String,
/// Schéma JSON d'entrée de l'outil.
pub input_schema: Value,
}
/// Erreurs du port d'invocation d'outils agentiques.
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum ToolInvocationError {
/// Outil inconnu ou non exposé par l'orchestrateur.
#[error("tool not found: {0}")]
NotFound(String),
/// Arguments invalides ou non conformes au schéma attendu.
#[error("tool invalid arguments: {0}")]
InvalidArguments(String),
/// Refus par gating produit/permissions.
#[error("tool rejected: {0}")]
Rejected(String),
/// Échec d'exécution de l'outil.
#[error("tool execution failed: {0}")]
Execution(String),
}
/// Port pur d'invocation des outils `idea_*` pour les modèles qui n'ont pas de
/// client MCP natif. L'impl concrète vit hors domaine.
#[async_trait]
pub trait ToolInvoker: Send + Sync {
/// Liste des outils exposés au modèle.
fn tools(&self) -> Vec<ToolSpec>;
/// Appelle un outil avec ses arguments JSON bruts.
///
/// # Errors
/// [`ToolInvocationError`] si l'outil est refusé, introuvable ou échoue.
async fn call(&self, name: &str, args_json: &str) -> Result<String, ToolInvocationError>;
}
/// Intention **model-agnostique** exécutée à l'échéance d'un réveil de
/// [`Scheduler`] (ARCHITECTURE §21.4).
///