PMFlow/backend/app/api/ai_steward_api/helpers.py

64 lines
1.9 KiB
Python

from __future__ import annotations
from .shared import *
def _utc_now_naive() -> datetime:
return now_cn_naive()
async def _ensure_project_signal_link(
db: AsyncSession,
*,
tenant_id: int,
project_id: int,
signal_id: int,
link_type: str = "related",
) -> None:
existing = (
await db.execute(
select(ProjectSignalLink.id).where(
and_(
ProjectSignalLink.tenant_id == int(tenant_id),
ProjectSignalLink.project_id == int(project_id),
ProjectSignalLink.signal_id == int(signal_id),
)
).limit(1)
)
).scalar_one_or_none()
if existing is not None:
return
db.add(
ProjectSignalLink(
tenant_id=int(tenant_id),
project_id=int(project_id),
signal_id=int(signal_id),
link_type=link_type,
relevance_score=1.0,
)
)
def _parse_related_users(raw_value: Any) -> List[str]:
"""兼容 involved_user_ids 的 list / json-string / 单值字符串。"""
if raw_value is None:
return []
if isinstance(raw_value, list):
return [str(item) for item in raw_value if item is not None]
if isinstance(raw_value, (bytes, bytearray)):
raw_value = raw_value.decode("utf-8", errors="ignore")
if isinstance(raw_value, str):
text = raw_value.strip()
if not text:
return []
try:
parsed = json.loads(text)
except (TypeError, ValueError, json.JSONDecodeError):
if "," in text:
return [v.strip() for v in text.split(",") if v.strip()]
return [text]
if isinstance(parsed, list):
return [str(item) for item in parsed if item is not None]
if parsed is None:
return []
return [str(parsed)]
return [str(raw_value)]