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:
@ -999,10 +999,13 @@ use application::{
|
||||
CloneOpenCodeProfileFromSeedInput, CloneOpenCodeProfileFromSeedOutput, ConfigureProfilesInput,
|
||||
ConfigureProfilesOutput, DeleteProfileInput, DetectProfilesInput, DetectProfilesOutput,
|
||||
FirstRunStateOutput, ListProfilesOutput, ProfileAvailability, ReferenceProfilesOutput,
|
||||
SaveOpenCodeProviderProfileInput, SaveOpenCodeProviderProfileOutput, SaveProfileInput,
|
||||
SaveProfileOutput,
|
||||
SaveClaudeProviderProfileInput, SaveClaudeProviderProfileOutput, SaveCodexProviderProfileInput,
|
||||
SaveCodexProviderProfileOutput, SaveOpenCodeProviderProfileInput,
|
||||
SaveOpenCodeProviderProfileOutput, SaveProfileInput, SaveProfileOutput,
|
||||
};
|
||||
use domain::profile::{
|
||||
AgentProfile, CodexCustomProviderConfig, CustomProviderConfig, OpenCodeConfig,
|
||||
};
|
||||
use domain::profile::{AgentProfile, CustomProviderConfig, OpenCodeConfig};
|
||||
use domain::ProfileId;
|
||||
|
||||
/// A profile crossing the wire. [`AgentProfile`] already serialises camelCase
|
||||
@ -1069,6 +1072,68 @@ impl From<application::OpenCodeProviderCatalogEntry> for OpenCodeProviderDto {
|
||||
}
|
||||
}
|
||||
|
||||
/// One entry of the static Codex provider catalogue (ticket #99).
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CodexProviderDto {
|
||||
pub provider_id: String,
|
||||
pub display_name: String,
|
||||
pub models: Vec<String>,
|
||||
pub custom_supported: bool,
|
||||
}
|
||||
|
||||
impl From<application::CodexProviderCatalogEntry> for CodexProviderDto {
|
||||
fn from(entry: application::CodexProviderCatalogEntry) -> Self {
|
||||
Self {
|
||||
provider_id: entry.provider_id,
|
||||
display_name: entry.display_name,
|
||||
models: entry.models,
|
||||
custom_supported: entry.custom_supported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of Codex provider catalogue entries.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct CodexProviderListDto(pub Vec<CodexProviderDto>);
|
||||
|
||||
impl From<application::ListCodexProvidersOutput> for CodexProviderListDto {
|
||||
fn from(out: application::ListCodexProvidersOutput) -> Self {
|
||||
Self(out.providers.into_iter().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// One entry of the static Claude provider catalogue (ticket #99).
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ClaudeProviderDto {
|
||||
pub provider_id: String,
|
||||
pub display_name: String,
|
||||
pub models: Vec<String>,
|
||||
}
|
||||
|
||||
impl From<application::ClaudeProviderCatalogEntry> for ClaudeProviderDto {
|
||||
fn from(entry: application::ClaudeProviderCatalogEntry) -> Self {
|
||||
Self {
|
||||
provider_id: entry.provider_id,
|
||||
display_name: entry.display_name,
|
||||
models: entry.models,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of Claude provider catalogue entries.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ClaudeProviderListDto(pub Vec<ClaudeProviderDto>);
|
||||
|
||||
impl From<application::ListClaudeProvidersOutput> for ClaudeProviderListDto {
|
||||
fn from(out: application::ListClaudeProvidersOutput) -> Self {
|
||||
Self(out.providers.into_iter().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of OpenCode cloud-provider catalogue entries (camelCase array on the
|
||||
/// wire).
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
@ -1181,6 +1246,63 @@ impl From<SaveOpenCodeProviderProfileOutput> for ProfileDto {
|
||||
}
|
||||
}
|
||||
|
||||
/// Request DTO for `save_codex_provider_profile` (ticket #99).
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SaveCodexProviderProfileRequestDto {
|
||||
pub profile: AgentProfile,
|
||||
pub provider_id: String,
|
||||
pub model: String,
|
||||
pub api_key: String,
|
||||
#[serde(default)]
|
||||
pub custom: Option<CodexCustomProviderConfig>,
|
||||
}
|
||||
|
||||
impl From<SaveCodexProviderProfileRequestDto> for SaveCodexProviderProfileInput {
|
||||
fn from(dto: SaveCodexProviderProfileRequestDto) -> Self {
|
||||
Self {
|
||||
profile: dto.profile,
|
||||
provider_id: dto.provider_id,
|
||||
model: dto.model,
|
||||
api_key: dto.api_key,
|
||||
custom: dto.custom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SaveCodexProviderProfileOutput> for ProfileDto {
|
||||
fn from(out: SaveCodexProviderProfileOutput) -> Self {
|
||||
Self(out.profile)
|
||||
}
|
||||
}
|
||||
|
||||
/// Request DTO for `save_claude_provider_profile` (ticket #99).
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SaveClaudeProviderProfileRequestDto {
|
||||
pub profile: AgentProfile,
|
||||
pub provider_id: String,
|
||||
pub model: String,
|
||||
pub api_key: String,
|
||||
}
|
||||
|
||||
impl From<SaveClaudeProviderProfileRequestDto> for SaveClaudeProviderProfileInput {
|
||||
fn from(dto: SaveClaudeProviderProfileRequestDto) -> Self {
|
||||
Self {
|
||||
profile: dto.profile,
|
||||
provider_id: dto.provider_id,
|
||||
model: dto.model,
|
||||
api_key: dto.api_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SaveClaudeProviderProfileOutput> for ProfileDto {
|
||||
fn from(out: SaveClaudeProviderProfileOutput) -> Self {
|
||||
Self(out.profile)
|
||||
}
|
||||
}
|
||||
|
||||
/// Request DTO for `clone_opencode_profile_from_seed`.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
||||
@ -26,13 +26,13 @@ use application::{
|
||||
GitCheckout, GitCommit, GitGraph, GitInit, GitLog, GitStage, GitStatus, GitUnstage,
|
||||
HarvestMemoryFromTurn, HealthUseCase, InspectConversation, InstallPluginFromArchive,
|
||||
InstallPluginFromDirectory, JsonPluginManifestValidator, LaunchAgent, LaunchAgentInput,
|
||||
LinkIssues, ListAgents, ListAgentsInput, ListDevices, ListEmbedderProfiles, ListIssues,
|
||||
ListLayouts, ListMemories, ListModelServers, ListOpenCodeProviders,
|
||||
ListPluginRuntimeContributions, ListPlugins, ListProfiles, ListProjects, ListResumableAgents,
|
||||
ListSkills, ListSprints, ListTemplates, LiveAgentRegistry, LiveSessions, LiveStateLeanProvider,
|
||||
LiveStateProvider, LiveStateReadProvider, LoadLayout, McpRuntime, McpToolPermissionCatalogue,
|
||||
MoveTabToNewWindow, MutateLayout, OnnxModelView, OpenProject, OpenTerminal,
|
||||
OpenTicketAssistant, OrchestratorService, PairAttemptLimiter, PairDevice,
|
||||
LinkIssues, ListAgents, ListAgentsInput, ListClaudeProviders, ListCodexProviders, ListDevices,
|
||||
ListEmbedderProfiles, ListIssues, ListLayouts, ListMemories, ListModelServers,
|
||||
ListOpenCodeProviders, ListPluginRuntimeContributions, ListPlugins, ListProfiles, ListProjects,
|
||||
ListResumableAgents, ListSkills, ListSprints, ListTemplates, LiveAgentRegistry, LiveSessions,
|
||||
LiveStateLeanProvider, LiveStateProvider, LiveStateReadProvider, LoadLayout, McpRuntime,
|
||||
McpToolPermissionCatalogue, MoveTabToNewWindow, MutateLayout, OnnxModelView, OpenProject,
|
||||
OpenTerminal, OpenTicketAssistant, OrchestratorService, PairAttemptLimiter, PairDevice,
|
||||
PermissionProjectorRegistry, ProposeContext, ReadAgentContext, ReadContext,
|
||||
ReadConversationPage, ReadIssue, ReadIssueCarnet, ReadMcpToolPermissions, ReadMemory,
|
||||
ReadMemoryIndex, ReadProjectContext, ReadSkill, ReadTemplate, RecallMemory, ReconcileLayouts,
|
||||
@ -40,17 +40,17 @@ use application::{
|
||||
RecordTurnProvider, ReferenceProfiles, RenameDevice, RenameLayout, RenameSprint,
|
||||
ReorderSprints, ResizeTerminal, ResolveAgentPermissions, ResolveAgentSystemPermissions,
|
||||
ResolveMemoryLinks, RestoreOpenWindows, RetryBackgroundTask, ReviewPluginPackage,
|
||||
RevokeAllDevices, RevokeDevice, RotateConversationLog, SaveEmbedderProfile, SaveModelServer,
|
||||
SaveOpenCodeProviderProfile, SaveProfile, SessionLimitService, SetActiveLayout,
|
||||
SetPluginEnabled, SnapshotOpenWindows, SnapshotRunningAgents, SpawnBackgroundCommand,
|
||||
StopLiveAgent, StructuredRoutingMode, StructuredSessions, SuggestedThisSession,
|
||||
SyncAgentWithTemplate, TerminalSessions, TouchDevice, UnassignSkillFromAgent,
|
||||
UnassignTicketFromSprint, UninstallPlugin, UnlinkIssues, UpdateAgentContext,
|
||||
UpdateAgentMcpToolPermissions, UpdateAgentPermissions, UpdateAgentSystemPermissions,
|
||||
UpdateIssue, UpdateIssueCarnet, UpdateLiveState, UpdateMemory, UpdateProjectContext,
|
||||
UpdateProjectMcpToolPermissions, UpdateProjectPermissions, UpdateProjectSystemPermissions,
|
||||
UpdateSkill, UpdateTemplate, WakeSessionProvider, WriteMemory, WriteToTerminal,
|
||||
AGENT_MEMORY_RECALL_BUDGET,
|
||||
RevokeAllDevices, RevokeDevice, RotateConversationLog, SaveClaudeProviderProfile,
|
||||
SaveCodexProviderProfile, SaveEmbedderProfile, SaveModelServer, SaveOpenCodeProviderProfile,
|
||||
SaveProfile, SessionLimitService, SetActiveLayout, SetPluginEnabled, SnapshotOpenWindows,
|
||||
SnapshotRunningAgents, SpawnBackgroundCommand, StopLiveAgent, StructuredRoutingMode,
|
||||
StructuredSessions, SuggestedThisSession, SyncAgentWithTemplate, TerminalSessions, TouchDevice,
|
||||
UnassignSkillFromAgent, UnassignTicketFromSprint, UninstallPlugin, UnlinkIssues,
|
||||
UpdateAgentContext, UpdateAgentMcpToolPermissions, UpdateAgentPermissions,
|
||||
UpdateAgentSystemPermissions, UpdateIssue, UpdateIssueCarnet, UpdateLiveState, UpdateMemory,
|
||||
UpdateProjectContext, UpdateProjectMcpToolPermissions, UpdateProjectPermissions,
|
||||
UpdateProjectSystemPermissions, UpdateSkill, UpdateTemplate, WakeSessionProvider, WriteMemory,
|
||||
WriteToTerminal, AGENT_MEMORY_RECALL_BUDGET,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use domain::ports::{
|
||||
@ -938,8 +938,18 @@ pub struct BackendCore {
|
||||
/// Save (upsert) an OpenCode profile backed by a cloud provider, sealing its
|
||||
/// literal API key into the [`SecretStore`] (ticket #92, lot B3).
|
||||
pub save_opencode_provider_profile: Arc<SaveOpenCodeProviderProfile>,
|
||||
/// Save (upsert) a Codex profile backed by a provider/model, sealing its
|
||||
/// literal API key into the [`SecretStore`] (ticket #99).
|
||||
pub save_codex_provider_profile: Arc<SaveCodexProviderProfile>,
|
||||
/// Save (upsert) a Claude profile backed by a provider/model, sealing its
|
||||
/// literal API key into the [`SecretStore`] (ticket #99).
|
||||
pub save_claude_provider_profile: Arc<SaveClaudeProviderProfile>,
|
||||
/// Static catalogue of OpenCode cloud providers (ticket #92, lot B3).
|
||||
pub list_opencode_providers: Arc<ListOpenCodeProviders>,
|
||||
/// Static catalogue of Codex providers (ticket #99).
|
||||
pub list_codex_providers: Arc<ListCodexProviders>,
|
||||
/// Static catalogue of Claude providers (ticket #99).
|
||||
pub list_claude_providers: Arc<ListClaudeProviders>,
|
||||
/// Create a new OpenCode profile instance from the canonical seed.
|
||||
pub clone_opencode_profile_from_seed: Arc<CloneOpenCodeProfileFromSeed>,
|
||||
/// Delete a profile.
|
||||
@ -1467,7 +1477,19 @@ impl BackendCore {
|
||||
Arc::clone(&secret_store_port),
|
||||
Arc::clone(&ids) as Arc<dyn IdGenerator>,
|
||||
));
|
||||
let save_codex_provider_profile = Arc::new(SaveCodexProviderProfile::new(
|
||||
Arc::clone(&profile_store_port),
|
||||
Arc::clone(&secret_store_port),
|
||||
Arc::clone(&ids) as Arc<dyn IdGenerator>,
|
||||
));
|
||||
let save_claude_provider_profile = Arc::new(SaveClaudeProviderProfile::new(
|
||||
Arc::clone(&profile_store_port),
|
||||
Arc::clone(&secret_store_port),
|
||||
Arc::clone(&ids) as Arc<dyn IdGenerator>,
|
||||
));
|
||||
let list_opencode_providers = Arc::new(ListOpenCodeProviders::new());
|
||||
let list_codex_providers = Arc::new(ListCodexProviders::new());
|
||||
let list_claude_providers = Arc::new(ListClaudeProviders::new());
|
||||
let clone_opencode_profile_from_seed = Arc::new(CloneOpenCodeProfileFromSeed::new(
|
||||
Arc::clone(&profile_store_port),
|
||||
Arc::clone(&ids) as Arc<dyn IdGenerator>,
|
||||
@ -2660,7 +2682,11 @@ impl BackendCore {
|
||||
list_profiles,
|
||||
save_profile,
|
||||
save_opencode_provider_profile,
|
||||
save_codex_provider_profile,
|
||||
save_claude_provider_profile,
|
||||
list_opencode_providers,
|
||||
list_codex_providers,
|
||||
list_claude_providers,
|
||||
clone_opencode_profile_from_seed,
|
||||
delete_profile,
|
||||
configure_profiles,
|
||||
|
||||
Reference in New Issue
Block a user