feat(wave): #119/#122/#131/#132 verts + sprint plugins ESM/persistance #135/#136/#139
État d'intégration confiné à la branche batch. Les tickets #119 (skills → capacités agent découvrables), #122 (override permissions par défaut), #131 (effort par agent/presets) et #132 (outil MCP d'édition du contexte projet) sont verts en périmètre. Le sprint plugins multi-fichiers ESM / persistance plugin-owned (#135/#136/#139) est co-implémenté dans les MÊMES fichiers de câblage (frontend/src/ports/index.ts, backend/src/lib.rs, domain/ports.rs, backend/dto.rs), inséparable sans staging interactif (indisponible ici). Commit unique volontaire : préserve l'état vert QA sans découpe hunk risquée. NON mergé vers develop tant que #137 (QA e2e plugins) n'est pas vert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -337,6 +337,47 @@ impl From<PluginWorkspaceWriteBinaryDto> for application::PluginWorkspaceWriteBi
|
||||
}
|
||||
}
|
||||
|
||||
/// Plugin-owned storage read/delete request DTO.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PluginStorageGetDto {
|
||||
/// Plugin id owning the value.
|
||||
pub plugin_id: String,
|
||||
/// Plugin-owned key.
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
impl From<PluginStorageGetDto> for application::PluginStorageGetInput {
|
||||
fn from(value: PluginStorageGetDto) -> Self {
|
||||
Self {
|
||||
plugin_id: value.plugin_id,
|
||||
key: value.key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Plugin-owned storage write request DTO.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PluginStorageSetDto {
|
||||
/// Plugin id owning the value.
|
||||
pub plugin_id: String,
|
||||
/// Plugin-owned key.
|
||||
pub key: String,
|
||||
/// JSON value to persist.
|
||||
pub value: Value,
|
||||
}
|
||||
|
||||
impl From<PluginStorageSetDto> for application::PluginStorageSetInput {
|
||||
fn from(value: PluginStorageSetDto) -> Self {
|
||||
Self {
|
||||
plugin_id: value.plugin_id,
|
||||
key: value.key,
|
||||
value: value.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Plugin structured config document read request DTO.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -2377,8 +2418,8 @@ use application::{
|
||||
LaunchAgentOutput, ListAgentsOutput, ReadAgentContextOutput, ReadMcpToolPermissionsOutput,
|
||||
};
|
||||
use domain::{
|
||||
Agent, AgentMcpToolPolicyOverride, EffectivePermissions, McpToolPolicy, PermissionSet,
|
||||
ProjectPermissions, SkillKind, TerminalSession,
|
||||
Agent, AgentMcpToolPolicyOverride, EffectivePermissions, EffortSelection, McpToolPolicy,
|
||||
PermissionSet, PermissionShadowReport, ProjectPermissions, SkillKind, TerminalSession,
|
||||
};
|
||||
|
||||
/// One discoverable capability carried by an agent.
|
||||
@ -2413,6 +2454,8 @@ pub struct AgentDto {
|
||||
pub agent: Agent,
|
||||
/// Resolved discoverable capabilities.
|
||||
pub capabilities: Vec<AgentCapabilityDto>,
|
||||
/// Whether this agent is the effective project orchestrator.
|
||||
pub is_orchestrator: bool,
|
||||
}
|
||||
|
||||
impl AgentDto {
|
||||
@ -2422,6 +2465,7 @@ impl AgentDto {
|
||||
Self {
|
||||
agent,
|
||||
capabilities: Vec::new(),
|
||||
is_orchestrator: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2443,6 +2487,7 @@ impl From<ListAgentsOutput> for AgentListDto {
|
||||
.into_iter()
|
||||
.map(AgentCapabilityDto::from)
|
||||
.collect(),
|
||||
is_orchestrator: entry.is_orchestrator,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
@ -2512,6 +2557,25 @@ pub struct ProjectPermissionsDto(pub ProjectPermissions);
|
||||
#[serde(transparent)]
|
||||
pub struct EffectivePermissionsDto(pub EffectivePermissions);
|
||||
|
||||
/// Response for resolving one agent's file/bash permissions.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ResolveAgentPermissionsResponseDto {
|
||||
/// Resolved policy, or `null` when neither project nor agent policy exists.
|
||||
pub effective: Option<EffectivePermissions>,
|
||||
/// Diagnostic report for agent-level allows shadowed by project defaults.
|
||||
pub shadowed: PermissionShadowReport,
|
||||
}
|
||||
|
||||
impl From<application::ResolveAgentPermissionsOutput> for ResolveAgentPermissionsResponseDto {
|
||||
fn from(out: application::ResolveAgentPermissionsOutput) -> Self {
|
||||
Self {
|
||||
effective: out.effective,
|
||||
shadowed: out.shadowed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Full project system permission document crossing the wire.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
@ -2767,6 +2831,18 @@ pub struct ChangeAgentProfileRequestDto {
|
||||
pub cols: u16,
|
||||
}
|
||||
|
||||
/// Request DTO for `update_agent_effort`.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UpdateAgentEffortRequestDto {
|
||||
/// Id of the owning project.
|
||||
pub project_id: String,
|
||||
/// Id of the agent whose effort override changes.
|
||||
pub agent_id: String,
|
||||
/// `null` clears the override.
|
||||
pub effort: Option<EffortSelection>,
|
||||
}
|
||||
|
||||
/// Response DTO for `change_agent_profile`: the mutated agent plus the freshly
|
||||
/// relaunched session when a live session was hot-swapped (absent otherwise).
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
@ -3997,10 +4073,16 @@ pub struct CreateSkillRequestDto {
|
||||
pub project_id: String,
|
||||
/// Display name.
|
||||
pub name: String,
|
||||
/// Optional one-line affordance description.
|
||||
#[serde(default)]
|
||||
pub description: Option<String>,
|
||||
/// Initial Markdown content.
|
||||
pub content: String,
|
||||
/// Scope the skill is created in.
|
||||
pub scope: SkillScope,
|
||||
/// Capability nature. Missing legacy clients create workflow skills.
|
||||
#[serde(default)]
|
||||
pub kind: SkillKind,
|
||||
}
|
||||
|
||||
/// Request DTO for `update_skill`.
|
||||
@ -4703,7 +4785,7 @@ pub struct SpawnBackgroundCommandRequestDto {
|
||||
mod tests {
|
||||
use application::McpToolPermissionCatalogue;
|
||||
use domain::mailbox::TicketId;
|
||||
use domain::{AgentId, ConversationId, ProjectMcpToolPermissions};
|
||||
use domain::{AgentId, ConversationId, PermissionShadowReport, ProjectMcpToolPermissions};
|
||||
use serde_json::json;
|
||||
use uuid::Uuid;
|
||||
|
||||
@ -4755,6 +4837,34 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_agent_permissions_response_dto_uses_effective_plus_shadowed_shape() {
|
||||
let dto = ResolveAgentPermissionsResponseDto {
|
||||
effective: None,
|
||||
shadowed: PermissionShadowReport {
|
||||
read: false,
|
||||
write: false,
|
||||
delete: false,
|
||||
execute_bash: true,
|
||||
fallback: true,
|
||||
},
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(dto).unwrap(),
|
||||
json!({
|
||||
"effective": null,
|
||||
"shadowed": {
|
||||
"read": false,
|
||||
"write": false,
|
||||
"delete": false,
|
||||
"executeBash": true,
|
||||
"fallback": true
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dto_plugins_workspace_requests_use_stable_camel_case_contract() {
|
||||
let path = PluginWorkspacePathDto {
|
||||
@ -4868,6 +4978,42 @@ mod tests {
|
||||
assert_eq!(input.value["enabled"], true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dto_plugins_storage_requests_use_stable_camel_case_contract() {
|
||||
let get = PluginStorageGetDto {
|
||||
plugin_id: "dev.acme.gitgraph".to_owned(),
|
||||
key: "helloPlugin.launches".to_owned(),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(&get).unwrap(),
|
||||
json!({
|
||||
"pluginId": "dev.acme.gitgraph",
|
||||
"key": "helloPlugin.launches"
|
||||
})
|
||||
);
|
||||
let input: application::PluginStorageGetInput = get.into();
|
||||
assert_eq!(input.plugin_id, "dev.acme.gitgraph");
|
||||
assert_eq!(input.key, "helloPlugin.launches");
|
||||
|
||||
let set = PluginStorageSetDto {
|
||||
plugin_id: "dev.acme.gitgraph".to_owned(),
|
||||
key: "helloPlugin.enabled".to_owned(),
|
||||
value: json!({"enabled": true}),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(&set).unwrap(),
|
||||
json!({
|
||||
"pluginId": "dev.acme.gitgraph",
|
||||
"key": "helloPlugin.enabled",
|
||||
"value": {"enabled": true}
|
||||
})
|
||||
);
|
||||
let input: application::PluginStorageSetInput = set.into();
|
||||
assert_eq!(input.plugin_id, "dev.acme.gitgraph");
|
||||
assert_eq!(input.key, "helloPlugin.enabled");
|
||||
assert_eq!(input.value, json!({"enabled": true}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dto_plugins_workspace_outputs_use_stable_camel_case_contract() {
|
||||
let listing = PluginWorkspaceDirectoryListingDto {
|
||||
|
||||
@ -579,6 +579,16 @@ pub enum DomainEventDto {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
orchestrator: Option<String>,
|
||||
},
|
||||
/// The project's global context was written directly.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
ProjectContextUpdated {
|
||||
/// The project whose global context changed.
|
||||
project_id: String,
|
||||
/// Writer party (`"user"` or agent id).
|
||||
by: String,
|
||||
/// Epoch-milliseconds of the write.
|
||||
at_ms: i64,
|
||||
},
|
||||
/// A memory note was created or updated.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
MemorySaved {
|
||||
@ -1213,6 +1223,15 @@ impl From<&DomainEvent> for DomainEventDto {
|
||||
project_id: project_id.to_string(),
|
||||
orchestrator: orchestrator.as_ref().map(|a| a.to_string()),
|
||||
},
|
||||
DomainEvent::ProjectContextUpdated {
|
||||
project_id,
|
||||
by,
|
||||
at_ms,
|
||||
} => Self::ProjectContextUpdated {
|
||||
project_id: project_id.to_string(),
|
||||
by: conversation_party_wire(*by),
|
||||
at_ms: *at_ms,
|
||||
},
|
||||
DomainEvent::MemorySaved { slug } => Self::MemorySaved {
|
||||
slug: slug.as_str().to_string(),
|
||||
},
|
||||
@ -1426,6 +1445,28 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn project_context_updated_relays_writer_to_wire() {
|
||||
let project_id = ProjectId::from_uuid(uuid::Uuid::from_u128(1));
|
||||
let writer = agent(2);
|
||||
|
||||
let dto = DomainEventDto::from(&DomainEvent::ProjectContextUpdated {
|
||||
project_id,
|
||||
by: ConversationParty::agent(writer),
|
||||
at_ms: 987_654,
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(&dto).unwrap(),
|
||||
json!({
|
||||
"type": "projectContextUpdated",
|
||||
"projectId": project_id.to_string(),
|
||||
"by": writer.to_string(),
|
||||
"atMs": 987654,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn background_completion_relays_rendezvous_context_to_wire() {
|
||||
let project_id = ProjectId::from_uuid(uuid::Uuid::from_u128(1));
|
||||
|
||||
@ -11,6 +11,7 @@ use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use application::orchestrator::UpdateProjectContext as GuardedUpdateProjectContext;
|
||||
use application::{
|
||||
AddIssueAttachment, AgentResumer, AgentWakeService, AppError, AssignIssueAgent,
|
||||
AssignSkillToAgent, AssignTicketToSprint, AttachLiveAgent, AuthenticateSession,
|
||||
@ -35,7 +36,7 @@ use application::{
|
||||
MarkIssueAttachmentSummarized, McpRuntime, McpToolPermissionCatalogue, MoveTabToNewWindow,
|
||||
MutateLayout, OnnxModelView, OpenProject, OpenTerminal, OpenTicketAssistant,
|
||||
OrchestratorService, PairAttemptLimiter, PairDevice, PermissionProjectorRegistry,
|
||||
PluginCommandTasks, PluginConfigDocuments, PluginEventSubscriptions,
|
||||
PluginCommandTasks, PluginConfigDocuments, PluginEventSubscriptions, PluginStorageAccess,
|
||||
PluginToolchainDiagnostics, PluginWorkspaceAccess, ProposeContext, QueryProjectStructure,
|
||||
ReadAgentContext, ReadContext, ReadConversationPage, ReadIssue, ReadIssueAttachment,
|
||||
ReadIssueCarnet, ReadMcpToolPermissions, ReadMemory, ReadMemoryIndex, ReadProjectContext,
|
||||
@ -49,7 +50,7 @@ use application::{
|
||||
SetPluginEnabled, SnapshotOpenWindows, SnapshotRunningAgents, SpawnBackgroundCommand,
|
||||
StopLiveAgent, StructuredRoutingMode, StructuredSessions, SuggestedThisSession,
|
||||
SyncAgentWithTemplate, TerminalSessions, TouchDevice, UnassignSkillFromAgent,
|
||||
UnassignTicketFromSprint, UninstallPlugin, UnlinkIssues, UpdateAgentContext,
|
||||
UnassignTicketFromSprint, UninstallPlugin, UnlinkIssues, UpdateAgentContext, UpdateAgentEffort,
|
||||
UpdateAgentMcpToolPermissions, UpdateAgentPermissions, UpdateAgentSystemPermissions,
|
||||
UpdateIssue, UpdateIssueCarnet, UpdateLiveState, UpdateMemory, UpdateProjectContext,
|
||||
UpdateProjectMcpToolPermissions, UpdateProjectPermissions, UpdateProjectSystemPermissions,
|
||||
@ -64,10 +65,11 @@ use domain::ports::{
|
||||
EmbedderProfileStore, EmbedderPromptStore, EnvironmentReader, EventBus, FileSystem, GitPort,
|
||||
IdGenerator, IssueNumberAllocator, IssueStore, McpToolPermissionStore, MemoryRecall,
|
||||
MemoryStore, ModelArtifactDownloader, PermissionStore, PluginManifestValidator,
|
||||
PluginMcpSupervisor, PluginPackageStore, PluginRegistryStore, ProcessSpawner, ProfileStore,
|
||||
ProjectStore, PtyHandle, PtyPort, RuntimePermissionProbe, ScheduledTask, Scheduler,
|
||||
SecretStore, SkillStore, SprintStore, StructuredSessionEnvironmentPreparer,
|
||||
SystemPermissionStore, TemplateStore, ToolInvoker, WakeError, WakeReason, WindowStateStore,
|
||||
PluginMcpSupervisor, PluginPackageStore, PluginRegistryStore, PluginStorageStore,
|
||||
ProcessSpawner, ProfileStore, ProjectStore, PtyHandle, PtyPort, RuntimePermissionProbe,
|
||||
ScheduledTask, Scheduler, SecretStore, SkillStore, SprintStore,
|
||||
StructuredSessionEnvironmentPreparer, SystemPermissionStore, TemplateStore, ToolInvoker,
|
||||
WakeError, WakeReason, WindowStateStore,
|
||||
};
|
||||
use domain::profile::{
|
||||
AgentProfile, ContextInjection, McpConfigStrategy, McpTransport, StructuredAdapter,
|
||||
@ -91,15 +93,15 @@ use infrastructure::{
|
||||
FsEmbedderProfileStore, FsEmbedderPromptStore, FsHandoffStore, FsIssueNumberAllocator,
|
||||
FsIssueStore, FsLiveStateStore, FsMcpToolPermissionStore, FsMemoryStore, FsModelServerRegistry,
|
||||
FsOrchestratorWatcher, FsPermissionStore, FsPluginPackageStore, FsPluginRegistryStore,
|
||||
FsProfileStore, FsProjectStore, FsProviderSessionStore, FsSecretStore, FsSkillStore,
|
||||
FsSprintStore, FsSystemPermissionStore, FsTemplateStore, FsWindowStateStore, Git2Repository,
|
||||
HeuristicHandoffSummarizer, HfModelArtifactDownloader, HttpOpenAiCompatibleProbe,
|
||||
HttpProviderModelCatalogue, IdeaiContextStore, InMemoryConversationRegistry, InMemoryMailbox,
|
||||
InMemoryPairAttemptLimiter, LlamaCppRuntime, LocalEnvironmentReader, LocalFileSystem,
|
||||
LocalManagedProcess, LocalProcessSpawner, McpServer, MediatedInbox, NaiveMemoryRecall,
|
||||
OrchestratorWatchHandle, PortablePtyAdapter, ProcessCliVersionReader,
|
||||
ReadOnlyRuntimePermissionProbe, RwFileGuard, StructuredSessionFactory, SystemClock,
|
||||
SystemMillisClock, TemplateToolProvider, TicketAssistantEnvironmentPreparer,
|
||||
FsPluginStorageStore, FsProfileStore, FsProjectStore, FsProviderSessionStore, FsSecretStore,
|
||||
FsSkillStore, FsSprintStore, FsSystemPermissionStore, FsTemplateStore, FsWindowStateStore,
|
||||
Git2Repository, HeuristicHandoffSummarizer, HfModelArtifactDownloader,
|
||||
HttpOpenAiCompatibleProbe, HttpProviderModelCatalogue, IdeaiContextStore,
|
||||
InMemoryConversationRegistry, InMemoryMailbox, InMemoryPairAttemptLimiter, LlamaCppRuntime,
|
||||
LocalEnvironmentReader, LocalFileSystem, LocalManagedProcess, LocalProcessSpawner, McpServer,
|
||||
MediatedInbox, NaiveMemoryRecall, OrchestratorWatchHandle, PortablePtyAdapter,
|
||||
ProcessCliVersionReader, ReadOnlyRuntimePermissionProbe, RwFileGuard, StructuredSessionFactory,
|
||||
SystemClock, SystemMillisClock, TemplateToolProvider, TicketAssistantEnvironmentPreparer,
|
||||
TicketToolProvider, TokioBroadcastEventBus, TokioScheduler, ToolPolicyRegistry, UuidGenerator,
|
||||
VectorMemoryRecall, DEFAULT_OLLAMA_BASE_URL, ONNX_CACHE_SUBDIR, RECOMMENDED_ONNX_MODELS,
|
||||
VECTOR_HTTP_ENABLED, VECTOR_ONNX_ENABLED,
|
||||
@ -1093,6 +1095,8 @@ pub struct BackendCore {
|
||||
pub update_project_permissions: Arc<UpdateProjectPermissions>,
|
||||
/// Update one agent permission override.
|
||||
pub update_agent_permissions: Arc<UpdateAgentPermissions>,
|
||||
/// Update one agent effort override.
|
||||
pub update_agent_effort: Arc<UpdateAgentEffort>,
|
||||
/// Resolve effective permissions for one agent.
|
||||
pub resolve_agent_permissions: Arc<ResolveAgentPermissions>,
|
||||
/// Read the project system permission document.
|
||||
@ -1142,6 +1146,8 @@ pub struct BackendCore {
|
||||
pub plugin_workspace_access: Arc<PluginWorkspaceAccess>,
|
||||
/// Public plugin structured config document facade.
|
||||
pub plugin_config_documents: Arc<PluginConfigDocuments>,
|
||||
/// Public plugin-owned storage facade.
|
||||
pub plugin_storage_access: Arc<PluginStorageAccess>,
|
||||
/// Public plugin project-structure query use case.
|
||||
pub query_project_structure: Arc<QueryProjectStructure>,
|
||||
/// Public plugin command/task facade.
|
||||
@ -1416,11 +1422,13 @@ impl BackendCore {
|
||||
let events_port = Arc::clone(&event_bus) as Arc<dyn EventBus>;
|
||||
let plugin_packages = Arc::new(FsPluginPackageStore::new(app_data_dir.clone()));
|
||||
let plugin_registry = Arc::new(FsPluginRegistryStore::new(app_data_dir.clone()));
|
||||
let plugin_storage = Arc::new(FsPluginStorageStore::new(app_data_dir.clone()));
|
||||
let plugin_validator =
|
||||
Arc::new(JsonPluginManifestValidator::new(env!("CARGO_PKG_VERSION")));
|
||||
let plugin_mcp_supervisor = Arc::new(ExternalMcpPluginSupervisor::new());
|
||||
let plugin_package_store = Arc::clone(&plugin_packages) as Arc<dyn PluginPackageStore>;
|
||||
let plugin_registry_store = Arc::clone(&plugin_registry) as Arc<dyn PluginRegistryStore>;
|
||||
let plugin_storage_store = Arc::clone(&plugin_storage) as Arc<dyn PluginStorageStore>;
|
||||
let plugin_manifest_validator =
|
||||
Arc::clone(&plugin_validator) as Arc<dyn PluginManifestValidator>;
|
||||
let plugin_mcp_supervisor_port =
|
||||
@ -2178,6 +2186,7 @@ impl BackendCore {
|
||||
let update_agent_permissions = Arc::new(UpdateAgentPermissions::new(Arc::clone(
|
||||
&permission_store_port,
|
||||
)));
|
||||
let update_agent_effort = Arc::new(UpdateAgentEffort::new(Arc::clone(&contexts_port)));
|
||||
let resolve_agent_permissions = Arc::new(ResolveAgentPermissions::new(Arc::clone(
|
||||
&permission_store_port,
|
||||
)));
|
||||
@ -2425,6 +2434,7 @@ impl BackendCore {
|
||||
));
|
||||
let uninstall_plugin = Arc::new(UninstallPlugin::new(
|
||||
Arc::clone(&plugin_package_store),
|
||||
Arc::clone(&plugin_storage_store),
|
||||
Arc::clone(&plugin_registry_store),
|
||||
Arc::clone(&events_port),
|
||||
Arc::clone(&plugin_mcp_supervisor_port),
|
||||
@ -2448,6 +2458,10 @@ impl BackendCore {
|
||||
PluginConfigDocuments::new(Arc::clone(&store_port), Arc::clone(&fs_port))
|
||||
.with_events(Arc::clone(&events_port)),
|
||||
);
|
||||
let plugin_storage_access = Arc::new(PluginStorageAccess::new(
|
||||
Arc::clone(&plugin_storage_store),
|
||||
Arc::clone(&plugin_registry_store),
|
||||
));
|
||||
let query_project_structure = Arc::new(QueryProjectStructure::new(
|
||||
Arc::clone(&store_port),
|
||||
Arc::clone(&fs_port),
|
||||
@ -2718,6 +2732,13 @@ impl BackendCore {
|
||||
Arc::clone(&fs_port),
|
||||
Arc::clone(&clock) as Arc<dyn Clock>,
|
||||
)),
|
||||
update_project_context: Arc::new(GuardedUpdateProjectContext::new(
|
||||
Arc::clone(&file_guard),
|
||||
Arc::clone(&contexts_port),
|
||||
Arc::clone(&fs_port),
|
||||
Arc::clone(&events_port),
|
||||
Arc::clone(&clock) as Arc<dyn Clock>,
|
||||
)),
|
||||
read_memory: Arc::new(ReadMemory::new(
|
||||
Arc::clone(&file_guard),
|
||||
Arc::clone(&memory_store_port),
|
||||
@ -2976,6 +2997,7 @@ impl BackendCore {
|
||||
get_project_permissions,
|
||||
update_project_permissions,
|
||||
update_agent_permissions,
|
||||
update_agent_effort,
|
||||
resolve_agent_permissions,
|
||||
get_project_system_permissions,
|
||||
update_project_system_permissions,
|
||||
@ -3045,6 +3067,7 @@ impl BackendCore {
|
||||
reconcile_plugin_mcp_servers,
|
||||
plugin_workspace_access,
|
||||
plugin_config_documents,
|
||||
plugin_storage_access,
|
||||
query_project_structure,
|
||||
plugin_command_tasks,
|
||||
plugin_toolchain_diagnostics,
|
||||
@ -4649,6 +4672,7 @@ mod mcp_serve_peer_tests {
|
||||
synchronized: false,
|
||||
synced_template_version: None,
|
||||
skills: Vec::new(),
|
||||
effort: None,
|
||||
});
|
||||
id
|
||||
}
|
||||
@ -5387,6 +5411,7 @@ mod mcp_serve_peer_tests {
|
||||
// traite ces commandes sans cette erreur — et le réfute sans le câblage.
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
use application::orchestrator::UpdateProjectContext as GuardedUpdateProjectContext;
|
||||
use application::{ContextGuardUseCases, ProposeContext, ReadContext, ReadMemory, WriteMemory};
|
||||
use domain::conversation::ConversationParty;
|
||||
use domain::memory::{
|
||||
@ -5481,6 +5506,13 @@ mod mcp_serve_peer_tests {
|
||||
Arc::new(FakeFs),
|
||||
Arc::new(FixedClock),
|
||||
)),
|
||||
update_project_context: Arc::new(GuardedUpdateProjectContext::new(
|
||||
Arc::clone(&file_guard),
|
||||
Arc::new(contexts.clone()),
|
||||
Arc::new(FakeFs),
|
||||
Arc::new(NoopBus),
|
||||
Arc::new(FixedClock),
|
||||
)),
|
||||
read_memory: Arc::new(ReadMemory::new(
|
||||
Arc::clone(&file_guard),
|
||||
Arc::clone(&memory) as Arc<dyn MemoryStore>,
|
||||
@ -5977,6 +6009,7 @@ mod mcp_e2e_loopback_tests {
|
||||
synchronized: false,
|
||||
synced_template_version: None,
|
||||
skills: Vec::new(),
|
||||
effort: None,
|
||||
});
|
||||
id
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user