use serde::{Deserialize, Serialize}; use uuid::Uuid; /// AI 队列任务协议。 /// /// 定义在协议 crate 中,使生产方(git / pulls)与消费方(agent / aihost) /// 都能引用同一份载荷定义而不产生 crate 依赖环。 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum AgentTask { PullReview { job_id: Uuid, repo_id: Uuid, pull_request_id: Uuid, head_sha: String, /// 输出语言(BCP-47 或 `auto`);`None` 时用 `[ai].output_language`。 #[serde(default)] language: Option, }, CommitReview { job_id: Uuid, repo_id: Uuid, commit_sha: String, #[serde(default)] language: Option, }, RepoSummary { job_id: Uuid, repo_id: Uuid, head_sha: String, base_sha: Option, limit: Option, #[serde(default)] language: Option, }, ReleaseNotes { job_id: Uuid, repo_id: Uuid, release_id: Uuid, tag_name: String, from_sha: Option, to_sha: String, #[serde(default)] language: Option, }, } impl AgentTask { #[must_use] pub fn job_id(&self) -> Uuid { match self { Self::PullReview { job_id, .. } | Self::CommitReview { job_id, .. } | Self::RepoSummary { job_id, .. } | Self::ReleaseNotes { job_id, .. } => *job_id, } } #[must_use] pub fn repo_id(&self) -> Uuid { match self { Self::PullReview { repo_id, .. } | Self::CommitReview { repo_id, .. } | Self::RepoSummary { repo_id, .. } | Self::ReleaseNotes { repo_id, .. } => *repo_id, } } /// 稳定字符串标识,与 `ai_job.kind` 的取值一致。 #[must_use] pub fn kind_str(&self) -> &'static str { match self { Self::PullReview { .. } => "pull_review", Self::CommitReview { .. } => "commit_review", Self::RepoSummary { .. } => "repo_summary", Self::ReleaseNotes { .. } => "release_notes", } } #[must_use] pub fn target_id(&self) -> Option { match self { Self::PullReview { pull_request_id, .. } => Some(*pull_request_id), Self::ReleaseNotes { release_id, .. } => Some(*release_id), Self::CommitReview { .. } | Self::RepoSummary { .. } => None, } } /// 该任务请求的输出语言(未指定时为 `None`,由消费侧取配置缺省)。 #[must_use] pub fn language(&self) -> Option<&str> { match self { Self::PullReview { language, .. } | Self::CommitReview { language, .. } | Self::RepoSummary { language, .. } | Self::ReleaseNotes { language, .. } => language.as_deref(), } } #[must_use] pub fn target_ref(&self) -> Option { match self { Self::PullReview { head_sha, .. } => Some(head_sha.clone()), Self::CommitReview { commit_sha, .. } => Some(commit_sha.clone()), Self::RepoSummary { head_sha, .. } => Some(head_sha.clone()), Self::ReleaseNotes { tag_name, .. } => Some(tag_name.clone()), } } pub fn encode(&self) -> Result, serde_json::Error> { serde_json::to_vec(self) } pub fn decode(payload: &[u8]) -> Result { serde_json::from_slice(payload) } }