fad06fd
/**
* AI domain: PR / commit 评审与行级发现的读写。
*
* 仓库级总结在 `entities/repo` 中(它属于仓库而非 PR);本文件只覆盖
* 合并请求与其提交的评审表面。
*/
import Apis from '@/shared/api'
import { getLocale, translate } from '@/shared/i18n'
import { unwrapApi } from '@/shared/lib'
import type {
AppResponseData_AiReviewDto,
AppResponseData_AiReviewJobDto,
AppResponseData_Vec_AiReviewDto,
AppResponseData_Vec_CommitAiReviewDto,
AppResponseData_Vec_LanguageOptionDto,
} from '@/shared/api'
export type PullAiReview = NonNullable<AppResponseData_AiReviewDto['data']>
export type PullAiReviewJob = NonNullable<AppResponseData_AiReviewJobDto['data']>
export type CommitAiReview = NonNullable<
NonNullable<AppResponseData_Vec_CommitAiReviewDto['data']>[number]
>
export type AiFinding = PullAiReview['findings'][number]
/** 手动(重跑)PR 的 AI 评审。 */
export const triggerPullAiReview = (
ref: { space: string; repo: string; pull: string },
language?: string,
) =>
unwrapApi<PullAiReviewJob>(
Apis.ai.trigger_ai_review({
pathParams: { space_name: ref.space, repo_name: ref.repo, pull_ref: ref.pull },
// 显式传语言可覆盖触发者的偏好;省略则服务端按用户偏好解析。
data: language ? { language } : {},
}),
)
export const listPullAiReviews = (ref: { space: string; repo: string; pull: string }) =>
unwrapApi<NonNullable<AppResponseData_Vec_AiReviewDto['data']>>(
Apis.ai.list_ai_reviews({
pathParams: { space_name: ref.space, repo_name: ref.repo, pull_ref: ref.pull },
}),
)
export const getPullAiReview = (
ref: { space: string; repo: string; pull: string },
reviewId: string,
) =>
unwrapApi<PullAiReview>(
Apis.ai.get_ai_review({
pathParams: {
space_name: ref.space,
repo_name: ref.repo,
pull_ref: ref.pull,
review_id: reviewId,
},
}),
)
/** 提交级 AI 评审(提交页与仓库页共用)。 */
export const triggerCommitAiReview = (
space: string,
repo: string,
revision?: string,
language?: string,
) =>
unwrapApi<PullAiReviewJob>(
Apis.ai.trigger_commit_ai_review({
pathParams: { space_name: space, repo_name: repo },
data: { revision: revision || null, language: language || null },
}),
)
export const listCommitAiReviews = (space: string, repo: string, revision: string) =>
unwrapApi<CommitAiReview[]>(
Apis.ai.list_commit_ai_reviews({
pathParams: { space_name: space, repo_name: repo, revision },
}),
)
export function aiReviewVerdictLabel(verdict: PullAiReview['verdict']): string {
return verdict === 'changes_requested'
? translate(getLocale(), 'pull.ai.verdict.changesRequested')
: translate(getLocale(), 'pull.ai.verdict.commented')
}
export function severityTone(severity?: string | null): string {
switch ((severity || 'minor').toLowerCase()) {
case 'critical':
return 'text-[#b42318] bg-[rgba(242,63,67,0.10)]'
case 'major':
return 'text-[#8a6100] bg-[rgba(240,178,50,0.16)]'
default:
return 'text-shell-ink-muted bg-shell-active'
}
}
/** 可选输出语言(`auto` = 沿用代码注释的语言)。 */
export type LanguageOption = NonNullable<
NonNullable<AppResponseData_Vec_LanguageOptionDto['data']>[number]
>
export const listAiLanguages = () =>
unwrapApi<LanguageOption[]>(Apis.ai.list_ai_languages({}))
/** 语言显示名:本语名优先,`auto` 用调用方给的文案。 */
export const languageLabel = (
option: LanguageOption,
autoLabel = translate(getLocale(), 'pull.ai.autoLanguage'),
) =>
option.auto ? autoLabel : option.native_name