198 lines
6.4 KiB
Python
198 lines
6.4 KiB
Python
from __future__ import annotations
|
||
|
||
from .shared import *
|
||
from .helpers import _utc_now_naive
|
||
|
||
@router.get("/stats")
|
||
async def get_ai_steward_stats(
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
获取 AI Steward 统计数据
|
||
|
||
展示 AI 为团队节省的工作量:
|
||
- 自动捕获的信号数
|
||
- 避免的认知冲突数
|
||
- 自动解决的阻塞数
|
||
- 节省的会议时间(小时)
|
||
"""
|
||
from ..models import Signal, CognitiveConflict
|
||
from sqlalchemy import func, text
|
||
|
||
# 统计信号数量
|
||
week_ago = _utc_now_naive() - timedelta(days=7)
|
||
month_ago = _utc_now_naive() - timedelta(days=30)
|
||
|
||
signal_result = await db.execute(
|
||
select(func.count(Signal.id)).where(
|
||
Signal.tenant_id == tenant_id,
|
||
Signal.created_at >= week_ago
|
||
)
|
||
)
|
||
signals_captured = signal_result.scalar() or 0
|
||
|
||
# 统计高影响信号
|
||
high_impact_result = await db.execute(
|
||
select(func.count(Signal.id)).where(
|
||
Signal.tenant_id == tenant_id,
|
||
Signal.impact_score >= 0.8,
|
||
Signal.created_at >= week_ago
|
||
)
|
||
)
|
||
high_impact_count = high_impact_result.scalar() or 0
|
||
|
||
# 统计认知冲突
|
||
conflict_result = await db.execute(
|
||
select(func.count(CognitiveConflict.id)).where(
|
||
CognitiveConflict.tenant_id == tenant_id,
|
||
CognitiveConflict.status.in_(['detected', 'active'])
|
||
)
|
||
)
|
||
active_conflicts = conflict_result.scalar() or 0
|
||
|
||
# 统计已解决的冲突
|
||
resolved_conflict_result = await db.execute(
|
||
select(func.count(CognitiveConflict.id)).where(
|
||
CognitiveConflict.tenant_id == tenant_id,
|
||
CognitiveConflict.status == 'resolved',
|
||
CognitiveConflict.resolved_at >= month_ago
|
||
)
|
||
)
|
||
conflicts_resolved = resolved_conflict_result.scalar() or 0
|
||
|
||
# 统计阻塞
|
||
blocker_result = await db.execute(
|
||
text("""
|
||
SELECT COUNT(*) FROM cognitive_conflicts
|
||
WHERE tenant_id = :tenant_id
|
||
AND conflict_type IN ('code_blocker', 'task_blocker')
|
||
AND status = 'detected'
|
||
"""),
|
||
{"tenant_id": tenant_id}
|
||
)
|
||
active_blockers = blocker_result.scalar() or 0
|
||
|
||
# 活跃项目数
|
||
from ..models import Project
|
||
project_result = await db.execute(
|
||
select(func.count(Project.id)).where(
|
||
Project.tenant_id == tenant_id,
|
||
Project.status == 'active'
|
||
)
|
||
)
|
||
active_projects = project_result.scalar() or 0
|
||
|
||
# 估算节省时间(每个冲突/阻塞避免约2小时会议)
|
||
hours_saved = conflicts_resolved * 2
|
||
|
||
stats = {
|
||
'signals_captured': signals_captured,
|
||
'high_impact_signals': high_impact_count,
|
||
'active_conflicts': active_conflicts,
|
||
'conflicts_resolved': conflicts_resolved,
|
||
'active_blockers': active_blockers,
|
||
'active_projects': active_projects,
|
||
'hours_saved': hours_saved,
|
||
'last_updated': now_cn_aware().isoformat()
|
||
}
|
||
|
||
return stats
|
||
|
||
@router.get("/config/suggest")
|
||
async def get_ai_config_suggestion(
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
AI 建议配置方案
|
||
|
||
根据团队现状,智能推荐应该优先配置哪些集成源
|
||
"""
|
||
from ..models import Integration, Project, Signal
|
||
from sqlalchemy.future import select
|
||
from sqlalchemy import func
|
||
|
||
# 检查已配置的集成
|
||
configured_sources = []
|
||
|
||
# 检查飞书配置
|
||
feishu_result = await db.execute(
|
||
select(Integration).where(
|
||
Integration.tenant_id == tenant_id,
|
||
Integration.type == 'feishu',
|
||
Integration.is_active == True
|
||
)
|
||
)
|
||
if feishu_result.scalar_one_or_none():
|
||
configured_sources.append('feishu')
|
||
|
||
# 检查活跃项目数
|
||
project_result = await db.execute(
|
||
select(func.count(Project.id)).where(
|
||
Project.tenant_id == tenant_id,
|
||
Project.status == 'active'
|
||
)
|
||
)
|
||
active_projects = project_result.scalar() or 0
|
||
|
||
# 检查近期信号数量
|
||
signal_result = await db.execute(
|
||
select(func.count(Signal.id)).where(
|
||
Signal.tenant_id == tenant_id,
|
||
Signal.created_at >= (_utc_now_naive() - timedelta(days=7))
|
||
)
|
||
)
|
||
recent_signals = signal_result.scalar() or 0
|
||
|
||
# AI 分析并推荐配置
|
||
recommended = []
|
||
reasoning_parts = []
|
||
|
||
# 根据项目数量推荐
|
||
if active_projects > 0:
|
||
if 'feishu' not in configured_sources:
|
||
recommended.append('feishu')
|
||
reasoning_parts.append(f"您有 {active_projects} 个活跃项目,建议配置飞书群聊集成以自动捕获需求讨论")
|
||
|
||
# 根据信号量推荐
|
||
if recent_signals < 10:
|
||
if 'hn' not in [s.split('_')[0] for s in configured_sources]:
|
||
recommended.append('hn')
|
||
reasoning_parts.append("近期信号较少,建议启用 HackerNews 监控获取更多技术趋势")
|
||
|
||
# 默认推荐
|
||
if not recommended:
|
||
if 'feishu' not in configured_sources:
|
||
recommended.append('feishu')
|
||
if 'hn' not in [s.split('_')[0] for s in configured_sources]:
|
||
recommended.append('hn')
|
||
reasoning_parts.append("建议配置基础集成源以启动 AI 主动捕获能力")
|
||
|
||
reasoning = ";".join(reasoning_parts) if reasoning_parts else "所有基础集成已配置,AI 主动捕获能力已全面启用"
|
||
|
||
# 估算影响
|
||
impact_levels = {
|
||
0: "暂无明显影响",
|
||
1: "预计每周节省 2 小时手动录入时间",
|
||
2: "预计每周节省 4 小时手动录入时间,捕获 10+ 个需求信号",
|
||
3: "预计每周节省 6 小时会议时间,自动对齐 5+ 个认知冲突",
|
||
4: "预计每周节省 8 小时会议时间,主动捕获 20+ 个需求信号"
|
||
}
|
||
impact = impact_levels.get(len(recommended), impact_levels[4])
|
||
|
||
return {
|
||
'recommended_sources': recommended,
|
||
'reasoning': reasoning,
|
||
'estimated_impact': impact,
|
||
'current_config': {
|
||
'feishu_configured': 'feishu' in configured_sources,
|
||
'hn_configured': any('hn' in s for s in configured_sources),
|
||
'github_configured': any('github' in s for s in configured_sources),
|
||
'browser_installed': False # 需要前端检测
|
||
}
|
||
}
|
||
|