AgentEvalTool/frontend/web/src/api/campaigns.ts
sinohqb eca7ccebe2 refactor(api): api.ts 拆分为 10 个域模块(Phase 4.22)
909 行的单文件 api.ts 按域拆为 10 个模块 + 共享 client;barrel
保持 import from '../api' 不变,调用点零改动。

- api/client.ts:axios 实例 + 拦截器 + authToken + setOnUnauthorized
  (唯一住处)。
- 10 个域模块:auth / targets / scenarios / modelConfigs / runs /
  reports / stats / campaigns / intelligentEvals / files,每个
  自包含类型声明与 API 方法。
- api/index.ts:barrel 再导出,调用点 import 路径全部不变。
- 原 api.ts 中的 Blob 导出仪式已在 Commit 4 下沉至
  utils/download.ts,本 commit 仅做拆分与搬运。
2026-08-24 05:53:45 +08:00

292 lines
7.4 KiB
TypeScript

import api from './client'
import { downloadBlob } from '../utils/download'
export interface CampaignPlanEntry {
scenario_id: string
offset_seconds: number
count: number
}
export interface ExplorationSeeds {
personas: string[]
goals: string[]
}
export interface ExplorationBudgetConfig {
max_sessions?: number | null
max_turns?: number | null
min_interval_seconds?: number | null
}
export interface ExplorationIssueCount {
issue: string
count: number
}
export interface ExplorationJudgeReview {
reviewed_sessions: number
findings: { dimension: string; rating: string; comment: string }[]
summaries: string[]
}
export interface ExplorationSummary {
session_count: number
sessions_with_experience: number
goal_achieved_count: number
goal_achievement_rate: number | null
issues: ExplorationIssueCount[]
misled: ExplorationIssueCount[]
judge_review: ExplorationJudgeReview | null
}
export interface ExplorationExperience {
goal_achieved: boolean
blockers: string[]
misled: string[]
emotion: string
notes: string
}
export interface ExplorationSession {
id: string
campaign_id: string
target_id: string
persona: Record<string, unknown>
goal: string
seed_ref: Record<string, unknown> | null
status: string
triggered_by: string
experience: ExplorationExperience | null
judge_review: Record<string, unknown> | null
turn_count: number
error: string | null
created_at: string | null
closed_at: string | null
}
export interface ExplorationMessage {
id: string
session_id: string
round_index: number
role: string
content: string
latency_ms: number | null
created_at: string | null
}
export const explorationApi = {
listSessions: (campaignId: string) =>
api.get<{ sessions: ExplorationSession[] }>(`/exploration/campaigns/${campaignId}/sessions`),
listMessages: (sessionId: string) =>
api.get<{ messages: ExplorationMessage[] }>(`/exploration/sessions/${sessionId}/messages`),
}
export interface CampaignProgress {
current_offset_seconds: number
spawned_runs: number
completed_runs: number
}
export interface CampaignListProgress {
completed_runs: number
planned_total: number
overall_pass_rate: number | null
}
export interface Campaign {
id: string
name: string
target_id: string
window_seconds: number
time_scale: number
plan: CampaignPlanEntry[]
status: string
started_at: string | null
completed_at: string | null
summary: Record<string, unknown> | null
analysis_model_config_id: string | null
exploration_seeds: ExplorationSeeds | null
exploration_budget: ExplorationBudgetConfig | null
progress?: CampaignProgress
}
export interface CampaignListItem extends Omit<Campaign, 'progress'> {
progress: CampaignListProgress
}
export interface CampaignTrendBucket {
bucket_index: number
start_seconds: number
end_seconds: number
run_count: number
pass_rate: number | null
availability: number | null
avg_latency_ms: number | null
}
export interface CampaignCapability {
scenario_id: string
scenario_name: string
run_count: number
pass_rate: number | null
availability: number | null
avg_latency_ms: number | null
}
export interface CampaignReport {
campaign_id: string
name: string
target_id: string
status: string
window_seconds: number
time_scale: number
started_at: string | null
completed_at: string | null
summary: {
total_runs: number
completed_runs: number
overall_pass_rate: number | null
overall_availability: number | null
avg_latency_ms: number | null
}
time_trend: CampaignTrendBucket[]
capability_summary: CampaignCapability[]
exploration?: ExplorationSummary | null
}
export interface CampaignTimelineEntry {
run_id: string
scenario_id: string
scenario_name: string
offset_seconds: number
status: string
pass_rate: number | null
avg_latency_ms: number | null
started_at: string | null
}
export type CampaignAnalysisStatus = 'none' | 'queued' | 'generating' | 'completed' | 'failed'
export interface CampaignAnalysisProblem {
severity: string
title: string
description: string
scenario_ids: string[]
evidence_run_ids: string[]
}
export interface CampaignAnalysisResult {
overall: string
problems: CampaignAnalysisProblem[]
scenario_narratives: { scenario_id: string; narrative: string }[]
suggestions: { priority: number; text: string }[]
}
export interface CampaignAnalysis {
status: CampaignAnalysisStatus
result?: CampaignAnalysisResult | null
error?: string | null
model_config_id?: string | null
triggered_by?: string
updated_at?: string | null
}
export interface CreateCampaignPayload {
name: string
target_id: string
window_seconds: number
time_scale: number
plan: CampaignPlanEntry[]
analysis_model_config_id?: string | null
exploration_seeds?: ExplorationSeeds | null
exploration_budget?: ExplorationBudgetConfig | null
}
export type ComparisonTrend = 'improving' | 'stable' | 'regressing'
export interface MetricDeltaPair {
baseline: number | null
current: number | null
delta: number | null
}
export interface MetricDiffScenario {
scenario_id: string
scenario_name: string
pass_rate: MetricDeltaPair
availability: MetricDeltaPair
avg_latency_ms: MetricDeltaPair
}
export interface MetricDiff {
overall: {
pass_rate: MetricDeltaPair
availability: MetricDeltaPair
avg_latency_ms: MetricDeltaPair
}
scenarios: MetricDiffScenario[]
}
export interface ComparisonBaselineInfo {
id: string
name: string
completed_at: string | null
}
export interface ComparisonProblemEvolution {
status: string
title: string
detail: string
scenario_ids: string[]
}
export interface ComparisonSuggestionTracking {
text: string
status: string
note: string
}
export interface ComparisonResult {
trend: ComparisonTrend
summary: string
problem_evolution: ComparisonProblemEvolution[]
suggestion_tracking: ComparisonSuggestionTracking[]
}
export interface CampaignComparison {
status: CampaignAnalysisStatus
auto_baseline: ComparisonBaselineInfo | null
metric_diff: MetricDiff | null
comparison: {
baseline_campaign_id: string
baseline: ComparisonBaselineInfo | null
result: ComparisonResult | null
error: string | null
model_config_id: string | null
triggered_by: string
updated_at: string | null
} | null
}
export const campaignsApi = {
list: () => api.get<CampaignListItem[]>('/campaigns'),
get: (id: string) => api.get<Campaign>(`/campaigns/${id}`),
create: (data: CreateCampaignPayload) => api.post<Campaign>('/campaigns', data),
cancel: (id: string) => api.post<Campaign>(`/campaigns/${id}/cancel`),
report: (id: string) => api.get<CampaignReport>(`/campaigns/${id}/report`),
timeline: (id: string) =>
api.get<{ entries: CampaignTimelineEntry[] }>(`/campaigns/${id}/timeline`),
getAnalysis: (id: string) => api.get<CampaignAnalysis>(`/campaigns/${id}/analysis`),
generateAnalysis: (id: string) => api.post<{ status: string }>(`/campaigns/${id}/analysis`),
getComparison: (id: string) => api.get<CampaignComparison>(`/campaigns/${id}/comparison`),
generateComparison: (id: string, baselineCampaignId?: string) =>
api.post<{ status: string }>(
`/campaigns/${id}/comparison`,
baselineCampaignId ? { baseline_campaign_id: baselineCampaignId } : {},
),
downloadReport: async (id: string) => {
const res = await api.get(`/campaigns/${id}/report/markdown`, { responseType: 'blob' })
downloadBlob(res.data as Blob, `campaign-report-${id.slice(0, 8)}.md`)
},
}