//! Internal app events delivered via channel. //! //! Background tasks (PTY child watchers, future hook listeners, etc.) send //! events to the main loop through this channel. No polling needed. use std::time::Instant; use crate::detect::{Agent, AgentState}; use crate::layout::PaneId; use crate::workspace::{GitStatusCacheEntry, WorkspaceGitStatus}; #[derive(Debug)] pub struct ApiWorktreeAddRequest { pub id: String, pub operation_id: u64, pub checkout_key: std::path::PathBuf, pub source_workspace_id: Option, pub source_existing_membership: Option, pub source_checkout_path: std::path::PathBuf, pub source_repo_root: std::path::PathBuf, pub repo_key: String, pub repo_name: String, pub label: Option, pub focus: bool, pub respond_to: std::sync::mpsc::Sender, } #[derive(Debug)] pub struct WorktreeAddResult { pub path: std::path::PathBuf, pub api_request: Option, pub result: Result<(), String>, } #[derive(Debug)] pub struct ApiWorktreeRemoveRequest { pub id: String, pub operation_id: u64, pub checkout_key: std::path::PathBuf, pub shutdown_panes: Vec, pub respond_to: std::sync::mpsc::Sender, } #[derive(Debug)] pub struct WorktreeRemoveResult { pub workspace_id: String, pub path: std::path::PathBuf, pub workspace: Option>, pub worktree: Option>, pub forced: bool, pub api_request: Option, pub result: Result<(), String>, } #[derive(Debug)] pub struct WorktreeReadResult { // Keep the slot until completion is consumed, including time queued on the app loop. pub(crate) _permit: tokio::sync::OwnedSemaphorePermit, pub(crate) client_local: bool, pub(crate) request: crate::api::schema::Request, pub(crate) source_workspace_id: Option, pub(crate) source_cwd: Option, pub(crate) result: Result, pub(crate) respond_to: std::sync::mpsc::Sender, } #[derive(Debug)] pub(crate) struct WorktreeReadData { pub source_checkout_path: std::path::PathBuf, pub source_repo_root: std::path::PathBuf, pub repo_key: String, pub repo_name: String, pub entries: Vec, } /// An event from a background task to the main loop. #[derive(Debug)] pub enum AppEvent { /// A pane's child process exited. PaneDied { pane_id: PaneId, exit_reason: crate::platform::ChildExitReason, }, /// A worktree-removal runtime could not be restored normally. WorktreeRuntimeRestoreFailed { pane_id: PaneId, operation_id: u64 }, /// Process detection identified an agent before its screen state was confirmed. AgentProcessDetected { pane_id: PaneId, agent: Agent, observed_at: Instant, }, /// The current Codex input screen is visible during managed startup. CodexPromptObserved { pane_id: PaneId, ready: bool }, /// Fallback detector state changed in a pane. StateChanged { pane_id: PaneId, agent: Option, state: AgentState, visible_blocker: bool, visible_working: bool, process_exited: bool, observed_at: Instant, }, /// Hook-authoritative agent state was reported for a pane. HookStateReported { pane_id: PaneId, source: String, agent_label: String, state: AgentState, message: Option, seq: Option, session_ref: Option, }, /// Agent session identity was reported without state authority. AgentSessionReported { pane_id: PaneId, source: String, agent_label: String, seq: Option, session_ref: Option, session_start_source: Option, }, /// A reporter supplied the command that resumes its own session. AgentResumeReported { pane_id: PaneId, source: String, agent_label: String, seq: Option, argv: Vec, }, /// A pane held by a self-reported agent is back at its idle shell. ReportedAgentShellReturned { pane_id: PaneId, observed_at: std::time::Instant, }, /// Display-only agent metadata was reported for a pane. HookMetadataReported { pane_id: PaneId, source: String, agent_label: Option, applies_to_source: Option, title: Option, display_agent: Option, state_labels: std::collections::HashMap, clear_title: bool, clear_display_agent: bool, clear_state_labels: bool, seq: Option, ttl: Option, }, /// Hook authority was explicitly cleared for a pane. HookAuthorityCleared { pane_id: PaneId, source: Option, seq: Option, }, /// The current detected agent gracefully released this pane back to the shell. HookAgentReleased { pane_id: PaneId, source: String, agent_label: String, known_agent: Option, seq: Option, }, /// A new version is available through the active installation manager. UpdateReady { version: String, install_command: String, }, /// Remote agent detection manifest update check finished. AgentDetectionManifestsUpdated { updated: Vec, activated: Vec, status: crate::detect::manifest_update::ManifestUpdateStatus, }, /// A pane child emitted one or more executable BEL characters. /// The host-facing process forwards them to its outer terminal. TerminalBell { pane_id: PaneId, count: u16 }, /// A pane child emitted a valid OSC 52 clipboard write. The main loop /// re-emits it through herdr's own clipboard writer. ClipboardWrite { content: Vec }, /// A pane child reported its shell current directory through terminal /// metadata such as OSC 7. TerminalCwdReported { pane_id: PaneId, cwd: std::path::PathBuf, }, /// Background git status refresh completed for workspaces. GitStatusRefreshed { results: Vec, cache_updates: Vec<(std::path::PathBuf, GitStatusCacheEntry)>, }, /// A configured tab bar status command finished. TabBarCommandFinished { generation: u64, segment_index: usize, result: Result, String>, }, /// A plugin action or event command finished. PluginCommandFinished { log_id: String, finished_unix_ms: u64, exit_code: Option, stdout: String, stderr: String, error: Option, }, /// Background `git worktree add` completed. WorktreeAddFinished(Box), /// Background `git worktree remove` completed. WorktreeRemoveFinished(Box), /// Background worktree discovery completed for an API list/open request. WorktreeReadFinished(Box), }