b90f48e
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<String>,
#[serde(default)]
trace: Option<String>,
#[serde(default)]
request_id: Option<String>,
},
CommitReview {
job_id: Uuid,
repo_id: Uuid,
commit_sha: String,
#[serde(default)]
language: Option<String>,
#[serde(default)]
trace: Option<String>,
#[serde(default)]
request_id: Option<String>,
},
RepoSummary {
job_id: Uuid,
repo_id: Uuid,
head_sha: String,
base_sha: Option<String>,
limit: Option<u64>,
#[serde(default)]
language: Option<String>,
#[serde(default)]
trace: Option<String>,
#[serde(default)]
request_id: Option<String>,
},
ReleaseNotes {
job_id: Uuid,
repo_id: Uuid,
release_id: Uuid,
tag_name: String,
from_sha: Option<String>,
to_sha: String,
#[serde(default)]
language: Option<String>,
#[serde(default)]
trace: Option<String>,
#[serde(default)]
request_id: Option<String>,
},
}
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<Uuid> {
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<String> {
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<Vec<u8>, serde_json::Error> {
serde_json::to_vec(self)
}
pub fn decode(payload: &[u8]) -> Result<Self, serde_json::Error> {
serde_json::from_slice(payload)
}
#[must_use]
pub fn trace(&self) -> Option<&str> {
match self {
Self::PullReview { trace, .. }
| Self::CommitReview { trace, .. }
| Self::RepoSummary { trace, .. }
| Self::ReleaseNotes { trace, .. } => trace.as_deref(),
}
}
#[must_use]
pub fn request_id(&self) -> Option<&str> {
match self {
Self::PullReview { request_id, .. }
| Self::CommitReview { request_id, .. }
| Self::RepoSummary { request_id, .. }
| Self::ReleaseNotes { request_id, .. } => request_id.as_deref(),
}
}
}