from __future__ import annotations QQBOT_CONFIG_HINTS: list[dict] = [ { "key": "app_id", "label": "App ID", "help": "QQ 开放平台应用 ID,从「应用管理」页面获取", "required": True, "sensitive": False, "section": "credentials", }, { "key": "app_secret", "label": "App Secret", "help": "QQ 开放平台客户端密钥,从「开发设置」中生成", "required": True, "sensitive": True, "section": "credentials", }, { "key": "client_secret_file", "label": "密钥文件路径", "help": "存放 App Secret 的文件路径,优先于环境变量", "required": False, "sensitive": False, "section": "credentials", }, { "key": "sandbox", "label": "沙箱模式", "help": "启用沙箱 API 端点 (sandbox.api.sgroup.qq.com)", "required": False, "default": False, "type": "boolean", "section": "connection", }, { "key": "bot_name", "label": "Bot 名称", "help": "机器人显示名称,用于 @提及匹配", "required": False, "section": "basic", }, { "key": "intents", "label": "WebSocket Intents", "help": "QQ Bot Gateway 意图位掩码,控制订阅的事件类型", "required": False, "type": "number", "section": "connection", }, { "key": "dm_policy", "label": "DM 策略", "help": "私信访问策略: open(开放) / allowlist(白名单) / pairing(配对) / disabled(禁用)", "required": False, "default": "open", "type": "enum", "options": ["open", "allowlist", "pairing", "disabled"], "section": "security", }, { "key": "group_policy", "label": "群组策略", "help": "群组访问策略: open(开放) / allowlist(白名单) / disabled(禁用)", "required": False, "default": "open", "type": "enum", "options": ["open", "allowlist", "disabled"], "section": "security", }, { "key": "allow_from", "label": "DM 白名单", "help": "允许私信的用户 ID 列表,支持通配符 '*'", "required": False, "type": "list", "section": "security", }, { "key": "group_allow_from", "label": "群组白名单", "help": "允许的群组 ID 列表,支持通配符 '*'", "required": False, "type": "list", "section": "security", }, { "key": "group_require_mention", "label": "群聊 @提及门控", "help": "群聊中是否需要 @机器人 才响应", "required": False, "default": True, "type": "boolean", "section": "security", }, { "key": "pairing_enabled", "label": "配对模式", "help": "启用配对模式,仅已配对用户可私信", "required": False, "default": False, "type": "boolean", "section": "security", }, { "key": "group_ignore_other_mentions", "label": "忽略他人 @", "help": "当消息 @了其他人但不包含机器人时忽略", "required": False, "default": True, "type": "boolean", "section": "security", }, { "key": "group_command_bypass_mention", "label": "命令跳过 @", "help": "白名单命令可不需要 @机器人", "required": False, "default": True, "type": "boolean", "section": "security", }, { "key": "use_markdown", "label": "使用 Markdown", "help": "使用 Markdown 格式发送消息", "required": False, "default": False, "type": "boolean", "section": "format", }, { "key": "markdown_template_id", "label": "Markdown 模板 ID", "help": "QQ Bot Markdown 消息模板 ID", "required": False, "section": "format", }, { "key": "stream_flush_interval", "label": "流式刷新间隔", "help": "C2C 流式消息的刷新间隔 (秒)", "required": False, "default": 0.6, "type": "number", "section": "streaming", }, { "key": "streaming_mode", "label": "流式模式", "help": "C2C 流式模式: off(关闭) / block(块流式)", "required": False, "default": "block", "type": "enum", "options": ["off", "block"], "section": "streaming", }, { "key": "silent", "label": "静默发送", "help": "发送消息时不通知用户 (no_notify)", "required": False, "default": False, "type": "boolean", "section": "format", }, { "key": "dedup_window_s", "label": "去重窗口", "help": "消息去重时间窗口 (秒)", "required": False, "default": 60, "type": "number", "section": "advanced", }, { "key": "auto_download_attachments", "label": "自动下载附件", "help": "自动下载消息中的图片/文件附件", "required": False, "default": True, "type": "boolean", "section": "advanced", }, { "key": "tts_default_voice", "label": "TTS 默认语音", "help": "文字转语音默认发音人", "required": False, "default": "zh-CN-XiaoxiaoNeural", "section": "audio", }, { "key": "tts_default_format", "label": "TTS 默认格式", "help": "音频输出格式", "required": False, "default": "mp3", "type": "enum", "options": ["mp3", "wav", "opus"], "section": "audio", }, { "key": "queue_global_limit", "label": "消息队列全局上限", "help": "消息队列最大容量", "required": False, "default": 1000, "type": "number", "section": "advanced", }, { "key": "queue_per_user_limit", "label": "每用户队列上限", "help": "每个用户的消息队列最大容量", "required": False, "default": 20, "type": "number", "section": "advanced", }, { "key": "queue_per_group_limit", "label": "每群组队列上限", "help": "每个群组的消息队列最大容量", "required": False, "default": 50, "type": "number", "section": "advanced", }, { "key": "queue_max_concurrency", "label": "队列最大并发", "help": "消息队列最大并发处理数", "required": False, "default": 10, "type": "number", "section": "advanced", }, { "key": "reconnect.max_retries", "label": "重连次数", "help": "WebSocket 最大重连次数", "required": False, "default": 10, "type": "number", "section": "connection", }, { "key": "reconnect.base_delay", "label": "重连基础延迟", "help": "重连指数退避基础延迟 (秒)", "required": False, "default": 1.0, "type": "number", "section": "connection", }, { "key": "reconnect.max_delay", "label": "重连最大延迟", "help": "重连指数退避最大延迟 (秒)", "required": False, "default": 60.0, "type": "number", "section": "connection", }, { "key": "reconnect.jitter", "label": "重连抖动系数", "help": "重连延迟随机抖动系数", "required": False, "default": 0.3, "type": "number", "section": "connection", }, { "key": "retry.attempts", "label": "发送重试次数", "help": "消息发送失败最大重试次数", "required": False, "default": 3, "type": "number", "section": "connection", }, { "key": "credential_backup_dir", "label": "凭据备份目录", "help": "凭据备份文件存储目录", "required": False, "section": "storage", }, { "key": "session_store_dir", "label": "会话存储目录", "help": "WebSocket 会话持久化目录", "required": False, "section": "storage", }, { "key": "known_users_max", "label": "已知用户上限", "help": "已知用户追踪器最大记录数", "required": False, "default": 10000, "type": "number", "section": "storage", }, { "key": "known_users_persist_dir", "label": "已知用户存储目录", "help": "已知用户持久化文件目录", "required": False, "section": "storage", }, { "key": "suppress_local_approval_prompt", "label": "抑制本地审批提示", "help": "防止 QQ Bot 本地二次审批提示去重", "required": False, "default": True, "type": "boolean", "section": "approval", }, { "key": "approval_native_routing", "label": "审批原生路由", "help": "审批请求通过 QQ Bot 内联键盘路由", "required": False, "default": True, "type": "boolean", "section": "approval", }, { "key": "plugin_version", "label": "插件版本", "help": "注入 HTTP User-Agent 的插件版本号", "required": False, "default": "1.0.0", "section": "advanced", }, { "key": "openclaw_version", "label": "OpenClaw 版本", "help": "注入 HTTP User-Agent 的平台版本号", "required": False, "default": "1.0.0", "section": "advanced", }, { "key": "message_cache_max", "label": "消息缓存上限", "help": "发送消息缓存最大记录数", "required": False, "default": 500, "type": "number", "section": "advanced", }, { "key": "message_cache_ttl_s", "label": "消息缓存 TTL", "help": "发送消息缓存过期时间 (秒)", "required": False, "default": 3600, "type": "number", "section": "advanced", }, ] def get_config_hints(section: str = "") -> list[dict]: if section: return [h for h in QQBOT_CONFIG_HINTS if h.get("section") == section] return list(QQBOT_CONFIG_HINTS) def get_config_sections() -> list[str]: seen: set[str] = set() result: list[str] = [] for hint in QQBOT_CONFIG_HINTS: section = hint.get("section", "") if section and section not in seen: seen.add(section) result.append(section) return result def get_required_config_keys() -> list[str]: return [h["key"] for h in QQBOT_CONFIG_HINTS if h.get("required")]