254 lines
7.7 KiB
Python
254 lines
7.7 KiB
Python
from __future__ import annotations
|
||
|
||
from .shared import *
|
||
from .helpers import _parse_related_users, _utc_now_naive
|
||
from .schemas import CognitiveConflictResponse, ConflictDetectRequest
|
||
|
||
@router.get("/cognitive-conflicts", response_model=List[CognitiveConflictResponse])
|
||
async def get_cognitive_conflicts(
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id),
|
||
project_id: Optional[int] = None
|
||
):
|
||
"""
|
||
获取认知冲突列表
|
||
|
||
AI 会自动识别团队中的隐性认知差异,例如:
|
||
- 产品说"用户留存提升10%",开发实现的是"DAU提升10%"
|
||
- 双方没有争论,但目标不一致,AI 会主动识别并推送对齐提醒
|
||
"""
|
||
from ..models import CognitiveConflict, TruthNode
|
||
from sqlalchemy.future import select
|
||
|
||
query = select(CognitiveConflict).where(
|
||
CognitiveConflict.tenant_id == tenant_id,
|
||
CognitiveConflict.status == 'active'
|
||
)
|
||
|
||
if project_id:
|
||
# 通过 truth_node 关联到项目
|
||
query = query.join(
|
||
TruthNode, CognitiveConflict.truth_node_id == TruthNode.id
|
||
).where(
|
||
TruthNode.project_id == project_id
|
||
)
|
||
|
||
result = await db.execute(query)
|
||
conflicts = result.scalars().all()
|
||
|
||
return [
|
||
CognitiveConflictResponse(
|
||
id=str(c.id),
|
||
type=c.conflict_type,
|
||
description=c.description,
|
||
severity="high" if "critical" in (c.description or "").lower() else "medium",
|
||
related_users=_parse_related_users(c.involved_user_ids),
|
||
)
|
||
for c in conflicts
|
||
]
|
||
|
||
@router.post("/conflicts/detect")
|
||
async def detect_conflicts(
|
||
request: ConflictDetectRequest,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
检测项目中的认知冲突
|
||
|
||
支持检测类型:
|
||
- all: 全部检测(宪章冲突 + 定义冲突)
|
||
- charter: 仅检测宪章中的潜在冲突
|
||
- definition: 仅检测用户定义冲突
|
||
"""
|
||
try:
|
||
service = get_cognitive_conflict_service(db)
|
||
|
||
detected_conflicts = []
|
||
|
||
if request.detect_type in ["all", "charter"]:
|
||
charter_conflicts = await service.detect_charter_conflicts(
|
||
project_id=request.project_id,
|
||
tenant_id=tenant_id
|
||
)
|
||
detected_conflicts.extend(charter_conflicts)
|
||
|
||
if request.detect_type in ["all", "definition"]:
|
||
definition_conflicts = await service.detect_user_definition_conflicts(
|
||
project_id=request.project_id,
|
||
tenant_id=tenant_id
|
||
)
|
||
detected_conflicts.extend(definition_conflicts)
|
||
|
||
return {
|
||
"project_id": request.project_id,
|
||
"detected_count": len(detected_conflicts),
|
||
"conflicts": detected_conflicts
|
||
}
|
||
except Exception as e:
|
||
raise HTTPException(status_code=500, detail=f"冲突检测失败: {str(e)}")
|
||
|
||
@router.post("/conflicts/{conflict_id}/propose-resolution")
|
||
async def propose_conflict_resolution(
|
||
conflict_id: int,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
AI 生成认知冲突解决方案
|
||
|
||
为冲突双方生成对齐方案:
|
||
1. 分析冲突根因
|
||
2. 提出妥协方案
|
||
3. 生成可执行的对齐计划
|
||
"""
|
||
try:
|
||
service = get_cognitive_conflict_service(db)
|
||
resolution = await service.propose_alignment_resolution(
|
||
conflict_id=conflict_id,
|
||
tenant_id=tenant_id
|
||
)
|
||
return resolution
|
||
except ValueError as e:
|
||
raise HTTPException(status_code=404, detail=str(e))
|
||
except Exception as e:
|
||
raise HTTPException(status_code=500, detail=f"方案生成失败: {str(e)}")
|
||
|
||
@router.post("/conflicts/{conflict_id}/align")
|
||
async def trigger_async_alignment(
|
||
conflict_id: int,
|
||
user1_id: int,
|
||
user2_id: int,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
触发异步 1v1 认知对齐
|
||
|
||
为冲突双方创建独立的对齐任务:
|
||
1. 发送对齐邀请
|
||
2. 提供背景信息
|
||
3. 收集双方观点
|
||
4. AI 生成共识方案
|
||
"""
|
||
try:
|
||
service = get_cognitive_conflict_service(db)
|
||
alignment = await service.trigger_async_alignment(
|
||
conflict_id=conflict_id,
|
||
user1_id=user1_id,
|
||
user2_id=user2_id,
|
||
tenant_id=tenant_id
|
||
)
|
||
return alignment
|
||
except ValueError as e:
|
||
raise HTTPException(status_code=404, detail=str(e))
|
||
except Exception as e:
|
||
raise HTTPException(status_code=500, detail=f"对齐触发失败: {str(e)}")
|
||
|
||
@router.post("/cognitive-conflicts/{conflict_id}/resolve")
|
||
async def resolve_cognitive_conflict(
|
||
conflict_id: int,
|
||
resolution_note: str,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
解决认知冲突
|
||
|
||
AI 会生成解决方案建议,双方确认后标记为已解决
|
||
"""
|
||
from ..models import CognitiveConflict
|
||
from sqlalchemy.future import select
|
||
|
||
result = await db.execute(
|
||
select(CognitiveConflict).where(
|
||
CognitiveConflict.id == conflict_id,
|
||
CognitiveConflict.tenant_id == tenant_id
|
||
)
|
||
)
|
||
conflict = result.scalar_one_or_none()
|
||
|
||
if not conflict:
|
||
raise HTTPException(status_code=404, detail="冲突记录不存在")
|
||
|
||
conflict.status = 'resolved'
|
||
conflict.resolved_at = _utc_now_naive()
|
||
conflict.description += f"\n\n解决方案({current_user.username}): {resolution_note}"
|
||
|
||
await db.commit()
|
||
|
||
return {"message": "冲突已标记为已解决"}
|
||
|
||
@router.get("/conflicts/task-mismatch/{task_id}")
|
||
async def check_task_charter_mismatch(
|
||
task_id: int,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
检测任务与宪章的一致性
|
||
|
||
检查:
|
||
1. 任务描述是否与宪章目标一致
|
||
2. 技术选型是否符合约束
|
||
3. 是否偏离项目方向
|
||
"""
|
||
from ..models import Task, TruthNode
|
||
from sqlalchemy.future import select
|
||
|
||
try:
|
||
# 获取任务
|
||
result = await db.execute(
|
||
select(Task).where(
|
||
Task.id == task_id,
|
||
Task.tenant_id == tenant_id
|
||
)
|
||
)
|
||
task = result.scalar_one_or_none()
|
||
|
||
if not task:
|
||
raise HTTPException(status_code=404, detail="任务不存在")
|
||
|
||
# 获取宪章
|
||
charter_result = await db.execute(
|
||
select(TruthNode).where(
|
||
TruthNode.id == task.truth_node_id,
|
||
TruthNode.tenant_id == tenant_id
|
||
)
|
||
)
|
||
charter = charter_result.scalar_one_or_none()
|
||
|
||
if not charter:
|
||
raise HTTPException(status_code=404, detail="宪章不存在")
|
||
|
||
# 检测一致性
|
||
service = get_cognitive_conflict_service(db)
|
||
mismatch = await service.detect_task_charter_mismatch(
|
||
task=task,
|
||
charter_content=charter.content,
|
||
tenant_id=tenant_id
|
||
)
|
||
|
||
if mismatch:
|
||
return {
|
||
"is_aligned": False,
|
||
"mismatch": mismatch
|
||
}
|
||
|
||
return {
|
||
"is_aligned": True,
|
||
"message": "任务与宪章一致"
|
||
}
|
||
|
||
except HTTPException:
|
||
raise
|
||
except Exception as e:
|
||
raise HTTPException(status_code=500, detail=f"一致性检测失败: {str(e)}")
|
||
|