feat: finalise ticket99 - implémentation agent model configuration v2
- agent/lifecycle.rs: lifecycle management per profile
- agent/provider_catalogue.rs: provider registration with model support
- agent/usecases.rs: usecases for profile-based agent invocation
- agent/mod.rs: expose agent capabilities via AgentManager
- backend/dto.rs: AgentModelConfig, AgentProviderConfig DTOs
- domain/profile.rs: extend Profile avec agent capabilities
- domain/permission.rs: permission checks pour agent access
- infrastructure/assistant/mod.rs: agent integration
- infrastructure/permission/{claude,codex}.rs: permission handlers
- web-server/lib.rs: agent endpoints
- commands.rs: agent commands
- frontend/adapters/{http,profile,mock,domain}.ts: adapters
- frontend/first-run/FirstRunWizard.{test.tsx,tsx}: first-run flow
This commit is contained in:
@ -27,9 +27,8 @@ use application::{
|
||||
reference_profile_id, reference_profiles, CloneOpenCodeProfileFromSeed,
|
||||
CloneOpenCodeProfileFromSeedInput, ConfigureProfiles, ConfigureProfilesInput, DeleteProfile,
|
||||
DeleteProfileInput, DetectProfiles, DetectProfilesInput, FirstRunState, ListProfiles,
|
||||
ReferenceProfiles, SaveClaudeProviderProfile, SaveClaudeProviderProfileInput,
|
||||
SaveCodexProviderProfile, SaveCodexProviderProfileInput, SaveOpenCodeProviderProfile,
|
||||
SaveOpenCodeProviderProfileInput, SaveProfile, SaveProfileInput, CODEX_SUBMIT_DELAY_MS,
|
||||
ReferenceProfiles, SaveOpenCodeProviderProfile, SaveOpenCodeProviderProfileInput, SaveProfile,
|
||||
SaveProfileInput, CODEX_SUBMIT_DELAY_MS,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -602,70 +601,25 @@ async fn delete_profile_with_opencode_provider_purges_its_secret() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn save_codex_provider_profile_seals_key_and_sets_backend_config() {
|
||||
async fn save_profile_persists_codex_claude_model_without_provider_or_secret_surface() {
|
||||
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 save = SaveProfile::new(Arc::new(store.clone()));
|
||||
let profile = profile(991, "Codex GPT-5", "codex").with_model("gpt-5-codex");
|
||||
|
||||
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,
|
||||
.execute(SaveProfileInput {
|
||||
profile: profile.clone(),
|
||||
})
|
||||
.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())
|
||||
);
|
||||
assert_eq!(out.profile.model.as_deref(), Some("gpt-5-codex"));
|
||||
let json = serde_json::to_string(&out.profile).unwrap();
|
||||
assert!(!json.contains("codexProvider"), "got: {json}");
|
||||
assert!(!json.contains("claudeProvider"), "got: {json}");
|
||||
assert!(!json.contains("apiKey"), "got: {json}");
|
||||
assert!(!json.contains("providerId"), "got: {json}");
|
||||
assert_eq!(store.list().await.unwrap(), vec![profile]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user