//! Domain events published on the [`crate::ports::EventBus`] and relayed to the //! presentation layer (ARCHITECTURE §3.2). use crate::ids::{AgentId, ProfileId, ProjectId, SessionId, SkillId, TemplateId}; use crate::memory::MemorySlug; use crate::template::TemplateVersion; /// Which entry door a processed orchestration request arrived through. /// /// IdeA exposes the *same* [`crate::OrchestratorService::dispatch`] behind two /// substitutable driving adapters (ARCHITECTURE §14.3 + cadrage `orchestration-v3`): /// the `.ideai/requests` filesystem watcher and the MCP server. This tag — set by /// the adapter that received the request, never inferred in the application — lets /// the presentation layer surface *how* a delegation came in. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OrchestrationSource { /// A JSON request file dropped under `.ideai/requests/`. File, /// A `tools/call` on the MCP server. Mcp, } /// Events emitted by the domain/application as state changes occur. /// /// Deliberately *not* `Serialize`/`Deserialize`: events are an in-process /// concern relayed to IPC by an infrastructure adapter, which owns the wire /// format. `PtyOutput` in particular is usually short-circuited to a Tauri /// channel rather than serialised here. #[derive(Debug, Clone, PartialEq, Eq)] pub enum DomainEvent { /// A project was created. ProjectCreated { /// The new project. project_id: ProjectId, }, /// An agent was launched in a terminal. AgentLaunched { /// The agent. agent_id: AgentId, /// The session it runs in. session_id: SessionId, }, /// A target agent produced a synchronous reply to an inter-agent `ask` /// (ARCHITECTURE §17.4): the requester sent a task via `agent.message`, IdeA /// drove the target's structured session to its turn `Final`, and this is the /// observability beacon for that completed rendezvous. Carries the target id and /// the reply size (a lightweight metric); the full body is returned to the /// requester out-of-band, not in the event payload (the bus stays I/O-free). AgentReplied { /// The agent that produced the reply. agent_id: AgentId, /// Number of bytes in the reply content (preview metric, not the payload). reply_len: usize, }, /// An agent's process exited. AgentExited { /// The agent. agent_id: AgentId, /// Exit code. code: i32, }, /// An agent's runtime profile was changed (hot-swap of the AI engine). AgentProfileChanged { /// The agent. agent_id: AgentId, /// The new runtime profile it now uses. profile_id: ProfileId, }, /// A template was updated (content changed, version bumped). TemplateUpdated { /// The template. template_id: TemplateId, /// New version. version: TemplateVersion, }, /// A synchronized agent is behind its template. AgentDriftDetected { /// The drifting agent. agent_id: AgentId, /// Version the agent is currently at. from: TemplateVersion, /// Version available from the template. to: TemplateVersion, }, /// A synchronized agent received its template update. AgentSynced { /// The agent. agent_id: AgentId, /// Version it was brought up to. to: TemplateVersion, }, /// A skill was assigned to (or unassigned from) an agent. SkillAssigned { /// The agent whose skill set changed. agent_id: AgentId, /// The skill involved. skill_id: SkillId, /// `true` if assigned, `false` if unassigned. assigned: bool, }, /// A tab's layout changed. LayoutChanged { /// The project whose layout changed. project_id: ProjectId, }, /// A remote host connection was established. RemoteConnected { /// The project on that remote. project_id: ProjectId, }, /// Git state for a project changed. GitStateChanged { /// The project. project_id: ProjectId, }, /// An orchestrator request (dropped under `.ideai/requests/`) was processed /// by IdeA on behalf of a requester agent (ARCHITECTURE §14.3). Relayed so the /// frontend can surface orchestration activity; the resulting cell/tab opens /// off the [`AgentLaunched`](Self::AgentLaunched) event for `spawn_agent`. OrchestratorRequestProcessed { /// Id of the requesting (orchestrator) agent — the request subdirectory. requester_id: String, /// The action that was processed (`spawn_agent`, `stop_agent`, …). action: String, /// Whether IdeA handled it successfully. ok: bool, /// Which entry door the request arrived through (file watcher vs MCP), /// tagged by the receiving adapter. source: OrchestrationSource, }, /// A memory note was created or updated (`.md` written, index upserted). MemorySaved { /// The saved note's slug. slug: MemorySlug, }, /// A memory note was deleted. MemoryDeleted { /// The deleted note's slug. slug: MemorySlug, }, /// The aggregated `MEMORY.md` index was rebuilt for a project. MemoryIndexRebuilt { /// The project whose index was rebuilt. project_id: ProjectId, }, /// A project's memory grew past the recall budget while no embedder is /// configured (strategy `none`): the first moment a semantic embedder would /// help (ARCHITECTURE §14.5.5, LOT C3). Published **at most once per session per /// project** (and never again once the user chose "ne plus demander"); the /// frontend surfaces a one-time, dismissible suggestion. Carries the detected /// local environment and the compiled-in capabilities so the UI never proposes /// a strategy this binary cannot run. EmbedderSuggested { /// The project whose memory crossed the budget. project_id: ProjectId, /// Whether an Ollama-style local embedding server was detected (best-effort). ollama_detected: bool, /// Ids of the recommended ONNX models already present in the local cache. onnx_cached: Vec, /// Whether the HTTP capability (`localServer`/`api`) is compiled in. vector_http_enabled: bool, /// Whether the in-process ONNX capability (`localOnnx`) is compiled in. vector_onnx_enabled: bool, }, /// Raw PTY output (usually routed to a dedicated channel, not this bus). PtyOutput { /// The session. session_id: SessionId, /// Output bytes. bytes: Vec, }, }