export type AgentRole = 'frontend' | 'backend' | 'ui' | 'testing'; export type AgentDecomposeTarget = 'all' | 'dev_tasks' | 'test_cases'; export type AgentTaskCategoryCode = | 'frontend_development' | 'frontend_interaction' | 'backend_development' | 'backend_api' | 'database_schema' | 'api_integration' | 'test_functional' | 'test_ui_interaction' | 'test_form_validation' | 'test_api' | 'test_data_consistency' | 'test_permission' | 'test_exception' | 'test_boundary' | 'test_state_flow' | 'test_compatibility' | 'test_regression' | 'data_processing' | 'implementation_support' | 'documentation'; export type AgentReferenceType = 'requirement' | 'prototype_note'; export interface AgentReference { type: AgentReferenceType; id: string; label: string; } export interface AgentDevTaskDraft { title: string; description: string; taskTypeName: string; categoryCode?: AgentTaskCategoryCode | string; priority: 'P0' | 'P1' | 'P2' | 'P3'; aiEstimateHours: number; requirementName?: string; recommendedAssigneeName?: string; recommendedAssigneeReason?: string; references: AgentReference[]; } export interface AgentTestCaseDraft { title: string; description: string; taskTypeName: string; categoryCode?: AgentTaskCategoryCode | string; priority: 'P0' | 'P1' | 'P2' | 'P3'; aiEstimateHours: number; requirementName?: string; recommendedAssigneeName?: string; recommendedAssigneeReason?: string; references: AgentReference[]; } export interface AgentDecomposeReport { matched: Array<{ reqId: string; noteIds: string[]; taskCount: number }>; reqOnly: string[]; prototypeOnly: Array<{ requirementName: string; noteIds: string[]; taskCount: number }>; noteOnly?: string[]; ambiguous: Array<{ noteId: string; reason: string }>; } export interface AgentDecomposeResult { report: AgentDecomposeReport; devTaskDrafts: AgentDevTaskDraft[]; testCaseDrafts: AgentTestCaseDraft[]; } export interface AgentDecomposeRequirement { id: string; code: string; title: string; description?: string; } export interface AgentDecomposeMember { name: string; role: string; } /** * 前端发往后端的请求体 */ export interface AgentDecomposeRequest { prototypeUrl: string; requirements: AgentDecomposeRequirement[]; members: AgentDecomposeMember[]; versionId: string; planId: string; target?: AgentDecomposeTarget; } /** * 后端响应体(成功) */ export interface AgentDecomposeResponse { ok: true; result: AgentDecomposeResult; meta: { model: string; inputTokens: number; outputTokens: number; durationMs: number; }; } /** * 后端响应体(失败) */ export interface AgentDecomposeError { ok: false; error: string; code: 'PROTOTYPE_FETCH_FAILED' | 'EMPTY_REQUIREMENTS' | 'API_ERROR' | 'PARSE_ERROR' | 'NO_PROVIDER' | 'UNKNOWN'; } export interface AgentRiskReason { key: string; label: string; severity: 'low' | 'medium' | 'high' | 'critical'; detail: string; } export interface AgentRiskInterpretRequest { versionId: string; versionName: string; productName?: string; projectName?: string; riskScore: number; riskLevel: 'on_track' | 'attention' | 'at_risk' | 'likely_delayed' | 'blocked'; expectedReleaseDate?: string | null; forecastReleaseDate?: string; delayDays: number; confidence: number; signals: { unfinishedCount: number; openBugCount: number; criticalBugCount: number; failedTestCount: number; blockedCount: number; silentRiskCount: number; daysToExpectedRelease?: number; }; trendSummary: string; reasons: AgentRiskReason[]; silentRisks: Array<{ key: string; days?: number; detail: string }>; dailyEvidence: { todayDeliveries: string[]; todayProgress: string[]; todayCreations: string[]; todayRisks: string[]; progressNotes: string[]; needsProgressItems: string[]; recentActivityCount: number; totalActivityCount: number; todayActualHours: number; lastActivityAt?: string; }; } export interface AgentRiskInsight { summary: string; why: string[]; forecast: string; recommendedReleaseWindow?: string; suggestedActions: string[]; ownerHints: string[]; generatedAt: string; } export interface AgentRiskInterpretResponse { ok: true; result: AgentRiskInsight; meta: { model: string; inputTokens: number; outputTokens: number; durationMs: number; }; } export interface AgentRiskInterpretError { ok: false; error: string; code: 'API_ERROR' | 'PARSE_ERROR' | 'NO_PROVIDER' | 'UNKNOWN'; } /* ───────────────────────── AI Provider 配置 ─────────────────────────── */ export type AiProviderFormat = 'anthropic' | 'openai'; /** * 单个提供商配置(写入侧,含完整 apiKey) */ export interface AiProviderConfig { id: string; // 用户给的唯一 id(如 'anthropic-official' / 'ikuncode') name: string; // 显示名("Anthropic 官方" / "ikuncode") format: AiProviderFormat; baseURL: string; // 'https://api.anthropic.com' 或中转站 URL apiKey: string; // 完整 Key(仅服务端持有) model: string; // 该提供商上使用的模型 ID remark?: string; createdAt: string; } /** * 提供商公开视图(前端只能拿到这个,apiKey 已脱敏) */ export interface AiProviderPublic { id: string; name: string; format: AiProviderFormat; baseURL: string; keyMask: string; // 脱敏后的 key(如 sk-ant...xxxx) model: string; remark?: string; createdAt: string; isActive: boolean; } /** * AI 配置整体(写入侧) */ export interface AiConfigStored { providers: AiProviderConfig[]; activeProviderId?: string; updatedAt?: string; updatedBy?: string; } /** * AI 配置公开视图(前端用) */ export interface AiConfigPublic { providers: AiProviderPublic[]; activeProviderId?: string; updatedAt?: string; updatedBy?: string; } /** * 创建 / 更新 提供商 入参 */ export interface AiProviderUpsertInput { id: string; name: string; format: AiProviderFormat; baseURL: string; apiKey?: string; // 编辑时若不传则保留原 key model: string; remark?: string; }