新增 Google Chat 对接的全套工具模块,包括: - 会话线程管理、消息解析与格式化 - Pub/Sub 消息解码、提及和命令识别 - 权限审批、目录管理和审计日志 - 消息缓存、媒体上传下载和 SSFR 防护 - 策略配置、卡片构建和流式回复支持
72 lines
1.9 KiB
Python
72 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
def normalize_approver_id(raw: str) -> str:
|
|
if not raw:
|
|
return ""
|
|
if raw.startswith("users/") or raw.startswith("user:"):
|
|
return raw
|
|
if "@" in raw:
|
|
return f"users/{raw}"
|
|
return f"users/{raw}"
|
|
|
|
|
|
def resolve_approver_ids(
|
|
dm_allow_from: list[str],
|
|
default_to: str = "",
|
|
) -> list[str]:
|
|
approvers: list[str] = []
|
|
for entry in dm_allow_from:
|
|
if entry == "*":
|
|
continue
|
|
normalized = normalize_approver_id(entry)
|
|
if normalized:
|
|
approvers.append(normalized)
|
|
if not approvers and default_to:
|
|
approvers.append(normalize_approver_id(default_to))
|
|
return approvers
|
|
|
|
|
|
def build_exec_approval_context(
|
|
action_id: str,
|
|
approvers: list[str],
|
|
metadata: dict[str, Any] | None = None,
|
|
) -> dict[str, Any]:
|
|
return {
|
|
"action_id": action_id,
|
|
"approvers": approvers,
|
|
"approved_by": [],
|
|
"rejected_by": [],
|
|
"metadata": metadata or {},
|
|
}
|
|
|
|
|
|
def record_approval_decision(
|
|
context: dict[str, Any],
|
|
user_id: str,
|
|
approved: bool,
|
|
) -> bool:
|
|
normalized = normalize_approver_id(user_id)
|
|
if normalized not in context.get("approvers", []):
|
|
logger.warning(f"User {normalized} is not an authorized approver")
|
|
return False
|
|
if approved:
|
|
if normalized in context.get("approved_by", []):
|
|
return True
|
|
context.setdefault("approved_by", []).append(normalized)
|
|
else:
|
|
if normalized in context.get("rejected_by", []):
|
|
return True
|
|
context.setdefault("rejected_by", []).append(normalized)
|
|
return True
|
|
|
|
|
|
def is_fully_approved(context: dict[str, Any]) -> bool:
|
|
approvers = context.get("approvers", [])
|
|
approved = context.get("approved_by", [])
|
|
return bool(approvers) and set(approvers) == set(approved)
|