feat(agent): orchestration v3 — surface MCP model-agnostic (M0→M4) — §14.3
Expose l'orchestration IdeA comme serveur MCP par-dessus le même OrchestratorService::dispatch, avec repli fichier .ideai/requests pour les CLI sans MCP. v3 réduite à la surface MCP : la messagerie inter-agents et la corrélation requête↔réponse étaient déjà résolues par §17 (send_blocking). - M0 capacité MCP sur le profil (McpCapability/McpConfigStrategy/McpTransport) - M1 injection conf MCP au LaunchAgent + prose adaptée selon la surface - M2 serveur/adapter MCP (JSON-RPC 2.0 maison ; outils idea_*) + ListAgents - M3 câblage par projet (registre mcp_servers jumeau du watcher) - M4 observabilité UI : OrchestratorRequestProcessed.source = file|mcp + badge Trois portes d'entrée (fichier, MCP, UI) → un seul dispatch ; aucun nouveau port applicatif ; MCP confiné à l'adapter infra. Tous lots verts (cycle §3). Cadrage : .ideai/briefs/orchestration-v3-cadrage.md ; ARCHITECTURE.md §14.3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -138,6 +138,64 @@ fn domain_event_dto_maps_pty_output_bytes() {
|
||||
assert_eq!(v["bytes"], json!([1, 2, 3]));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// M4 — orchestration source on `orchestratorRequestProcessed`
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn orchestration_source_dto_serialises_lowercase() {
|
||||
use app_tauri_lib::events::OrchestrationSourceDto;
|
||||
use domain::events::OrchestrationSource;
|
||||
|
||||
// File → "file"; Mcp → "mcp" (camelCase rename on a unit enum = lowercase).
|
||||
let file = serde_json::to_value(OrchestrationSourceDto::from(OrchestrationSource::File)).unwrap();
|
||||
assert_eq!(file, json!("file"));
|
||||
|
||||
let mcp = serde_json::to_value(OrchestrationSourceDto::from(OrchestrationSource::Mcp)).unwrap();
|
||||
assert_eq!(mcp, json!("mcp"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn domain_event_dto_maps_orchestrator_request_processed_with_file_source() {
|
||||
use domain::events::OrchestrationSource;
|
||||
|
||||
let dto = DomainEventDto::from(&DomainEvent::OrchestratorRequestProcessed {
|
||||
requester_id: "Main".into(),
|
||||
action: "spawn_agent".into(),
|
||||
ok: true,
|
||||
source: OrchestrationSource::File,
|
||||
});
|
||||
let v = serde_json::to_value(&dto).unwrap();
|
||||
assert_eq!(
|
||||
v,
|
||||
json!({
|
||||
"type": "orchestratorRequestProcessed",
|
||||
"requesterId": "Main",
|
||||
"action": "spawn_agent",
|
||||
"ok": true,
|
||||
"source": "file",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn domain_event_dto_maps_orchestrator_request_processed_with_mcp_source() {
|
||||
use domain::events::OrchestrationSource;
|
||||
|
||||
let dto = DomainEventDto::from(&DomainEvent::OrchestratorRequestProcessed {
|
||||
requester_id: "mcp".into(),
|
||||
action: "idea_ask_agent".into(),
|
||||
ok: false,
|
||||
source: OrchestrationSource::Mcp,
|
||||
});
|
||||
let v = serde_json::to_value(&dto).unwrap();
|
||||
assert_eq!(v["type"], "orchestratorRequestProcessed");
|
||||
assert_eq!(v["requesterId"], "mcp");
|
||||
assert_eq!(v["action"], "idea_ask_agent");
|
||||
assert_eq!(v["ok"], json!(false));
|
||||
assert_eq!(v["source"], "mcp", "MCP door must badge as `mcp`");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Terminal DTOs (L3)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user