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:
@ -3,15 +3,16 @@
|
||||
//! error behaviour.
|
||||
|
||||
use app_tauri_lib::dto::{
|
||||
parse_delete_profile, parse_profile_id, ConfigureProfilesRequestDto, DetectProfilesRequestDto,
|
||||
DetectProfilesResponseDto, FirstRunStateDto, ProfileListDto, SaveProfileRequestDto,
|
||||
parse_delete_profile, parse_profile_id, CloneOpenCodeProfileFromSeedRequestDto,
|
||||
ConfigureProfilesRequestDto, DetectProfilesRequestDto, DetectProfilesResponseDto,
|
||||
FirstRunStateDto, ProfileListDto, SaveProfileRequestDto,
|
||||
};
|
||||
use application::{
|
||||
ConfigureProfilesInput, DetectProfilesInput, DetectProfilesOutput, FirstRunStateOutput,
|
||||
ProfileAvailability, SaveProfileInput,
|
||||
CloneOpenCodeProfileFromSeedInput, ConfigureProfilesInput, DetectProfilesInput,
|
||||
DetectProfilesOutput, FirstRunStateOutput, ProfileAvailability, SaveProfileInput,
|
||||
};
|
||||
use domain::ids::ProfileId;
|
||||
use domain::profile::{AgentProfile, ContextInjection};
|
||||
use domain::ids::{LocalModelServerId, ProfileId};
|
||||
use domain::profile::{AgentProfile, ContextInjection, OpenCodeConfig};
|
||||
use serde_json::json;
|
||||
use uuid::Uuid;
|
||||
|
||||
@ -94,6 +95,47 @@ fn save_request_deserialises_profile() {
|
||||
assert!(input.profile.detect.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_opencode_profile_from_seed_request_deserialises_camelcase_config() {
|
||||
let server_id = LocalModelServerId::from_uuid(Uuid::from_u128(35));
|
||||
let raw = json!({
|
||||
"name": "Local Qwen",
|
||||
"opencode": {
|
||||
"baseURL": "http://localhost:8081/v1",
|
||||
"model": "qwen3-coder-70b",
|
||||
"reasoning": false,
|
||||
"attachment": true,
|
||||
"localModelServerId": server_id.to_string()
|
||||
}
|
||||
});
|
||||
|
||||
let dto: CloneOpenCodeProfileFromSeedRequestDto = serde_json::from_value(raw).unwrap();
|
||||
let input: CloneOpenCodeProfileFromSeedInput = dto.into();
|
||||
assert_eq!(input.name.as_deref(), Some("Local Qwen"));
|
||||
let opencode = input.opencode.expect("config override");
|
||||
assert_eq!(opencode.base_url, "http://localhost:8081/v1");
|
||||
assert_eq!(opencode.api_key, None);
|
||||
assert_eq!(opencode.model, "qwen3-coder-70b");
|
||||
assert_eq!(opencode.reasoning, Some(false));
|
||||
assert_eq!(opencode.attachment, Some(true));
|
||||
assert_eq!(opencode.local_model_server_id, Some(server_id));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opencode_config_dto_omits_local_model_server_id_when_none() {
|
||||
let config = OpenCodeConfig::new(
|
||||
"http://localhost:8080/v1",
|
||||
None,
|
||||
"qwen3-coder-30b",
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let value = serde_json::to_value(&config).unwrap();
|
||||
assert!(value.get("localModelServerId").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn configure_request_deserialises_profiles() {
|
||||
let raw = json!({ "profiles": [] });
|
||||
|
||||
Reference in New Issue
Block a user