feat(model-server): afficher le téléchargement du modèle llamacpp au démarrage (#54)
Ajoute un handle du téléchargement des modèles lors du démarrage de llamacpp : le domaine et l'application émettent la progression de téléchargement du modèle, relayée en événement côté app-tauri, et l'UI l'affiche via un badge de lancement et un overlay de cellule pendant que le serveur de modèle démarre. Backend (B1) : progression de téléchargement dans domain/application, relais d'événement app-tauri, couverture de tests. Frontend (F1) : modelServerLaunch, badge et overlay LayoutGrid, tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -36,6 +36,18 @@ pub enum ModelServerStatusDto {
|
||||
Probing,
|
||||
/// IdeA is starting the process.
|
||||
Starting,
|
||||
/// Server is downloading/preparing a remote model.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Downloading {
|
||||
/// Downloaded bytes when known.
|
||||
downloaded_bytes: Option<u64>,
|
||||
/// Total bytes when known.
|
||||
total_bytes: Option<u64>,
|
||||
/// Completion percentage when known.
|
||||
percent: Option<f32>,
|
||||
/// Remote model source.
|
||||
source: Option<String>,
|
||||
},
|
||||
/// Server is ready.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Ready {
|
||||
@ -58,6 +70,17 @@ impl From<&ModelServerLifecycleStatus> for ModelServerStatusDto {
|
||||
ModelServerLifecycleStatus::NotConfigured => Self::NotConfigured,
|
||||
ModelServerLifecycleStatus::Probing => Self::Probing,
|
||||
ModelServerLifecycleStatus::Starting => Self::Starting,
|
||||
ModelServerLifecycleStatus::Downloading {
|
||||
downloaded_bytes,
|
||||
total_bytes,
|
||||
percent,
|
||||
source,
|
||||
} => Self::Downloading {
|
||||
downloaded_bytes: *downloaded_bytes,
|
||||
total_bytes: *total_bytes,
|
||||
percent: *percent,
|
||||
source: source.clone(),
|
||||
},
|
||||
ModelServerLifecycleStatus::Ready { reused } => Self::Ready { reused: *reused },
|
||||
ModelServerLifecycleStatus::Failed { code, message } => Self::Failed {
|
||||
code: code.clone(),
|
||||
@ -1168,6 +1191,31 @@ mod tests {
|
||||
assert_eq!(json["status"]["reused"], true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn model_server_status_changed_relays_downloading_to_dto_and_wire() {
|
||||
let dto = DomainEventDto::from(&DomainEvent::ModelServerStatusChanged {
|
||||
server_id: server(37),
|
||||
status: ModelServerLifecycleStatus::Downloading {
|
||||
downloaded_bytes: None,
|
||||
total_bytes: None,
|
||||
percent: None,
|
||||
source: Some("Qwen/Qwen3-Coder-30B-A3B-Instruct-GGUF".to_owned()),
|
||||
},
|
||||
});
|
||||
|
||||
let json = serde_json::to_value(&dto).expect("serialisable");
|
||||
assert_eq!(json["type"], "modelServerStatusChanged");
|
||||
assert_eq!(json["serverId"], server(37).to_string());
|
||||
assert_eq!(json["status"]["state"], "downloading");
|
||||
assert_eq!(json["status"]["downloadedBytes"], serde_json::Value::Null);
|
||||
assert_eq!(json["status"]["totalBytes"], serde_json::Value::Null);
|
||||
assert_eq!(json["status"]["percent"], serde_json::Value::Null);
|
||||
assert_eq!(
|
||||
json["status"]["source"],
|
||||
"Qwen/Qwen3-Coder-30B-A3B-Instruct-GGUF"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_launch_failed_relays_model_server_cause() {
|
||||
let dto = DomainEventDto::from(&DomainEvent::AgentLaunchFailed {
|
||||
|
||||
Reference in New Issue
Block a user