ForcePilot/backend/package/yuxi/channels/adapters/mattermost/config_schema.py

220 lines
7.3 KiB
Python
Raw Normal View History

from __future__ import annotations
MATTERMOST_CONFIG_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "Mattermost Channel Configuration",
"properties": {
"server_url": {
"type": "string",
"format": "uri",
"description": "Mattermost 服务器 URL",
"examples": ["https://mattermost.example.com"],
},
"bot_token": {
"type": "string",
"description": "Bot Personal Access Token",
"writeOnly": True,
},
"dm_policy": {
"type": "string",
"enum": ["open", "allowlist", "pairing", "disabled"],
"default": "open",
"description": "DM 安全策略",
},
"group_policy": {
"type": "string",
"enum": ["open", "allowlist", "disabled"],
"default": "open",
"description": "群组安全策略",
},
"allow_from": {
"type": "array",
"items": {"type": "string"},
"description": "DM 白名单(用户 ID 或 @username",
},
"group_allow_from": {
"type": "array",
"items": {"type": "string"},
"description": "群组白名单",
},
"chatmode": {
"type": "string",
"enum": ["oncall", "onmessage", "onchar"],
"default": "onmessage",
"description": "消息响应模式",
},
"require_mention": {
"type": "boolean",
"default": True,
"description": "群组消息是否需要 @提及",
},
"onchar_prefixes": {
"type": "array",
"items": {"type": "string"},
"default": [">", "!"],
"description": "onchar 模式触发前缀",
},
"reply_to_mode": {
"type": "string",
"enum": ["off", "first", "all", "batched"],
"default": "off",
"description": "回复线程绑定模式",
},
"text_chunk_limit": {
"type": "integer",
"minimum": 1000,
"maximum": 16383,
"default": 4000,
"description": "消息分块大小上限",
},
"media_filename": {
"type": "string",
"default": "file",
"description": "媒体文件默认文件名",
},
"max_media_size_mb": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 100,
"description": "最大媒体文件大小 (MB)",
},
"dangerously_allow_name_matching": {
"type": "boolean",
"default": False,
"description": "允许白名单名称匹配(安全风险)",
},
"auto_register_commands": {
"type": "boolean",
"default": False,
"description": "自动注册 Slash Commands",
},
"commands": {
"type": "array",
"items": {
"type": "object",
"properties": {
"command": {"type": "string"},
"description": {"type": "string"},
},
},
"description": "自定义 Slash Commands",
},
"silence_send": {
"type": "boolean",
"default": False,
"description": "静默发送模式 — 发送 message 时不连带任何 props/attachments",
},
"block_streaming": {
"type": "boolean",
"default": True,
"description": "启用/禁用块流式输出",
},
"stream_min_chars": {
"type": "integer",
"minimum": 1,
"maximum": 16383,
"default": 50,
"description": "partial/block 流式模式下缓冲区最小字符数,达到后刷新",
},
"stream_idle_ms": {
"type": "integer",
"minimum": 100,
"maximum": 30000,
"default": 1000,
"description": "partial/block 流式模式下最大空闲等待 (ms),超时后刷新缓冲",
},
"blockStreamingCoalesce": {
"type": "object",
"properties": {
"minChars": {"type": "integer", "default": 1500},
"idleMs": {"type": "integer", "default": 1000},
},
"description": "block 流式合并配置",
},
"dmChannelRetry": {
"type": "object",
"properties": {
"baseDelayMs": {"type": "integer", "default": 1000},
"maxRetries": {"type": "integer", "default": 3},
},
"description": "DM 频道创建重试配置",
},
"responsePrefix": {
"type": "string",
"default": "",
"description": "所有回复前添加的前缀",
},
"network": {
"type": "object",
"properties": {
"dangerouslyAllowPrivateNetwork": {
"type": "boolean",
"default": False,
},
},
"description": "网络配置",
},
"configWrites": {
"type": "boolean",
"default": False,
"description": "允许通过命令写入配置",
},
"agent_routes": {
"type": "object",
"description": "Per-channel/Per-team Agent 路由配置",
},
"default_agent_id": {
"type": "string",
"description": "默认 Agent ID",
},
"groups": {
"type": "object",
"description": "Per-Group 配置,支持 requireMention 覆盖",
"additionalProperties": {
"type": "object",
"properties": {
"requireMention": {"type": "boolean"},
},
},
},
},
"required": ["server_url", "bot_token"],
"additionalProperties": True,
}
def validate_config_schema(config: dict) -> list[str]:
"""基于 JSON Schema 验证配置。返回错误列表。"""
errors = []
for req in MATTERMOST_CONFIG_SCHEMA.get("required", []):
if not config.get(req):
errors.append(f"Missing required field: {req}")
dm_policy = config.get("dm_policy", "")
allowed_dm = MATTERMOST_CONFIG_SCHEMA["properties"]["dm_policy"]["enum"]
if dm_policy and dm_policy not in allowed_dm:
errors.append(f"dm_policy must be one of {allowed_dm}")
group_policy = config.get("group_policy", "")
allowed_gp = MATTERMOST_CONFIG_SCHEMA["properties"]["group_policy"]["enum"]
if group_policy and group_policy not in allowed_gp:
errors.append(f"group_policy must be one of {allowed_gp}")
chatmode = config.get("chatmode", "")
allowed_cm = MATTERMOST_CONFIG_SCHEMA["properties"]["chatmode"]["enum"]
if chatmode and chatmode not in allowed_cm:
errors.append(f"chatmode must be one of {allowed_cm}")
text_chunk_limit = config.get("text_chunk_limit", 0)
if text_chunk_limit and (text_chunk_limit < 1000 or text_chunk_limit > 16383):
errors.append("text_chunk_limit must be between 1000 and 16383")
return errors
def get_config_schema() -> dict:
"""返回配置 JSON Schema。"""
return MATTERMOST_CONFIG_SCHEMA