"""信号源接入编排服务。""" from __future__ import annotations import asyncio import hashlib import json import re import time from datetime import datetime, timezone from types import SimpleNamespace from typing import Any, Optional from uuid import uuid4 from sqlalchemy import and_, select from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession from ....config.ai_prompts import ( PROMPT_AI_WORKER_SIGNAL_SOURCE_EXECUTION, PROMPT_SIGNAL_SOURCE_ONBOARDING, ) from ....models import ( AIWorkerExecution, Project, Signal, SignalSourceRegistry, User, ) from ....core.database import AsyncSessionLocal from ...ai_orchestration_run import AIOrchestrationRunService from ...model.prompt_profile import prompt_profile_service from ...llm_service import llm_service from ....utils.timezone import now_cn_naive SOURCE_ONBOARDING_ACTION_RE = re.compile( r"(新增|增加|添加|接入|配置|注册|建立|加个|加一个|加).{0,8}(信号源|来源|监控源|channel|source|webhook|飞书|github|url|rss)", re.IGNORECASE, ) SOURCE_KIND_HINTS: tuple[tuple[str, tuple[str, ...]], ...] = ( ("feishu", ("飞书", "lark", "群聊", "chat")), ("github", ("github", "repo", "仓库", "pull request", "issue")), ("webhook", ("webhook", "回调", "回传")), ("url", ("url", "链接", "网页", "站点", "rss")), ("browser", ("浏览器", "标签页", "页面")), ("pmflow", ("pmflow", "内置ai", "ai管家", "steward")), ) DEFAULT_WORKER_ROLE_KEYS = ("pm_dispatcher", "tech_architect", "delivery_coach") MAX_SOURCE_NAME_LEN = 120 MAX_SOURCE_IDENTIFIER_LEN = 180 WORKER_MAX_CONCURRENCY = 3 COMPLETE_WORKER_WAIT_TIMEOUT_SECONDS = 6.0 def _utc_now_naive() -> datetime: return now_cn_naive() __all__ = [name for name in globals() if not name.startswith("__")]