use std::path::PathBuf;
use std::time::Instant;
use crossterm::event::{KeyEvent, MouseEvent};
use crate::types::GeneratedMessage;
use super::state::{Mode, PanelId};
#[derive(Debug, Clone)]
pub enum StudioEvent {
KeyPressed(KeyEvent),
Mouse(MouseEvent),
SwitchMode(Mode),
FocusPanel(PanelId),
FocusNext,
FocusPrev,
GenerateCommit {
instructions: Option<String>,
preset: String,
use_gitmoji: bool,
amend: bool,
},
ToggleAmendMode,
GenerateReview { from_ref: String, to_ref: String },
GeneratePR { base_branch: String, to_ref: String },
GenerateChangelog { from_ref: String, to_ref: String },
GenerateReleaseNotes { from_ref: String, to_ref: String },
ChatMessage(String),
AgentStarted { task_type: TaskType },
AgentProgress {
task_type: TaskType,
tool_name: String,
message: String,
},
AgentComplete {
task_type: TaskType,
result: AgentResult,
},
AgentError { task_type: TaskType, error: String },
StreamingChunk {
task_type: TaskType,
chunk: String,
aggregated: String,
},
StreamingComplete { task_type: TaskType },
StatusMessage(crate::agents::StatusMessage),
UpdateContent {
content_type: ContentType,
content: ContentPayload,
},
LoadData {
data_type: DataType,
from_ref: Option<String>,
to_ref: Option<String>,
},
StageFile(PathBuf),
UnstageFile(PathBuf),
FileStaged(PathBuf),
FileUnstaged(PathBuf),
RefreshGitStatus,
GitStatusRefreshed,
SelectFile(PathBuf),
FileLogLoaded {
file: PathBuf,
entries: Vec<crate::studio::state::FileLogEntry>,
},
FileLogLoading(PathBuf),
GlobalLogLoaded {
entries: Vec<crate::studio::state::FileLogEntry>,
},
GlobalLogLoading,
ToggleGlobalLog,
OpenModal(ModalType),
CloseModal,
ModalConfirmed {
modal_type: ModalType,
data: Option<String>,
},
Notify {
level: NotificationLevel,
message: String,
},
Scroll {
direction: ScrollDirection,
amount: usize,
},
ToggleEditMode,
NextMessageVariant,
PrevMessageVariant,
CopyToClipboard(String),
SetPreset(String),
ToggleGitmoji,
SetEmoji(String),
Quit,
Tick,
CompanionFileCreated(PathBuf),
CompanionFileModified(PathBuf),
CompanionFileDeleted(PathBuf),
CompanionGitRefChanged,
CompanionWatcherError(String),
CompanionBranchSwitch {
branch: String,
welcome_message: Option<String>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TaskType {
Commit,
Review,
PR,
Changelog,
ReleaseNotes,
Chat,
SemanticBlame,
}
impl std::fmt::Display for TaskType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Commit => write!(f, "commit"),
Self::Review => write!(f, "review"),
Self::PR => write!(f, "pr"),
Self::Changelog => write!(f, "changelog"),
Self::ReleaseNotes => write!(f, "release_notes"),
Self::Chat => write!(f, "chat"),
Self::SemanticBlame => write!(f, "semantic_blame"),
}
}
}
#[derive(Debug, Clone)]
pub enum AgentResult {
CommitMessages(Vec<GeneratedMessage>),
ReviewContent(String),
PRContent(String),
ChangelogContent(String),
ReleaseNotesContent(String),
ChatResponse(String),
SemanticBlame(SemanticBlameResult),
}
#[derive(Debug, Clone)]
pub struct SemanticBlameResult {
pub file: PathBuf,
pub start_line: usize,
pub end_line: usize,
pub commit_hash: String,
pub author: String,
pub commit_date: String,
pub commit_message: String,
pub explanation: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ContentType {
CommitMessage,
PRDescription,
CodeReview,
Changelog,
ReleaseNotes,
}
impl std::fmt::Display for ContentType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CommitMessage => write!(f, "commit_message"),
Self::PRDescription => write!(f, "pr_description"),
Self::CodeReview => write!(f, "code_review"),
Self::Changelog => write!(f, "changelog"),
Self::ReleaseNotes => write!(f, "release_notes"),
}
}
}
#[derive(Debug, Clone)]
pub enum ContentPayload {
Commit(GeneratedMessage),
Markdown(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataType {
GitStatus,
CommitDiff,
ReviewDiff,
PRDiff,
ChangelogCommits,
ReleaseNotesCommits,
ExploreFiles,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ModalType {
Help,
Chat,
Settings,
PresetSelector,
EmojiSelector,
RefSelector { field: RefField },
ConfirmCommit,
ConfirmAmend,
ConfirmQuit,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RefField {
From,
To,
Base,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NotificationLevel {
Info,
Success,
Warning,
Error,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScrollDirection {
Up,
Down,
PageUp,
PageDown,
Top,
Bottom,
}
#[derive(Debug, Clone)]
pub enum SideEffect {
SpawnAgent { task: AgentTask },
LoadData {
data_type: DataType,
from_ref: Option<String>,
to_ref: Option<String>,
},
GitStage(PathBuf),
GitUnstage(PathBuf),
GitStageAll,
GitUnstageAll,
SaveSettings,
RefreshGitStatus,
CopyToClipboard(String),
ExecuteCommit { message: String },
ExecuteAmend { message: String },
#[allow(dead_code)] ShowNotification {
level: NotificationLevel,
message: String,
duration_ms: u64,
},
#[allow(dead_code)] Redraw,
Quit,
GatherBlameAndSpawnAgent {
file: PathBuf,
start_line: usize,
end_line: usize,
},
LoadFileLog(PathBuf),
LoadGlobalLog,
}
#[derive(Debug, Clone)]
pub struct BlameInfo {
pub file: PathBuf,
pub start_line: usize,
pub end_line: usize,
pub commit_hash: String,
pub author: String,
pub commit_date: String,
pub commit_message: String,
pub code_content: String,
}
#[derive(Debug, Clone)]
pub enum AgentTask {
Commit {
instructions: Option<String>,
preset: String,
use_gitmoji: bool,
amend: bool,
},
Review {
from_ref: String,
to_ref: String,
},
PR {
base_branch: String,
to_ref: String,
},
Changelog {
from_ref: String,
to_ref: String,
},
ReleaseNotes {
from_ref: String,
to_ref: String,
},
Chat {
message: String,
context: ChatContext,
},
#[allow(dead_code)]
SemanticBlame {
blame_info: BlameInfo,
},
}
#[derive(Debug, Clone, Default)]
pub struct ChatContext {
pub mode: Mode,
pub current_content: Option<String>,
#[allow(dead_code)] pub diff_summary: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EventSource {
User,
Agent,
Tool,
System,
}
#[derive(Debug, Clone)]
pub struct TimestampedEvent {
pub timestamp: Instant,
pub source: EventSource,
pub event: StudioEvent,
}
impl TimestampedEvent {
pub fn user(event: StudioEvent) -> Self {
Self {
timestamp: Instant::now(),
source: EventSource::User,
event,
}
}
pub fn agent(event: StudioEvent) -> Self {
Self {
timestamp: Instant::now(),
source: EventSource::Agent,
event,
}
}
pub fn tool(event: StudioEvent) -> Self {
Self {
timestamp: Instant::now(),
source: EventSource::Tool,
event,
}
}
pub fn system(event: StudioEvent) -> Self {
Self {
timestamp: Instant::now(),
source: EventSource::System,
event,
}
}
}