From b6b7ebf44f9451eee70794e887443fc8b6c0c7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=80=82?= Date: Wed, 8 Jul 2026 20:56:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(ai-analysis):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E5=88=86=E6=9E=90=E5=85=B1=E4=BA=AB=E5=A5=91?= =?UTF-8?q?=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/shared/src/analysis.ts | 238 ++++++++++++++++++++++++++++++++ packages/shared/src/index.ts | 1 + 2 files changed, 239 insertions(+) create mode 100644 packages/shared/src/analysis.ts diff --git a/packages/shared/src/analysis.ts b/packages/shared/src/analysis.ts new file mode 100644 index 0000000..c24f654 --- /dev/null +++ b/packages/shared/src/analysis.ts @@ -0,0 +1,238 @@ +export type AnalysisSurface = 'ai_assistant' | 'product_detail' | 'project_detail' | 'version_detail'; + +export type MetricId = + | 'version_risk_score' + | 'completion_trend' + | 'overdue_item_count' + | 'requirement_status_count' + | 'requirement_completion_count' + | 'requirement_source_count' + | 'department_workload' + | 'member_pending_work' + | 'member_effort_hours' + | 'bug_severity_count' + | 'test_pass_rate' + | 'overtime_reason_hours' + | 'delay_rate' + | 'delay_reason_count'; + +export type DimensionId = + | 'product' + | 'project' + | 'version' + | 'requirement_status' + | 'requirement_type' + | 'requirement_source' + | 'department' + | 'member' + | 'role' + | 'month' + | 'week' + | 'day' + | 'bug_severity' + | 'bug_status' + | 'test_status' + | 'delay_reason'; + +export type AnalysisType = + | 'ranking' + | 'trend' + | 'comparison' + | 'distribution' + | 'composition' + | 'correlation' + | 'breakdown' + | 'summary'; + +export type TimePolicy = 'current_state' | 'last_30_days' | 'lifecycle' | 'user_required' | 'explicit_range'; + +export type ChartKind = + | 'number_card' + | 'line_area' + | 'horizontal_bar' + | 'stacked_horizontal_bar' + | 'donut' + | 'table_preview'; + +export interface MetricRef { + metricId: MetricId; + version: number; +} + +export interface MetricDefinition { + metricId: MetricId; + version: number; + name: string; + description: string; + formula: string; + owner: string; + supportedDimensions: DimensionId[]; + supportedAnalysisTypes: AnalysisType[]; + defaultChart: ChartKind; + defaultDimension?: DimensionId; + defaultTimePolicy: TimePolicy; + status: 'active' | 'deprecated'; +} + +export type DataScope = + | { type: 'self'; userId: string } + | { type: 'managed_projects'; projectIds: string[] } + | { type: 'product'; productId: string } + | { type: 'project'; projectId: string } + | { type: 'version'; versionId: string } + | { type: 'system'; reason: 'admin' | 'management_permission' }; + +export interface AnalysisPlan { + metricRef: MetricRef; + analysisType: AnalysisType; + dimensions: DimensionId[]; + timeRange?: { + start: string; + end: string; + policy: TimePolicy; + }; + filters: Record; + scope: DataScope; + limit?: number; + sort?: Array<{ field: string; direction: 'asc' | 'desc' }>; +} + +export interface EvidenceItem { + label: string; + value: string | number; + unit?: string; + sourceDomain: + | 'product' + | 'project' + | 'version' + | 'requirement' + | 'version_plan' + | 'dev_task' + | 'test_case' + | 'bug' + | 'work_activity' + | 'task_worklog' + | 'overtime' + | 'xiaobao'; + sourceLabel?: string; + drilldown?: { + type: 'list' | 'detail'; + target: string; + filters: Record; + }; +} + +export interface MetricResult { + metricRef: MetricRef; + analysisType: AnalysisType; + columns: Array<{ id: string; label: string; type: 'string' | 'number' | 'date' | 'percent' }>; + rows: Array>; + totals?: Record; + comparison?: { + baselineLabel: string; + currentLabel: string; + deltaValue?: number; + deltaPercent?: number; + }; + evidence: EvidenceItem[]; + dataScope: DataScope; + generatedAt: string; +} + +export interface UnifiedChartSpec { + kind: ChartKind; + title: string; + subtitle?: string; + dataset: { + source: Array>; + x?: string; + y?: string; + series?: string; + value?: string; + label?: string; + }; + encoding: { + x?: { field: string; label: string }; + y?: { field: string; label: string }; + value?: { field: string; label: string; unit?: string }; + color?: { mode: 'single' | 'risk' | 'semantic'; field?: string }; + }; + annotations?: Array<{ + type: 'outlier' | 'peak' | 'target' | 'threshold'; + label: string; + value?: string | number; + field?: string; + }>; + stylePreset: 'apple_vision_light' | 'apple_vision_dark'; +} + +export interface InsightCard { + summary: string; + primaryValue?: { + label: string; + value: string | number; + unit?: string; + }; + comparison?: { + label: string; + direction: 'up' | 'down' | 'flat'; + value: string | number; + tone: 'positive' | 'negative' | 'neutral'; + }; + semanticConfidence: 'high' | 'medium' | 'low'; + dataConfidence: 'sufficient' | 'partial' | 'insufficient'; +} + +export interface AnalysisReport { + summary: string; + keyFindings: string[]; + evidence: EvidenceItem[]; + suggestions: string[]; + dataScope: { + timeDescription: string; + permissionDescription: string; + metricFormulaDescription: string; + generatedAt: string; + }; +} + +export type FollowUp = + | { type: 'question'; label: string; prompt: string } + | { type: 'drilldown'; label: string; target: string; filters: Record } + | { type: 'export'; label: string; format: 'png' | 'pdf' | 'csv' }; + +export interface AnalysisRequest { + question: string; + context?: { + surface: AnalysisSurface; + productId?: string; + projectId?: string; + versionId?: string; + }; +} + +export type AnalysisErrorCode = + | 'NO_PERMISSION' + | 'UNSUPPORTED_ANALYSIS' + | 'AMBIGUOUS_INTENT' + | 'NO_DATA' + | 'AI_UNAVAILABLE' + | 'INVALID_PLAN'; + +export type AnalysisResponse = + | { + ok: true; + plan: AnalysisPlan; + metricResult: MetricResult; + insight: InsightCard; + chart: UnifiedChartSpec; + report: AnalysisReport; + followUps: FollowUp[]; + } + | { + ok: false; + code: AnalysisErrorCode; + message: string; + clarificationOptions?: Array<{ label: string; prompt: string }>; + dataScope?: DataScope; + }; diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index b57aca8..afc11ba 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,3 +1,4 @@ export * from './enums'; export * from './types'; export * from './agent'; +export * from './analysis';