feat(skills): capacités agent découvrables via idea_list_agents
Ajoute SkillKind (Workflow/Reference) sur Skill, extrait le use case ResolveAgentCapabilities à partir des SkillRef assignés, et enrichit idea_list_agents d'un champ additif capabilities (name, description, kind) — remplace l'exposition de SkillRef opaques par un inventaire de capacités interrogeable, source commune avec le bloc « Skills disponibles » injecté au lancement (#119). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1967,20 +1967,58 @@ pub fn parse_profile_id(raw: &str) -> Result<ProfileId, ErrorDto> {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
use application::{
|
||||
ChangeAgentProfileOutput, CreateAgentOutput, InspectConversationOutput, LaunchAgentOutput,
|
||||
ListAgentsOutput, ReadAgentContextOutput, ReadMcpToolPermissionsOutput,
|
||||
AgentCapability, ChangeAgentProfileOutput, CreateAgentOutput, InspectConversationOutput,
|
||||
LaunchAgentOutput, ListAgentsOutput, ReadAgentContextOutput, ReadMcpToolPermissionsOutput,
|
||||
};
|
||||
use domain::{
|
||||
Agent, AgentMcpToolPolicyOverride, EffectivePermissions, McpToolPolicy, PermissionSet,
|
||||
ProjectPermissions, TerminalSession,
|
||||
ProjectPermissions, SkillKind, TerminalSession,
|
||||
};
|
||||
|
||||
/// An agent crossing the wire. [`Agent`] already serialises camelCase
|
||||
/// (`id`, `name`, `contextPath`, `profileId`, `origin` tagged, `synchronized`),
|
||||
/// so we embed it directly — the TS mirror matches this shape.
|
||||
/// One discoverable capability carried by an agent.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct AgentDto(pub Agent);
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AgentCapabilityDto {
|
||||
/// Capability display name.
|
||||
pub name: String,
|
||||
/// One-line affordance description.
|
||||
pub description: String,
|
||||
/// Capability nature.
|
||||
pub kind: SkillKind,
|
||||
}
|
||||
|
||||
impl From<AgentCapability> for AgentCapabilityDto {
|
||||
fn from(value: AgentCapability) -> Self {
|
||||
Self {
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
kind: value.kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An agent crossing the wire. The raw [`Agent`] shape is flattened so existing
|
||||
/// fields, including `skills`, remain compatible; `capabilities` is additive.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AgentDto {
|
||||
/// Raw agent manifest shape.
|
||||
#[serde(flatten)]
|
||||
pub agent: Agent,
|
||||
/// Resolved discoverable capabilities.
|
||||
pub capabilities: Vec<AgentCapabilityDto>,
|
||||
}
|
||||
|
||||
impl AgentDto {
|
||||
/// Builds a DTO without resolved capabilities.
|
||||
#[must_use]
|
||||
pub fn from_agent(agent: Agent) -> Self {
|
||||
Self {
|
||||
agent,
|
||||
capabilities: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of agents (camelCase array on the wire).
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
@ -1989,13 +2027,25 @@ pub struct AgentListDto(pub Vec<AgentDto>);
|
||||
|
||||
impl From<ListAgentsOutput> for AgentListDto {
|
||||
fn from(out: ListAgentsOutput) -> Self {
|
||||
Self(out.agents.into_iter().map(AgentDto).collect())
|
||||
Self(
|
||||
out.discovery_entries()
|
||||
.into_iter()
|
||||
.map(|entry| AgentDto {
|
||||
agent: entry.agent,
|
||||
capabilities: entry
|
||||
.capabilities
|
||||
.into_iter()
|
||||
.map(AgentCapabilityDto::from)
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CreateAgentOutput> for AgentDto {
|
||||
fn from(out: CreateAgentOutput) -> Self {
|
||||
Self(out.agent)
|
||||
Self::from_agent(out.agent)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2326,7 +2376,7 @@ pub struct ChangeAgentProfileDto {
|
||||
impl From<ChangeAgentProfileOutput> for ChangeAgentProfileDto {
|
||||
fn from(out: ChangeAgentProfileOutput) -> Self {
|
||||
Self {
|
||||
agent: AgentDto(out.agent),
|
||||
agent: AgentDto::from_agent(out.agent),
|
||||
relaunched_session: out.relaunched.map(TerminalSessionDto::from),
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,19 +40,19 @@ use application::{
|
||||
ReadProjectContext, ReadSkill, ReadTemplate, RecallMemory, ReconcileLayouts,
|
||||
ReconcileLiveState, ReconcileLiveStateInput, ReconcilePluginMcpServers, RecordTurn,
|
||||
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,
|
||||
ReorderSprints, ResizeTerminal, ResolveAgentCapabilities, 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,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use domain::ports::{
|
||||
@ -1977,12 +1977,18 @@ impl BackendCore {
|
||||
&prompt_store_port,
|
||||
)));
|
||||
|
||||
let agent_capabilities =
|
||||
Arc::new(ResolveAgentCapabilities::new(Arc::clone(&skill_store_port)));
|
||||
|
||||
let create_agent = Arc::new(CreateAgentFromScratch::new(
|
||||
Arc::clone(&contexts_port),
|
||||
Arc::clone(&ids) as Arc<dyn IdGenerator>,
|
||||
Arc::clone(&events_port),
|
||||
));
|
||||
let list_agents = Arc::new(ListAgents::new(Arc::clone(&contexts_port)));
|
||||
let list_agents = Arc::new(ListAgents::with_capabilities(
|
||||
Arc::clone(&contexts_port),
|
||||
Arc::clone(&agent_capabilities),
|
||||
));
|
||||
let read_agent_context = Arc::new(ReadAgentContext::new(Arc::clone(&contexts_port)));
|
||||
let update_agent_context = Arc::new(UpdateAgentContext::new(Arc::clone(&contexts_port)));
|
||||
let delete_agent = Arc::new(DeleteAgent::new(
|
||||
|
||||
Reference in New Issue
Block a user