feat(backend): catalogue de providers OpenCode dynamique + provider personnalisé (#92)

Le catalogue de providers OpenCode lit désormais le cache local
~/.cache/opencode/models.json pour refléter les providers réellement
disponibles, avec repli garanti sur le catalogue statique en cas
d'absence ou d'erreur de lecture du cache. Ajout d'un champ additif
`custom` sur OpenCodeProviderConfig pour permettre à l'utilisateur de
déclarer un provider hors catalogue (id + clé API en saisie libre).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 12:43:59 +02:00
parent 162e3ae641
commit e943a0efed
10 changed files with 502 additions and 57 deletions

View File

@ -999,7 +999,7 @@ use application::{
SaveOpenCodeProviderProfileInput, SaveOpenCodeProviderProfileOutput, SaveProfileInput,
SaveProfileOutput,
};
use domain::profile::{AgentProfile, OpenCodeConfig};
use domain::profile::{AgentProfile, CustomProviderConfig, OpenCodeConfig};
use domain::ProfileId;
/// A profile crossing the wire. [`AgentProfile`] already serialises camelCase
@ -1059,9 +1059,9 @@ pub struct OpenCodeProviderDto {
impl From<application::OpenCodeProviderCatalogEntry> for OpenCodeProviderDto {
fn from(entry: application::OpenCodeProviderCatalogEntry) -> Self {
Self {
provider_id: entry.provider_id.to_owned(),
display_name: entry.display_name.to_owned(),
models: entry.models.iter().map(|&m| m.to_owned()).collect(),
provider_id: entry.provider_id,
display_name: entry.display_name,
models: entry.models,
}
}
}
@ -1154,6 +1154,10 @@ pub struct SaveOpenCodeProviderProfileRequestDto {
pub model: String,
/// Literal API key, sealed into the `SecretStore` — never persisted as-is.
pub api_key: String,
/// Optional custom-provider configuration (endpoint outside the OpenCode
/// registry). Absent/`null` = known provider (unchanged behaviour).
#[serde(default)]
pub custom: Option<CustomProviderConfig>,
}
impl From<SaveOpenCodeProviderProfileRequestDto> for SaveOpenCodeProviderProfileInput {
@ -1163,6 +1167,7 @@ impl From<SaveOpenCodeProviderProfileRequestDto> for SaveOpenCodeProviderProfile
provider_id: dto.provider_id,
model: dto.model,
api_key: dto.api_key,
custom: dto.custom,
}
}
}