feat: implémentation et QA ticket99 - agent model configuration v2
- backend A-C: VO Codex/Claude, renderers/projecteurs modèle, SecretRef/env, catalogues/use cases/Tauri commands - frontend D: profils Codex/Claude provider->model->secret, validations, conservation SecretRef - fix: app-tauri embedded_server isolant IDEA_WEB_ROOT QA: backend 57/57 tests, frontend 74/74 tests OK
This commit is contained in:
@ -27,8 +27,9 @@ use application::{
|
||||
reference_profile_id, reference_profiles, CloneOpenCodeProfileFromSeed,
|
||||
CloneOpenCodeProfileFromSeedInput, ConfigureProfiles, ConfigureProfilesInput, DeleteProfile,
|
||||
DeleteProfileInput, DetectProfiles, DetectProfilesInput, FirstRunState, ListProfiles,
|
||||
ReferenceProfiles, SaveOpenCodeProviderProfile, SaveOpenCodeProviderProfileInput, SaveProfile,
|
||||
SaveProfileInput, CODEX_SUBMIT_DELAY_MS,
|
||||
ReferenceProfiles, SaveClaudeProviderProfile, SaveClaudeProviderProfileInput,
|
||||
SaveCodexProviderProfile, SaveCodexProviderProfileInput, SaveOpenCodeProviderProfile,
|
||||
SaveOpenCodeProviderProfileInput, SaveProfile, SaveProfileInput, CODEX_SUBMIT_DELAY_MS,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -600,6 +601,73 @@ async fn delete_profile_with_opencode_provider_purges_its_secret() {
|
||||
assert_eq!(secrets.get(&secret_ref).await.unwrap(), None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn save_codex_provider_profile_seals_key_and_sets_backend_config() {
|
||||
let store = FakeProfileStore::default();
|
||||
let secrets = FakeSecretStore::default();
|
||||
let save = SaveCodexProviderProfile::new(
|
||||
Arc::new(store.clone()),
|
||||
Arc::new(secrets.clone()),
|
||||
Arc::new(SeqIds::new(vec![uuid::Uuid::from_u128(9901)])),
|
||||
);
|
||||
|
||||
let out = save
|
||||
.execute(SaveCodexProviderProfileInput {
|
||||
profile: profile(991, "Codex GPT-5", "codex"),
|
||||
provider_id: "openai".to_owned(),
|
||||
model: "gpt-5".to_owned(),
|
||||
api_key: "sk-openai-literal".to_owned(),
|
||||
custom: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let provider = out.profile.codex_provider.as_ref().unwrap();
|
||||
assert_eq!(provider.provider_id, "openai");
|
||||
assert_eq!(provider.model, "gpt-5");
|
||||
assert_ne!(provider.api_key_ref.as_str(), "sk-openai-literal");
|
||||
assert!(!serde_json::to_string(&out.profile)
|
||||
.unwrap()
|
||||
.contains("sk-openai-literal"));
|
||||
assert_eq!(
|
||||
secrets.get(&provider.api_key_ref).await.unwrap(),
|
||||
Some("sk-openai-literal".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn save_claude_provider_profile_seals_key_and_sets_backend_config() {
|
||||
let store = FakeProfileStore::default();
|
||||
let secrets = FakeSecretStore::default();
|
||||
let save = SaveClaudeProviderProfile::new(
|
||||
Arc::new(store.clone()),
|
||||
Arc::new(secrets.clone()),
|
||||
Arc::new(SeqIds::new(vec![uuid::Uuid::from_u128(9902)])),
|
||||
);
|
||||
|
||||
let out = save
|
||||
.execute(SaveClaudeProviderProfileInput {
|
||||
profile: profile(992, "Claude Sonnet", "claude"),
|
||||
provider_id: "anthropic".to_owned(),
|
||||
model: "claude-sonnet-4-5".to_owned(),
|
||||
api_key: "sk-anthropic-literal".to_owned(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let provider = out.profile.claude_provider.as_ref().unwrap();
|
||||
assert_eq!(provider.provider_id, "anthropic");
|
||||
assert_eq!(provider.model, "claude-sonnet-4-5");
|
||||
assert_ne!(provider.api_key_ref.as_str(), "sk-anthropic-literal");
|
||||
assert!(!serde_json::to_string(&out.profile)
|
||||
.unwrap()
|
||||
.contains("sk-anthropic-literal"));
|
||||
assert_eq!(
|
||||
secrets.get(&provider.api_key_ref).await.unwrap(),
|
||||
Some("sk-anthropic-literal".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn clone_opencode_profile_from_seed_creates_distinct_open_code_instance() {
|
||||
let store = FakeProfileStore::default();
|
||||
|
||||
Reference in New Issue
Block a user