feat(model-server): backend modèles locaux — serveur llama.cpp intégré (#35) et profils OpenCode locaux multiples (#36)
Sprint « Modeles locaux », couche backend (domain/application/infra/app-tauri). #35 — Serveur de modèle local intégré (llama.cpp) : - domain: model_server.rs (agrégat + statut), ports ModelServerProbe / ManagedProcess / ModelServerRuntime / ModelServerRegistry, événements model_server_status_changed et agent_launch_failed. - application: use case EnsureLocalModelServer branché sur LaunchAgent. - infrastructure: adapters HttpOpenAiCompatibleProbe, LlamaCppRuntime, LocalManagedProcess, FsModelServerRegistry. - app-tauri: DTO plat LocalModelServerConfigDto, commandes list/save/delete_model_server avec garde model_server_in_use, wiring. #36 — Profils OpenCode locaux multiples : - domain: VO LocalModelServerId, OpenCodeConfig.local_model_server_id. - application: use case CloneOpenCodeProfileFromSeed. - app-tauri: commande clone_opencode_profile_from_seed, DTO/wiring. Tests verts (exécution réelle) : domain+application OK, app-tauri dto_model_servers 3/3 et dto_profiles 10/10, infra model_server 2/2, application model_server+profile_usecases 19/19, cargo build workspace Finished. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -6,8 +6,8 @@
|
||||
//! with one error shape when building its `ErrorDTO`.
|
||||
|
||||
use domain::ports::{
|
||||
AgentSessionError, EmbedderError, FsError, GitError, MemoryError, ProcessError, PtyError,
|
||||
RemoteError, RuntimeError, StoreError,
|
||||
AgentSessionError, EmbedderError, FsError, GitError, MemoryError, ModelServerError,
|
||||
ProcessError, PtyError, RemoteError, RuntimeError, StoreError,
|
||||
};
|
||||
use domain::{AgentId, NodeId};
|
||||
use domain::{IssueStoreError, SprintStoreError};
|
||||
@ -38,6 +38,15 @@ pub enum AppError {
|
||||
#[error("process error: {0}")]
|
||||
Process(String),
|
||||
|
||||
/// A local model server could not be prepared for launch.
|
||||
#[error("model server error ({code}): {message}")]
|
||||
ModelServer {
|
||||
/// Stable model-server error code.
|
||||
code: String,
|
||||
/// Human-readable message.
|
||||
message: String,
|
||||
},
|
||||
|
||||
/// A git operation failed.
|
||||
#[error("git error: {0}")]
|
||||
Git(String),
|
||||
@ -101,6 +110,7 @@ impl AppError {
|
||||
Self::FileSystem(_) => "FILESYSTEM",
|
||||
Self::Store(_) => "STORE",
|
||||
Self::Process(_) => "PROCESS",
|
||||
Self::ModelServer { .. } => "MODEL_SERVER",
|
||||
Self::Git(_) => "GIT",
|
||||
Self::Remote(_) => "REMOTE",
|
||||
Self::AgentAlreadyRunning { .. } => "AGENT_ALREADY_RUNNING",
|
||||
@ -183,6 +193,30 @@ impl From<ProcessError> for AppError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ModelServerError> for AppError {
|
||||
fn from(e: ModelServerError) -> Self {
|
||||
Self::ModelServer {
|
||||
code: model_server_error_code(&e).to_owned(),
|
||||
message: e.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn model_server_error_code(err: &ModelServerError) -> &'static str {
|
||||
match err {
|
||||
ModelServerError::NotConfigured => "not_configured",
|
||||
ModelServerError::Invalid(_) => "invalid",
|
||||
ModelServerError::PermissionDenied(_) => "permission_denied",
|
||||
ModelServerError::PathNotAccessible(_) => "path_not_accessible",
|
||||
ModelServerError::PortOccupied(_) => "port_occupied",
|
||||
ModelServerError::InUse(_) => "model_server_in_use",
|
||||
ModelServerError::Probe(_) => "probe",
|
||||
ModelServerError::Process(_) => "process",
|
||||
ModelServerError::Store(_) => "store",
|
||||
ModelServerError::Timeout => "timeout",
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RuntimeError> for AppError {
|
||||
fn from(e: RuntimeError) -> Self {
|
||||
Self::Process(e.to_string())
|
||||
|
||||
Reference in New Issue
Block a user