配置
通道、模型与群聊策略 先建立稳定的模型连接,再分配模型职责和平台通道,最后按群收敛触发、时间、用户与工具边界。
所有启用的机器人配置会并行运行,回复始终回到来源通道。凭据在「机器人」页按平台填写;密钥字段留空表示沿用已保存的那份,填写才覆盖。
接入方式决定部署形态
真正影响部署的不是平台本身,而是消息怎么进来。OneBot、Telegram、QQ 官方机器人、钉钉和微信由 Diana 主动出站建立连接,家庭宽带或内网也能直接用;飞书和企业微信只能由平台把事件 POST 过来,必须有一个公网可达的 HTTPS 地址。
平台 接入方式 需要公网地址
OneBot v11 正向 WS、反向 WS 或 HTTP API + 事件上报 否
Telegram Bot API 长轮询,Diana 主动出站 否
QQ 官方机器人 开放平台 WebSocket 网关,Diana 主动出站 否
钉钉 Stream 模式长连接,Diana 主动出站 否
飞书 事件订阅回调,由飞书 POST 过来 是
企业微信 自建应用回调,由企业微信 POST 过来 是
微信 腾讯 iLink Bot 扫码登录,长轮询,Diana 主动出站 否
iMessage Mac 上的 BlueBubbles Server 推 webhook,可选轮询兜底 否,Mac 能访问到 Diana 即可
各平台需要的凭据
OneBot v11
适配器 推荐 SnowLuma
连接 支持正向 WS、反向 WS(默认)和 HTTP API + 事件上报
反向 WS ws://HOST:18080/onebot/v11/ws,双方 Access Token 一致
正向 WS Diana 填接入端的通用地址,如 ws://127.0.0.1:6700/,自动重连
HTTP Diana 填接入端 API 地址,如 http://127.0.0.1:5700;接入端上报至 http://HOST:18080/onebot/v11/http,双方配置相同的签名 secret。API Token 独立配置,回复通过 API 发送。
边界 OneBot v11;固定反向 WS 与 HTTP 入口各接一个配置档,正向 WS 可接多个。HTTP 连通状态仅表示 API 探测成功,需同时配置事件上报。
能力 群列表、CQ 码、引用、群文件、本地媒体
Telegram
凭据 BotFather 生成的 Bot Token
连接 通过 Bot API 长轮询主动出站
公网 不需要 webhook 或公网入口
网络 支持代理和自建 Bot API 地址
QQ 官方机器人
凭据 开放平台的 AppID 与 AppSecret
连接 换取 access token 后连网关 WebSocket
沙箱 机器人未上架时可勾选沙箱环境联调
能力 收:文字、图片、视频、语音(平台自动转写)、文件,合并聊天记录里的媒体同样拆出。发:文字、图片、视频、语音;带 Markdown 的文字走原生 Markdown(msg_type 2,不认行内代码和表格),被拒收时自动降成纯文本重发
范围 群聊默认只推送 @ 了机器人的消息,群主可在群聊设置里改成获取群内全部消息
钉钉
凭据 应用的 Client ID 与 Client Secret
连接 Stream 模式,不必在后台配 HTTP 回调
回复 优先走会话的 sessionWebhook,不占推送额度
范围 只能收到 @ 了机器人的群消息
飞书
凭据 自建应用的 App ID 与 App Secret
验签 事件订阅页的 Verification Token
加密 后台开了加密推送时填 Encrypt Key
地址 Lark 国际版填 open.larksuite.com
企业微信
凭据 企业 ID、AgentId、应用 Secret
验签 「接收消息」里的 Token 与 EncodingAESKey
必填 后两项缺一个就只能发不能收
格式 AgentId 必须是纯数字
能力 收:应用单聊和应用群聊的文本;图片、语音、事件推送忽略。发:文本或 Markdown(企业微信客户端渲染,不认斜体和表格),群聊走 appchat/send。发送不回消息 ID,入站没有引用关系。
微信
凭据 不用填:保存机器人后在「接入」里扫码,确认后自动写入
连接 腾讯 iLink Bot 接口(ilinkai.weixin.qq.com)长轮询,游标和会话 context_token 存在数据目录的 weixin/ 下,重启接着收
能力 只有私聊。收:文字、图片(CDN 下载后解密)、引用原文、语音的服务端转写文字;文件和视频只给占位。发:文字、图片;视频、语音、文件暂不支持
主动消息 只能发给先给机器人发过消息的人:回复要带对方最近一条消息里的 context_token。提醒、主人通知、审计告警发给从没说过话的人会直接报「对方需要先给机器人发一条消息」
失效 服务端判定登录失效(errcode -14)时暂停收发一小时,状态里写明原因;持续失效请重新扫码。其余拒绝(风控、频控)原样显示服务端错误并退避重试
iMessage
前提 一台常开、登录 Apple ID 的 Mac 运行 BlueBubbles Server
凭据 服务器地址与密码;webhook 密钥保存时自动生成
回调 /api/channels/imessage/callback?token=…
回调地址
飞书和企业微信要把下面的地址填到各自后台的事件接收配置里。HOST 必须是平台服务器能访问到的公网地址,并且是 HTTPS。
https://HOST/api/channels/feishu/callback
https://HOST/api/channels/wecom/callback
同一平台配置了多个机器人时,在地址后面加配置档 ID 区分,例如 /api/channels/feishu/callback/<profile-id>;只有一个时用上面的短地址即可。
这两条路径不走 WebUI 登录 平台服务器带不了登录会话,所以它们由各自的规范验签:企业微信校验 msg_signature、按 WXBizMsgCrypt 解密并核对报文里的企业 ID;飞书核对 Verification Token,配了 Encrypt Key 时还会验 X-Lark-Signature 并解密。回调地址本身是公开信息,不能当凭据用,所以验签凭据请务必填写。
平台能力差异
群等级门槛只对 OneBot v11 生效 。其余平台没有群等级概念,准入设置里不显示该项。
语音消息和 @某人 依赖 OneBot 的 CQ 码,其他平台上自然降级:正文照发,但不会 @ 到人。
本地媒体 在 OneBot 侧由适配器拉取 Diana 的 /media/resolver 地址;Telegram 拉不到本机地址,改为直接 multipart 上传。
QQ 官方机器人默认只推送 @ 了机器人的群消息 ,群主在群聊设置里把「机器人可获取的群聊消息范围」改成「获取群内全部消息」后,自然插话、群聊氛围感知即可用。钉钉只推送 @ 了机器人的群消息,这两个功能在钉钉上不会触发。
飞书、企业微信和钉钉目前只处理文本消息 。图片和文件在这几家给的是下载凭据,需要另外换取,暂未接入。
多通道上下文
每个机器人保存独立的平台、账号、主人、人设和模型分配。多个平台同时运行时,回复始终回到来源通道。会话上下文固定按机器人隔离,不能关闭;同编号的群聊或私聊不会合并。需要交流时,可单独配置消息互通,或在双方机器人启用跨平台记忆后检索非敏感群公共事实与摘要,不共享原始聊天和个人记忆。
旧配置中的 isolate_platform_contexts 字段不再生效,原设置接口已移除。此前共享的历史记录保留在原位置,不会自动分配给各机器人;后续消息进入各自的隔离会话。
“提供商”页管理 Base URL、API Key 和协议,可同步模型目录,也可添加自定义模型 ID;机器人配置再将不同职责绑定到具体模型。
所有模型都可以点击编辑上下文窗口和输入、输出能力,包含同步的模型与自定义 ID。手动设置与目录信息独立保存,重新同步不会覆盖;关闭“手动设置模型能力”可恢复跟随目录。输入图片、输出文字表示视觉理解,输出图片表示图片生成。能力标注仅用于提示和排序,机器人仍可选择并保存能力不匹配的模型。
实际上下文窗口按“提供商统一覆盖 → 当前模型的手动窗口 → 128,000 Token 兜底值”取值;同步目录中的窗口只作参考。模型窗口随实际选中的模型切换,单次请求上限仍不能超过窗口。模型编辑先应用到草稿,再保存提供商配置。
角色 用途 测试要求
对话 最终回复、Agent 推理 验证中文表达、工具调用和长上下文。
视觉 普通图片、截图、历史图片 发送真实图片,验证小字 OCR、界面结构和多图关系。
意图识别 主动回复、回复抑制、关系判断 验证低延迟、稳定结构化输出和边界案例。
图片生成 文生图与图片编辑 必须实际生成并返回图片,不能只测文本连通性。
默认启用 “识别机器人并自动不回复”默认打开,用于避免机器人之间循环对话;有明确业务需要时再关闭。
授权登录(OAuth)
配置档的“凭据方式”可以用 OAuth 代替 API Key。控制台常跑在服务器上、浏览器未必同机,所以回调不强求落回本机:点“登录”后在自己的浏览器里完成授权,把地址栏那条回调地址整条粘回来即可(只粘其中的 code 也认)。令牌在过期前自动续期;同时填了 API Key 的话,续期失败会回落到它,不至于整个配置档一起哑掉。
提供商是配置而不是代码。内置 OpenRouter,其余在“自定义提供商”里填授权地址、令牌地址、Client ID 和 Scope 自行接入,适合自建网关或未内置的服务。两个地址必须是 https,本机回环地址(127.0.0.1)可以用 http。
拿到令牌之后怎么带给模型接口,同样是配置项。默认 Authorization: Bearer <token> 适用于绝大多数提供商;个别家不吃这一套——Anthropic 收到 Authorization 里的 OAuth 令牌会直接回 401“OAuth authentication is currently not supported.”,它要求令牌放在 x-api-key 里且不带前缀。所以自定义提供商的“高级”里可以指定令牌请求头、令牌前缀和一组附加请求头。换用非默认落点时,各家 SDK 自己写上的鉴权头会被摘掉,避免同一个请求带两种鉴权。
换令牌那一步的请求体格式 同样在“高级”里选。RFC 6749 §4.1.3 规定令牌接口用 application/x-www-form-urlencoded,所以那是默认值;JSON 是部分服务自己的方言,内置的 OpenRouter 就只收 JSON。发错格式时对方通常只回一句“参数缺失”,不会说是整包没解析出来,排查方向容易被带到 Client ID 上去。在这个选项出现之前存下来的自定义提供商会继续按 JSON 发 ,免得本来配通的配置突然换不到令牌;新建的按规范走 form。
不预置需要冒用第一方 Client ID 的提供商 那类用法要向授权服务器谎报客户端身份,也超出消费级订阅本身的授权范围,是否使用属于部署者自己的判断;需要的话可以在“自定义提供商”里自行填写。
上下文与超时
llm:
context_window_tokens: 65536
max_context_tokens: 65536
max_output_tokens: 2048
timeout: 60000ms
图片同样占用视觉 token。视觉质量差时,优先检查模型职责是否真的绑定了视觉模型、原图是否进入请求、图片是否因数量或 token 预算被裁剪,再考虑提高细节等级和上下文上限。
群管理会通过 OneBot get_group_list 同步机器人加入的全部群,而不仅是已经存在本地配置的群。连接不可用时才回退显示 SQLite 中保存的群配置。
私聊默认关闭,包括主人的普通私聊和私聊通知。需要时在「机器人 → 行为 → 准入与限额」选择所有人、仅主人或白名单;关闭时消息静默忽略,不排队、不预处理、不调用模型,群聊和控制台登录配对不受影响。已有配置显式保存的准入模式继续生效;未设置或无效模式按关闭处理。
启用状态 单独停止某个群,不影响其他群或私聊。
触发与主动回复 显式 @、引用、触发词和主动回复语义路由分层判断;显式 @ 优先于引用。
回复时间 支持同日、跨夜时间段和 IANA 时区;这属于群策略,不写入模型提示。
图文输入预算 发送前按 token 估算文字与图片占用,先扣除输出、安全余量及其他媒体预留,再按 1:1 分配图文预算,双方可借用对方未使用的份额;总量能放下时不压缩。文字超额时先不调模型:从最旧的聊天历史整轮丢起(换成一句省略提示),不够再把 Agent 较早的大段工具结果截成开头加结尾,一次裁到文字限额的 85%,给后续几步工具结果留出余量;同一次回复里后续每步沿用同一裁剪点,前缀保持稳定。系统规则、当前问题、最近三轮历史、记忆与摘要、最新两条工具结果和工具调用对应关系都不动。仍装不下时才调模型压缩最长的较早内容,每次回复内同一段文字只压缩一次。仅图片超额时才将部分图片换成带编号的视觉描述,描述计入文字预算。描述失败保留原图,图片确实超额时可降细节。全部做完仍超限时先丢图,余下交给供应商按上下文上限裁剪,不让整轮失败。日志记录的是估算值,不是上游实际计费量。
回复排版 “允许多条发送”关闭后默认收为单条,超限压缩,不自动合并转发;本轮用户明确要求可覆盖。“保留普通段落换行”独立控制消息内部排版,未设置时兼容现有行为,关闭后只收拢普通说明,列表、代码、表格和引用保留结构。两项均支持群级继承,本轮覆盖不持久化。模型继续使用显式消息与换行标记,真实换行不作为布局指令。
人员准入 黑名单(默认)除屏蔽账号外都回;白名单只回名单里的人,名单外连静默提示都不发。主人不受白名单限制。
屏蔽账号 本群名单和全局名单是并集:在这里加人不会让全局屏蔽名单失效。等级和时段则由「为本群单独设置回复规则」整份接管。
人设与上下文 群级提示、历史条数和单条回复上限可以覆盖机器人默认值。旧字段 max_reply_chars 和默认值 3500 保留,但各平台统一按每条消息检查,不再按多条正文总字数压缩。生成提示词提前带上限;允许分条时先按完整段落、句子或章节拆分,只有仍超长的段才交给模型压缩,已达标的段不重写。整轮最多两次压缩调用,失败不发送半份结果、不硬截断;明确要求单条时才压缩整份回复。模型输出 token 预算及发送频率控制仍生效。
工具覆盖 所有插件的参数和凭据全局共享一份,不设共享模式开关;插件启停仍按机器人独立控制。在全部机器人视图统一设置,保存或恢复默认影响所有机器人。旧独立配置迁移时按机器人列表顺序选取第一份已配置的完整设置,其他旧配置保留备份,不混合账号凭据;页面标注迁移来源。群级非密钥行为覆盖沿用原规则。RSS 与 GitHub 订阅均可添加多个“机器人+群聊或私聊”目标,一次检查后分别投递,旧订阅不会自动合并。
平台投递 QQ/OneBot 达到阈值时用合并转发卡片包装分段,不因此删减正文。Telegram 不使用合并转发阈值,也不自动把多条拼成一条;按用户选择正常分段或单条发送,并校验渲染后的平台容量。单段仍超长时先尝试压缩,不可安全压缩的代码等内容仍会报错,不破坏内容。其它平台不尝试 OneBot 转发。
每台机器人的人设是一份 Markdown:她是谁、在乎什么、怎么说话、长什么样。整份原样放在系统提示词最前面,不加任何包装。在「机器人 → 人设」里编辑;群可以在群管理里整份覆盖,留空就跟着机器人走。
Diana 的写法是讲理由,不列规则 :规则总会漏掉没料到的情况,讲清楚为什么,没写到的场合她也能自己推出来;只有做错了代价很大的几件事才写成硬线。用「我们」(主人)的口吻写她,写明身份在压力下不变,写清长相。输出格式、分条、工具、时间、在哪个群这些不用写,运行时会另外补上。完整说明见仓库里的 docs/soul-md.md。
人设库
人设库是套用来源,不是活绑定 :点一份就把正文填进编辑框,保存配置才生效;库里那份之后再改,不会偷偷改变已经配好的机器人。
内置六份(Diana、真人感、猫娘、助手、女友、男友)编译在程序里,只读;想改就套用后另存一份。
每一份都能导出成 名字.md;导入 .md 时名字取第一行一级标题,没有标题用文件名。
导入只增不减:同名但内容不同的改成「名字 (2)」,同名且正文一样的跳过;库上限 50 份。
从旧版升级
人设文件只收 .md,旧版的 JSON / YAML 人设文件不再导入。已经存着的不会丢:升级时机器人配置和人设库里的品格层(soul)、自称、句尾语气词、动作描写开关会渲染成原来运行时注入的那几段文字,并进 SOUL.md,模型读到的指令不变,只是现在在编辑框里看得见、改得了。旧人设里带的提示词覆盖和判据不再跟着人设走,丢弃;机器人自己的提示词覆盖和判据原样保留。
SillyTavern 角色卡
「导入」还认 SillyTavern 角色卡:V1/V2/V3 的 JSON 卡和内嵌卡的 PNG(tEXt 块里的 chara/ccv3)都能直接选中。卡里的 description、personality、scenario、示例对话和开场白会拼成一份正文({{char}}/{{user}} 宏就地展开,超出 4000 字时整段整段舍弃靠后的内容);内嵌的 character_book 顺路并进世界书。
回复模式(搭话频率)、拒答话术、模型分配都不在人设里:它们描述的是「这台机器人在这个群里怎么运行」,跟她是谁无关。
世界书 是机器人所处世界的设定集,在「档案 → 世界书」里维护。设定按树状章节组织,路径本身就是语境(注入时写成「枝江 / 港口:……」)。每个节点自己声明注入方式:常驻 的每轮都带上,写世界的骨架;带触发词 的只在最近对话聊到时注入,写细节,不浪费上下文。只有标题的节点当目录用,自身不注入;关掉一章,底下的节一起停用。
世界书是所有机器人共用的一本,用不用由每台机器人的开关决定(「机器人 → 人设 → 世界书」,默认用,书是空的时开着也不注入内容)。整本可以导出成 JSON 再导入回来,条目的父子关系会按文件里的引用重建;和人设文件一样,ID 是本机状态,导入时一律重新分配。
导入还兼容 SillyTavern 世界书 :世界书文件顶层的 entries、角色卡里内嵌的 character_book 都能直接选中导入。字段按语义折算——蓝灯 constant 对常驻、绿灯关键词对触发词、comment 对标题(缺了退回第一个触发词或内容开头)、disable 对停用,按 order 排好顺序落在根上。次要关键词(keysecondary,AND ANY 逻辑)也会搬过来:主词命中还要求任一副词在场才注入;其他副词逻辑(NOT ANY 等)语义相反,硬搬会把排除当要求,导入时退回只看主词。递归扫描、概率、插入位置这些酒馆扫描器的高级字段没有对应概念,导入时忽略,注入行为以本地规则为准。
拟人化行为
「机器人 → 行为 → 拟人化」里还有三个独立开关,默认全关:
情绪系统 —— 心情随相处涨落:默认就是开心(语气轻快、爱接梗);被骂得多了会暂时回到人设本来的语气,不会变低落,没人再惹它两三个小时就自己回到开心。它复用每条消息本来就要跑的关系评估结果,不多花一次模型调用;只影响语气,不影响回答质量,重启后归于平静。
风格学习 —— 每个群大约一天学一次:后台模型读最近的群友消息(发言人换成字母),写一段不超过 300 字的「这个群怎么说话」,包括口头禅和梗的意思、句子长短、标点和表情习惯、大家怎么互相调侃,回复时带上。群管理页编辑群时能看到这段,可以手动改(手动的不再被自动覆盖)或点「重新学习」(会先确认,覆盖现在这段);也可以只在这个群关掉风格:不学、不带进回复,写好的留着。关掉或不回复的群不学。群友在群里叫机器人「别再说某个词」(比如「别说草了」)时,长期记忆会把它记成本群约定:不挂在提要求的人名下,放在风格笔记后面,回谁都照做,笔记里有也不用;这个不看风格学习开没开。约定默认 30 天后失效(说了「今天别说」这类更短的期限就按说的算),期间有人再提一次就顺延,群里任何人明确说「又可以说了」就撤销。要机器人加口头禅、换语气的要求仍只对提要求的本人生效。
戳一戳回应 —— 被戳一戳时按人设和当前关系亲疏回一句短的(仅 OneBot 平台有此事件);同一个人 90 秒内连戳只回第一下,模型不可用时保持沉默而不是报错。
Agent 运行器将结构化工具结果送回模型,直到得到最终回复、取消或超时,不再设置工具步数上限。工具注册表根据平台、关系权限、群配置和功能状态收敛。
本机运行状态
host_stats 让机器人回答「内存占了多少」「CPU 忙不忙」「现在多少度」这类问题:CPU 型号与占用、平均负载、内存、磁盘、Diana 自身占用,以及这台机器能提供的温度、功率和电池。只读、无参数,采集与控制台总览页共用同一份实现。
温度走 /sys/class/hwmon,功率走 RAPL 的能量计数,电池走 /sys/class/power_supply,都不依赖 lm-sensors 之类的外部命令;容器里只要挂了 /sys 就能读。RAPL 给的是累计能量而非瞬时功率,所以功率要两次采样之间的差值才算得出来,第一次调用会如实说明这一点。macOS 的 powermetrics 需要 root、Windows 缺少通用接口,这两个平台的温度与功率直接报「读不到」——报一个编出来的数比不报更糟 。这条对所有项都成立:读不到的项不会填 0,而是带上读不到的原因。
这个工具同样只对主人开放:主机名、磁盘路径和硬件型号不该对群里所有人可见。
本地文件与命令:读 / 写 / 执行三档
本地那几个工具全部锁在数据目录下的 workspace 里,路径固定不可配置,绝对路径和 ../ 一律拒绝。三档权限各自独立:
档位 工具 默认 开关
读 read_file、list_files、grep、find_files、manage_files 的 stat开 跟随「内置 Agent」总开关
写 write_file、edit_file、save_to_workspace、manage_files 的 move / copy / delete / mkdir新建配置默认开 「允许写入文件」
执行 run_command新建配置带只读白名单 命令白名单非空才注册
新建的机器人装完即可用:写入默认打开(锁在数据目录下的 workspace 内,碰不到配置和数据库),命令白名单预置一组只报状态、不碰数据的命令——uptime、free、df、uname、nproc、date、hostname、whoami。
收进这份默认白名单的标准有三条,缺一不可:不读任意路径的文件、不出网、不改任何东西。因为没有可用沙盒时,白名单里的程序就是以 Diana 自己的进程权限直接跑的——白名单只管得到「能不能跑」,管不到「能碰什么」。所以 cat、ls、find(能读任意路径)、curl、wget(能出网)、ps(会带上别的进程的完整命令行,那里面可能有别人的密钥)都被刻意排除;工作目录内的读取用 read_file / grep / find_files,它们锁在 workspace 里。
默认值只作用于新建配置 已经在跑的部署升级后不会凭空多出命令执行和文件写入:当初留空的白名单仍然是空的,关着的写入开关仍然关着。默认值是给新用户的便利,不该变成对存量部署的静默扩权。老部署想要这些能力,用同一张表单上的「填入推荐默认值」把推荐值填进来——它只改表单,点「保存配置」才生效,授权动作是你自己做的。
write_file 只写文本,目标是 .png、.pdf、.mp4、.zip 这类二进制格式时直接拒绝;read_file 碰到二进制文件同样拒绝,改用 view_image 看图、manage_files stat 看大小和类型。图片、音视频、PDF、压缩包用 save_to_workspace 原样存进来:来源可以是当前会话里某条消息的媒体(包括机器人自己发出去的生成图)、公网网址(和其他下载共用挡内网地址的下载缓存)或 MCP 工具返回的 media_id。存的时候按内容认类型、纠正扩展名(JPEG 一律存成 .jpg),没指定路径时聊天媒体和网址进 downloads/,机器人自己的产物进 outputs/,同名不覆盖。主人开着文件写入时,image 出的图除了照常发送,也会把原图存进 outputs/。manage_files delete 不真删,而是挪进 .trash/<时间戳>/,保留原来的相对路径;回收站里的东西不能再用 manage_files 挪动或删除,也不能往里存文件。
工作目录按用途分区:tmp/ 放草稿和中间文件(1 天后清理),downloads/ 放下载和从聊天里存下的文件、.agent-browser/ 放浏览器截图(7 天),outputs/ 放机器人的产出(30 天),.trash/ 按删除时间 7 天后永久清理,每天由存储维护任务执行。keep/<机器人>/ 是长期保存区,永不自动清理:主人说「存下来」「留着」「别过期」时,save_to_workspace 传 keep=true,或者用 manage_files 挪进 keep/,并附一句 description。每台机器人的长期区上限 2 GB,超了直接拒绝、不挤掉旧文件;别的机器人的长期区只能读。长期区的索引(路径、说明、来源消息、谁存的、时间、大小、类型)放在 .diana/keep-index/,最近 20 条会随主人的每轮对话放进提示词尾部。根下散落的文件和没有机器人引用、30 天没动的 coding/ 仓库只在日志和 WebUI 里报告,不自动删除。侧栏的 文件 页上面是各分区的占用、文件数、清理规则和长期区配额,点一块跳进对应目录;下面逐层浏览、预览和下载,长期区的文件带着索引里的说明,删除先进回收站,在 .trash/ 里可以清空回收站。这一页只有管理员进得来,所以什么都给看:运行时配置和凭据(.diana/、MCP 配置、编码代理登录态)照常列出、能打开和下载,只标上「凭据」或「运行时文件」;指到工作目录外面的符号链接照样跟过去,标成「外部链接」。删除凭据和运行时文件要多确认一次。
edit_file 的每个替换必须在原文件里唯一命中一处,命中多处或找不到都整批拒绝而不是改错地方;多个替换都按原文件定位,不是依次生效——依次生效会让后一个替换命中前一个刚写进去的内容,而那种改动从调用方的输入上完全看不出来。
身份挡不住提示注入 这三档只对主人开放,但「调用发生在主人的会话里」不等于「这次调用是主人要的」:群里其他人的消息和主人的消息在同一个上下文里,模型是读完那些之后才决定调用工具的。所以真正的边界是这里的开关和白名单,而不是身份判断——需要哪一档就开哪一档,不需要的保持关闭。
编码代理
把改代码的活交给 Claude Code / Codex,跑完回来汇报
「编码代理」插件(official.coding-agent)让机器人把一件编码工作派给本机安装的编码 CLI:在持久工作区里改代码、跑测试、提交,几分钟到几小时都行,期间可以随时问进度,跑完机器人主动把结果发回派活的那个会话。默认不启用 ——它会在后台改代码还会自己开口,装完就生效等于替你做了决定。
工具是 coding,只对主人开放,七个操作:submit 派活、status 查进度、tail 看最近几步动作、cancel 终止、followup 在原会话上追加指令、list 列历史任务、workspaces 列可用工作区。日常用法就是直接说「把刚才聊的那个换行 bug 在 diana 仓库里修掉」,然后隔一会儿问「跑到哪了」。
派出去几秒内还没结束的任务,由 Diana 自己发一条固定格式的受理消息:任务号、代理、工作区和指令摘要,不经过模型。看到这条才算真派出去了——模型嘴上说「交给 Claude Code 了」却没调工具的时候,群里就不会出现它。几秒内就结束的(认证失败、账号被封这类)不发受理消息,结果直接由派活那一轮回复;结果超过 1500 字时,全文先由系统发出,模型只说结论。跑完的汇报先发一条带 @ 的头部;结果在 1500 字以内就跟在头部里,更长的报告头部只带开头几行,全文紧跟着用一张合并转发发出(机器人关了合并转发或平台不支持时分条发;合并转发没等到回执时按已送达处理,不再重发)。全文没发成会重试,重试只补全文,不重发头部。记录里留全文,上限 2 万字;给模型查进度用的 status 只带开头 1500 字,并用 result_truncated 标明。
设置项
设置 说明
后端 CLI claude / codex / acp / 自定义命令。Claude Code 的 stream-json 能精确解析出会话 ID、逐步进度和结构化结果(含模型轮次和花费);acp 接 Gemini CLI、opencode 这类 ACP 代理,可执行文件填代理命令、命令模板只填代理参数(如 --acp),有结构化进度和最终结论(设计见 ACP 编码后端 );自定义命令退化成按日志尾巴汇报。
可执行文件 留空按后端取默认名从 PATH 查找,不在 PATH 里就填绝对路径。
命令模板 留空用后端预置。占位符 {{instruction}}、{{model}}、{{session}}、{{workspace}};取不到值的占位符连同紧挨在前面的标志一起丢掉,所以没配模型时不会留一个孤零零的 --model。参数不经过 shell,指令里的引号和分号只是普通字符。
工作区白名单 一行一个 名字=本地路径 或 名字=git 仓库地址。只有这里登记过的工作区能被派活。 填仓库地址时首次使用会 clone 到 workspace/coding/<名字> 并常驻。
单次最长运行时间 默认 120 分钟,上限 1440。超时杀掉整个进程组,已完成的改动留在工作区里。
同时运行的任务数 全局并发上限。同一个工作区永远只允许一个任务 ,这条不可配置:两个代理同时改一份检出会互相覆盖。
API 密钥 按后端注入 ANTHROPIC_API_KEY / OPENAI_API_KEY。留空则依赖 CLI 自己已登录的凭据——注意那是跑 Diana 的那个系统用户 的登录态,不是你本机的。
任务扛得住 Diana 重启
编码 CLI 以独立会话(setsid)启动,脱离 Diana 的进程组,输出落进 workspace/coding/.jobs/<任务号>.log,任务记录是同目录下的 JSON。Diana 重启后扫这个目录接回:进程还活着就继续盯,已经结束的按日志收尾并把欠下的汇报补上,汇报成功才落已汇报标记——发失败时下次启动还会再试,比静默丢掉一小时的工作强。
PID 会被系统复用,所以接回时不只看 PID 是否存在:日志安静超过 30 分钟就不再认这个 PID,按中断收尾。Windows 上没有 setsid 这种完全脱离的语义,任务扛不住重启,只能按中断收尾。
授权边界
编码 CLI 不走内置 Agent 那套命令白名单和沙盒 :它需要出网、需要在整个仓库里写文件,塞进白名单等于把白名单的意义废掉。预置模板用 --permission-mode auto,也就是常规改动 CLI 自己放手做,要点头的操作走下面那套聊天里确认。真正的边界是四条:只有主人能调用(工具不在非主人白名单里,工具自身再校验一次身份)、只能在登记过的工作区里干活(工作区名不允许路径分隔符和 ..)、危险操作要主人在聊天里回码放行、每次调用都写运行日志。
聊天里确认危险操作
派活是无人值守的,但「改完顺手推上去」这种事该有人点头。Diana 给编码 CLI 装一个 PreToolUse hook:CLI 每次要跑命令,hook 先问一句能不能做。不在危险清单里的直接放行,命中的就停下来,Diana 把这条发给主人:
编码任务 code-3f2a1b(工作区 diana)要执行一个需要你点头的操作:
Bash:git push origin main
同意就回 7c1d9e,不同意回 b40f22。10 分钟内没人回我就当拒绝。
主人在聊天里把码打出来,任务就继续;回拒绝码或者超时不回,这一步被拦掉,CLI 自己决定绕开还是报错收尾。查进度时 status 会带上 awaiting_approval 和两个码,所以那条消息刷过去了也能再问一次。
为什么是确认码而不是「同意」两个字。 和扩展变更确认码同一个思路:判断只剩一次结构匹配,不涉及任何语义推断,措辞怎么变都不会两头出错。更要紧的是码只出现在主人自己那条消息里——网页正文、工具输出、别人的发言即使写满「同意」也放行不了任何东西。码必须作为独立片段出现,被更长的哈希串包住不算命中;用过即作废,同一条消息重放第二次没有效果。
hook 进程和 Diana 之间走任务目录下的文件信箱(.jobs/approvals/),不开本地端口、不需要令牌:hook 是 CLI 的子进程,环境不由 Diana 决定,而这个目录一定拿得到。顺带来的好处是等待期间 Diana 重启也不丢 ——请求文件还在,hook 还在轮询,重启后接着问。hook 回调的是 Diana 自己的可执行文件(内部子命令 __coding-approve),不生成脚本,也就不用管可执行位和解释器路径在各平台上的差别。
设置 说明
聊天里确认 「危险操作」(默认)只拦清单命中的命令;「所有写操作」连改一个文件都问一次,很吵,一般只在试水时用;「不确认」全程放手。
危险操作清单 一行一个命令片段,大小写不敏感,命中即要确认。默认收了 git push、git reset --hard、git clean -f、git tag -d、gh pr merge、gh pr create、gh release、npm publish、docker push、rm -rf、sudo。收进来的标准是:做完就收不回来,或者影响跑到工作区外面去。改文件、跑测试、本地提交不在其中——那些是派活时就默许的事。
等确认多久 默认 10 分钟,超时按拒绝。等待期间任务是停着的,这段时间也算在单次最长运行时间里,所以把等待调长的时候记得一起看看运行上限。
这套支持 Claude Code 和 ACP 代理:Claude Code 靠 PreToolUse hook,ACP 代理靠它自己发来的授权请求,信箱和放行码是同一套;ACP 代理只能审到它主动来问的操作。codex 和自定义命令没有等价机制。审批开着但后端做不到时,派活会当场报错而不是安静地全放行 :安静地不审批等于骗人。
auto 档拦下来的步骤,加进危险清单就能救hook 对清单外的操作不表态,那些仍然由 --permission-mode auto 自己裁决。非交互模式下没人能回答 CLI 的询问,所以 auto 认为需要确认的步骤会直接被拒,任务日志里会写明是哪一步。遇到这种情况把那个命令片段加进危险清单:命中清单的操作走聊天确认,主人回码之后 hook 给出的是明确放行 ,能越过 auto 的犹豫。不想一个个加就把模板里的权限档换成 bypassPermissions——注意那个档位在 root 下会被 Claude Code 自己拒掉,Docker 部署默认就是 root。
审批链路自身出故障(读不到策略文件之类)时 hook 选择放行,理由写进 Diana 的运行日志。这一档是刻意的:自己的辅助设施坏掉不该把任务卡死在半路。真正不想让它碰的东西靠工作区白名单挡,不靠审批。
身份挡不住提示注入 和本地文件与命令那三档同理:「调用发生在主人的会话里」不等于「这次调用是主人要的」。群里其他人的消息和主人的消息在同一个上下文里。所以工作区白名单才是真正的闸门——只登记你愿意让它随便改的仓库,不要把生产配置或密钥仓库放进去。不想给推送权限的话,把模板里的权限档换成 --permission-mode acceptEdits,并在那些仓库上用 git hook 拦住 push。
指令怎么写
编码 CLI 看不到这里的聊天记录。需要依据聊天内容改代码时,模型会把相关原话摘进 context 参数,作为背景附在指令前面。指令最长 8000 字——它要落进 argv,系统对单个参数有长度上限;更长的材料该写进工作区里的文件让 CLI 自己读。
任务结束后如果拿到了会话 ID,可以用 followup 在同一个会话上继续,CLI 记得上一轮做过什么。运行中的任务不接受追加:非交互模式的编码 CLI 没有中途收指令的通道,硬插只会变成第二个进程同时改同一份检出。
WebUI 使用登录会话保护 API,并立即更换首次管理员密码。
OneBot 单独配置 Access Token,WS 或 HTTP API 两端保持一致;HTTP 事件上报另配相同的签名 secret。
config.yaml、模型 API Key、Bot Token 和平台 Cookie 不进入 Git。
调试模式会记录完整上下文和工具参数,只在可信环境短期开启。
公网入口放在 HTTPS 反向代理后,并限制管理端来源。
上一页 ← 部署 下一页 实现 →