Files
IdeaSDK/crates/infrastructure/src/orchestrator/mcp/policy.rs
Blomios 1fdf62c089 feat(tickets): création d'un assistant IA de ticket (backend + frontend)
Ajoute le chat assistant IA attaché à un ticket (#8).

Backend Rust :
- use cases OpenTicketAssistant/CloseTicketAssistant + tests
- politique d'outils par agent (domain/agent_tool_policy) et policy MCP
- store de contexte assistant + gabarit default_ticket_assistant.md + tests
- events TicketAssistantOpened/Closed
- commandes Tauri open_ticket_chat/close_ticket_chat et câblage state/lib/events

Frontend :
- gateway (ports, adapters ticket + mock, domain)
- hook useTicketAssistant + composant TicketAssistantPanel
- intégration dans TicketDetail

Tests verts : vitest tickets.test.tsx (23), cargo test application::ticket_assistant (1),
infrastructure::assistant_context_store (2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 06:06:24 +02:00

77 lines
2.0 KiB
Rust

//! In-memory MCP tool policy registry.
use std::collections::HashMap;
use std::sync::RwLock;
use domain::AgentToolPolicy;
use domain::AgentToolPolicyStore;
/// Stores per-requester MCP tool policies for live assistant sessions.
#[derive(Default)]
pub struct ToolPolicyRegistry {
policies: RwLock<HashMap<String, AgentToolPolicy>>,
}
impl ToolPolicyRegistry {
/// Builds an empty registry.
#[must_use]
pub fn new() -> Self {
Self::default()
}
/// Sets or replaces the policy for `requester`.
pub fn set(&self, requester: impl Into<String>, policy: AgentToolPolicy) {
self.policies
.write()
.unwrap()
.insert(requester.into(), policy);
}
/// Returns the policy for `requester`, if any.
#[must_use]
pub fn get(&self, requester: &str) -> Option<AgentToolPolicy> {
self.policies.read().unwrap().get(requester).cloned()
}
/// Clears the policy for `requester`.
pub fn clear(&self, requester: &str) {
self.policies.write().unwrap().remove(requester);
}
}
impl AgentToolPolicyStore for ToolPolicyRegistry {
fn set_policy(&self, requester: String, policy: AgentToolPolicy) {
self.set(requester, policy);
}
fn get_policy(&self, requester: &str) -> Option<AgentToolPolicy> {
self.get(requester)
}
fn clear_policy(&self, requester: &str) {
self.clear(requester);
}
}
#[cfg(test)]
mod tests {
use domain::IssueRef;
use super::*;
#[test]
fn set_get_clear_roundtrips_by_requester() {
let registry = ToolPolicyRegistry::new();
let policy = AgentToolPolicy::new(
vec!["idea_ticket_read".to_owned()],
Some("#7".parse::<IssueRef>().unwrap()),
true,
);
registry.set("assistant-1", policy.clone());
assert_eq!(registry.get("assistant-1"), Some(policy));
assert_eq!(registry.get("assistant-2"), None);
registry.clear("assistant-1");
assert_eq!(registry.get("assistant-1"), None);
}
}