Skip to content

Repository files navigation

hermes-plugin-milky

standard-readme compliant

Hermes 的 Milky QQ 平台适配器

让 Hermes 进入 QQ 私聊和群聊,成为一个会判断何时回应的 AI 参与者:

  • 接收消息,并识别提及、引用、图片等上下文;
  • 根据会话状态判断何时回应、何时保持沉默;
  • 发送文本、@、引用、图片、语音、视频和文件;
  • 提供群组、成员、文件和好友/入群请求等 QQ 能力。

Warning

当前仍有一类权限隔离尚未完成:

  • ToolSpec: 25 个 QQ 工具没有独立的调用者和目标授权。模型、其他会话或 cron 可能查询无关群/好友,或执行禁言、踢人、撤回、退群、删好友、接受/拒绝请求等操作。

最低限度的安全配置:

  • MILKY_ALLOWED_CHATS 只填写你能控制、成员可信且用途明确的会话;
  • 不要加入公开群、成员可随意加入的群或不受控私聊;
  • 记住:该配置只限制入站会话,不等于 ToolSpec 或通用出站 sender 的授权;
  • 留空表示允许所有会话进入。

示例:

MILKY_ALLOWED_CHATS=group:123456789,dm:987654321

示例中的 ID 仅为占位值。

允许使用 dm:* 放行所有私聊,或使用 group:* 放行所有群聊;通配符只匹配对应的 dm:/group: 命名空间,也可以和具体 chat key 混用。

详细的模块职责、生命周期和行为契约见 ARCHITECTURE.md;主规范、未归档 change 和已归档 change 的测试证据见 openspec/

目录

核心能力

插件适合希望把 Hermes 放进 QQ 私聊和群聊的场景:

  • 自然参与: 根据提及、引用、关键词和会话状态,决定回应还是保持沉默;
  • 多媒体消息: 接收图片等上下文,并发送文本、@、引用、图片、语音、视频和文件;
  • QQ 信息能力: 查询群组、成员、文件和好友/入群请求,并提供部分 QQ 操作;
  • 会话安全边界: 支持 chat 白名单、禁言状态同步、消息去重和有界历史缓冲。

运行环境:Python 3.13+、Hermes Gateway、Milky v1.3 服务和 httpx。Hermes 负责 Agent 队列及入站资源的下载、缓存和权限边界;本插件负责 Milky 适配和已声明的 QQ 能力。

安装

从 Hermes 安装

hermes plugins install ByteColtX/hermes-plugin-milky --enable

--enable 会在安装成功后直接启用插件并跳过确认提示。首次安装完成后,可以用下面的命令确认 插件状态:

hermes plugins list

如果 hermes-plugin-milky 显示为 disabled,启用插件:

hermes plugins enable hermes-plugin-milky

插件启用后,按配置完成 Milky 服务地址、access token 和可选白名单配置, 然后重启 Gateway:

hermes gateway restart

已有安装需要拉取新版本时,执行:

hermes plugins update hermes-plugin-milky
hermes gateway restart

更新插件代码或配置后都需要重启 Gateway,运行中的进程不会自动加载新的插件代码。

从源码设置开发环境

git clone https://github.com/ByteColtX/hermes-plugin-milky.git
cd hermes-plugin-milky
uv sync

源码安装适合开发和调试。拉取新代码后重新同步环境,并重启 Gateway:

git pull
uv sync
hermes gateway restart

Important

启动前先完成下方的 Milky 配置,并确保启动 Hermes 的进程会加载 ~/.hermes/.env。 配置只在启动时读取;修改后需要重启 Gateway。

配置

Milky 最小配置

建议将环境变量集中保存到 ~/.hermes/.env

MILKY_BASE_URL=http://127.0.0.1:3000
MILKY_ACCESS_TOKEN=<从安全凭证存储注入>
MILKY_ALLOWED_CHATS=group:123456789,dm:987654321
MILKY_SESSION_BUFFER_SIZE=20
MILKY_HOME_CHANNEL=group:123456789
# MILKY_MAX_LOCAL_MEDIA_BYTES=33554432
# MILKY_WILL_POLICY=<JSON 字符串,见下方 Will policy>

上面的 QQ/群号仅为合成示例。.env 只应保存在本机或安全的部署环境中,不要提交到版本库。

变量 必需 作用
MILKY_BASE_URL Milky 服务基址;Action 使用 <base>/api/{action},事件流使用 <base>/event。远程部署请使用 HTTPS。
MILKY_ACCESS_TOKEN Milky access token,只用于 Bearer 认证。
MILKY_ALLOWED_CHATS 入站 chat key 白名单,支持具体 group:<群号>/dm:<QQ号> 以及 group:*/dm:*;通配符只匹配对应命名空间,可混用;留空表示允许所有会话进入。
MILKY_WILL_POLICY 决定消息等待(wait)或触发(trigger)的嵌套 JSON 配置。
MILKY_SESSION_BUFFER_SIZE wait 历史消息上限,默认 20;设为 0 可关闭历史缓冲。
MILKY_HOME_CHANNEL 系统消息和 cron 的默认目标;不参与入站白名单。
MILKY_MAX_LOCAL_MEDIA_BYTES 出站本地资源原始字节数上限,默认 3355443232 MiB),合法范围 83886088 MiB)至 3355443232 MiB)。

消息 chat key 只接受 group:<十进制群号>dm:<十进制 QQ 号>;白名单另支持完整的 group:*dm:* 规则,temp 会话不会回退到其他目标。

Hermes Agent 推荐配置

下面的配置让群聊共享 session、在 Agent 忙碌时排队,并减少进度消息。请合并到 ~/.hermes/config.yaml,保留已有的其他配置:

# 群友共享同一个 group:<群号> 会话
group_sessions_per_user: false

# 显式指定时区
timezone: Asia/Shanghai

# 长任务跟进
agent:
  gateway_timeout: 1800
  gateway_auto_continue_freshness: 3600
  gateway_notify_interval: 180  # 每 3 分钟发一次“仍在处理”
  session_stall_timeout: 300    # 排队且无进展 5 分钟时提醒
  # 已确认主模型支持图片输入时,直接以内联图片交给主模型
  image_input_mode: native

# 自定义 provider 的模型不会总能从模型目录自动识别视觉能力。
# 请在已有 model 配置中保留其他字段,并追加 supports_vision: true。
model:
  supports_vision: true

# 群聊消息不要打断当前任务,排队处理
display:
  busy_input_mode: queue
  busy_ack_enabled: false
  tool_progress_command: false
  background_process_notifications: result
  memory_notifications: off
  platforms:
    milky:
      thinking_progress: off       # 关闭“思考中”状态
      tool_progress: off           # 关闭工具进度
      interim_assistant_messages: false
      long_running_notifications: false  # 可选:关闭“仍在处理”心跳
      show_reasoning: false        # 关闭最终回复中的思考摘要
      streaming: false             # 关闭本插件会话的流式输出
      busy_ack_detail: false       # 隐藏忙碌提示中的迭代/工具详情
      busy_steer_ack_enabled: false
      live_status: off             # 关闭支持状态文本时的实时状态

# Slash Command 发送者门禁;命令名不带 /
platforms:
  milky:
    extra:
      # 私聊管理员 QQ 号
      allow_admin_from:
        - "123456789"

      # 私聊普通用户允许的只读命令
      user_allowed_commands:
        - "milky"
        - "status"
        - "context"
        - "agents"

      # 群聊管理员 QQ 号
      group_allow_admin_from:
        - "123456789"

      # 群聊普通用户允许的只读命令
      group_user_allowed_commands:
        - "milky"
        - "status"
        - "context"
        - "agents"

# 关闭后台自动复盘、自动写入记忆/Skill
auxiliary:
  background_review:
    enabled: true

memory:
  memory_enabled: true
  user_profile_enabled: true
  nudge_interval: 20    # 每累计 20 个对话回合,触发一次自动记忆复盘,写入 MEMORY.md / USER.md

# 关闭自动建议创建 Skill
skills:
  creation_nudge_interval: 0

# /goal 的最大自动续行轮数
goals:
  max_turns: 20

# 推荐闲置 2 小时后重置,避免群聊上下文无限变旧
session_reset:
  mode: idle
  idle_minutes: 120
  notify: false

管理员可以执行所有已注册命令;普通用户默认可以执行 /help/whoami,以及对应 user_allowed_commands 中列出的命令。私聊和群聊的管理员列表分别配置;某个作用域未配置 对应的 *_allow_admin_from 时,该作用域的 Slash Command 门禁不会启用。

建议只开放明确的只读命令。configtoolsmodelsessionscrongoalmemorysuggestionsskills 等命令包含配置、会话、工具或任务状态变更,不建议加入普通用户白名单。

修改后需要重启 Gateway;配置只在启动时读取。

group_sessions_per_user: false 会让群友共享同一个 Hermes session;这适合群聊,但也意味着 群内消息会共同影响上下文。busy_input_mode: queue 让 Hermes 负责 queue、follow-up、 pending 和 interrupt/steer,插件不复制 Agent 执行队列。

Tip

平台显示设置必须放在 display.platforms.milky 下,不要放到全局 display 下。

关闭自动压缩进度提示

如果不希望在 QQ 中看到自动压缩过程中的 413/compression 提示,可通过 CLI 关闭:

hermes config set compression.progress_notices false
hermes gateway restart

该配置只隐藏常规压缩进度提示;压缩最终失败时的错误提示仍会保留。

image_input_mode: nativemodel.supports_vision: true 只应配置在已确认支持 OpenAI-compatible image_url 输入的主模型上。如果接口不支持原生图片输入,请移除这两项并 使用文本视觉路径。修改后重启 Gateway;日志应出现 Image routing: native

记忆后端

建议使用 Hermes 的 holographic 记忆后端:

hermes config set memory.provider holographic

它适合本地部署:数据保存在本地,不依赖付费云服务,并支持围绕实体召回长期上下文。修改后 重启 Gateway 使配置生效。

查看本地记忆库中的事实记录:

sqlite3 -header -column ~/.hermes/memory_store.db "SELECT fact_id, content, category, tags, trust_score, updated_at FROM facts ORDER BY fact_id;"

Will policy

Will 决定一条消息是先等待,还是交给 Hermes:

  • wait:放入当前 chat 的有界缓冲,暂不启动 Agent;
  • trigger:先取出该 chat 的等待历史,再把当前消息交给 Hermes。

MILKY_WILL_POLICY.engine 只选择一套引擎。routingwillingness 共用消息特征、都输出 wait/trigger,但不会叠加运行

引擎 决策方式 适合场景
routing(默认) 当前消息命中规则就触发,结果确定 希望行为可预测、方便排查
willingness 按 chat 维护分数,再按概率抽样 希望机器人偶尔参与、减少刷屏

routing:确定性规则

routing 只看当前消息:不维护分数、不使用随机数。direct 等规则字段的值只能是 waittriggerkeywords 不填写动作,命中时固定为 trigger

字段 命中条件 默认行为
direct friend 私聊 trigger
mention 直接 @Bot(只认 mention.user_id == self_id trigger
mentionAll @全体成员 wait
quote 回复 Bot 的消息(只认 reply.data.sender_id == self_id wait
poke 协议明确指向 Bot 的 poke wait
allMessage 每条普通 friend/group 消息 wait
keywords 正文包含任意一个非空关键词 空数组(不命中)

一条消息可以同时命中多条规则;结果按 OR 合并,任一规则为 trigger 就触发,不会被其他 wait 抵消。图片没有独立 routing 规则,单独出现时仍由 allMessage 决定; friend_nudgegroup_nudge 在普通消息流程中保持 observe-only。

示例:只有私聊、@Bot 或包含“提醒”的消息进入 Hermes,其余消息等待:

{
  "engine": "routing",
  "routing": {
    "allMessage": "wait",
    "direct": "trigger",
    "mention": "trigger",
    "keywords": ["提醒"]
  }
}

willingness:分数 + 概率

willingness 不把每个信号直接设成 wait/trigger,而是为每个 chat 单独维护一个分数。 普通消息大致经过以下步骤:

  1. 先让分数按静默时间衰减;
  2. 根据文本、提及、reply、图片、私聊等特征增加分数;
  3. 命中 willingness.interestKeywords 时提高本次增益倍率;
  4. 命中 willingness.forceKeywords 时直接得到 trigger,否则在分数超过 probabilityThreshold 后换算成概率并抽样,得到 waittrigger

因此,同一条消息可能因为当前分数或随机抽样不同而得到不同结果。willingness.interestKeywords 只控制加分倍率,不是确定性触发器;willingness.forceKeywords 才是包含即触发的 确定性规则。

directForcementionForcequoteForce 可让对应信号跳过随机抽样,直接 trigger。 其中 mentionForce 只匹配直接提及当前 Bot(mention.user_id == self_id),quoteForce 只匹配 至少一个明确引用当前 Bot 的 reply(reply.data.sender_id == self_id);他人提及、mention_allhere、他人引用和无法确认目标的引用都会继续走其他 force 条件或概率抽样。 forceKeywords 与这些 force 字段等价地跳过随机抽样,但不额外增加 score;两类关键词同时 命中时,interestKeywords 仍控制增益倍率,forceKeywords 决定最终触发。 mentionGain 只在直接提及当前 Bot 时加分;quoteGain 只在至少一个 reply 明确引用当前 Bot 时加分,has_reply 只保留 reply 存在性事实,不会单独产生 quoteGainpokeGain 只在协议 确认 Bot 为接收者的 self-poke 时加分。非 Bot 或无法确认目标的 mention、reply、poke 均不产生 对应 gain。routing 的 quote 规则同样只认引用 Bot;friend_nudgegroup_nudge 仍是 observe-only,不会直接创建 Agent turn。通过 Gate 且得到 trigger 后立即扣除一次 replyCost 参与成本,不等待 Hermes 接受、资源解析或最终发送;后续失败不回滚。等待、Gate 拒绝、命令、temp 和系统事件不会扣费。

示例:默认按概率参与,命中“提醒”时提高增益,命中“紧急”时直接触发:

{
  "engine": "willingness",
  "willingness": {
    "interestKeywords": ["提醒"],
    "forceKeywords": ["紧急"],
    "keywordMultiplier": 1.2,
    "directForce": false,
    "mentionForce": false,
    "quoteForce": false
  }
}

迁移时将旧的 willingness.keywords 改为 willingness.interestKeywords;旧字段不会被静默 兼容。需要包含即触发时再配置 willingness.forceKeywords,省略或配置为空数组表示关闭。 两者都只匹配规范化正文的直接子串,不支持正则、分词或隐式大小写转换。

配置提示

  • 不确定时使用默认的 routing;它最容易预测和调试;
  • 想切换到概率决策时,将 engine 改为 willingness,并配置 willingness 对象;
  • 完整配置可以同时保留两套参数,但运行时只使用 engine 选中的一套;
  • priority 当前只保留在配置 schema 中,不参与 routing 优先级或 willingness 权重计算;
  • 旧的扁平字段、routing.grouprouting.imagerouting.mentionHere 不会被静默转换, 启动时会直接拒绝。

完整默认配置示例(包含两套引擎参数,默认折叠):

展开完整默认配置
{
  "engine": "routing",
  "routing": {
    "direct": "trigger",
    "mention": "trigger",
    "mentionAll": "wait",
    "quote": "wait",
    "poke": "wait",
    "allMessage": "wait",
    "keywords": []
  },
  "willingness": {
    "maxScore": 100,
    "initialScore": 0,
    "decayHalfLifeSeconds": 600,
    "probabilityThreshold": 55,
    "probabilityAmplifier": 0.04,
    "replyCost": 35,
    "textGain": 12,
    "mentionGain": 100,
    "quoteGain": 15,
    "directGain": 40,
    "imageGain": 8,
    "pokeGain": 80,
    "interestKeywords": [],
    "forceKeywords": [],
    "keywordMultiplier": 1.2,
    "defaultMultiplier": 1,
    "hotWindowSeconds": 15,
    "warmWindowSeconds": 60,
    "hotDecayWeight": 0.3,
    "warmDecayWeight": 0.7,
    "mentionForce": false,
    "quoteForce": false,
    "directForce": false
  },
  "priority": 1000
}

未列出的字段使用插件默认值。配置写入 MILKY_WILL_POLICY 时必须是 JSON 字符串。

Home channel 与 cron

MILKY_HOME_CHANNEL 只影响 Hermes 系统消息和 cron 的默认出站目标,不参与入站 allowlist。 显式的 milky:group:<id>milky:dm:<id> 目标优先。

未配置 home channel 时不会回退到 origin、默认频道、群聊或私聊,也不会猜测目标。standalone cron 每次创建并关闭临时 Milky client,目前只支持无附件文本;媒体和文件输入返回 unsupported

日志

运行时日志使用 hermes_plugins.milky.* 标准 logger,并传播到 Hermes root。关键消息使用 event=milky.lifecyclemilky.actionmilky.ssemilky.inboundmilky.resourcemilky.outboundmilky.mutemilky.tool 标签;插件不创建独立日志文件、handler、异步队列 或脱敏后端。

常用查看命令:

hermes logs -f
hermes logs --level DEBUG -f
hermes logs gateway -f

Action、Tool 和出站日志保留结果分类、已知状态码和 duration_ms,不记录 token、Authorization、 完整 URL、请求/响应 body、消息正文、媒体引用、路径、文件内容、Tool 原始参数或结果。Tool 调用方 仍会收到既有 raw envelope。日志不可用或 handler 失败不改变连接、重连、Gate/Will、扣费、发送和 未知结果语义。

常用运维

Gateway 与 Hermes 状态

# 查看 Gateway 状态
hermes gateway status

# 重启 Gateway,使启动配置生效
hermes gateway restart

# 执行 Hermes 整体状态和深度健康检查
hermes status --deep
hermes doctor

日志与配置

# 查看最近的 Gateway 日志和错误
hermes logs gateway -n 100
hermes logs errors --since 30m

# 临时提高日志级别并实时跟踪
hermes logs gateway --level DEBUG --since 15m -f

# 列出日志文件,以及检查配置文件位置和有效性
hermes logs list
hermes config path
hermes config env-path
hermes config check
hermes config get security.redact_secrets

插件与 Milky smoke

# 查看已安装插件及启用状态
hermes plugins list

# 在源码 checkout 中执行只读 Milky smoke
uv run scripts/milky_smoke.py

# 生成用于提交 issue 的脱敏诊断摘要
hermes dump

milky_smoke.py 默认只执行登录、群列表、Bot 成员禁言同步和有界 SSE 连接。发送消息或上传文件 必须显式使用 --allow-write,并且目标还必须位于 MILKY_ALLOWED_CHATS 中;没有明确授权时不要 使用该选项。hermes dump 用于生成脱敏诊断摘要,不要把包含敏感配置的命令输出直接粘贴到公开 issue。

排查日志中的 chat key 脱敏

Hermes core 默认会对日志中的敏感字段进行脱敏。如果需要临时确认日志中的完整 chat_key,可用 Hermes CLI 关闭全局脱敏:

hermes config set security.redact_secrets false

修改后必须重启 Gateway;该配置只在进程启动时读取。排查完成后立即恢复脱敏:

hermes config set security.redact_secrets true

该开关影响 Hermes 全局的日志、工具输出和聊天响应,不只影响 Milky。关闭期间可能泄露 API key、 token 或密码,仅应在受控环境中短时使用。

功能与使用

消息与媒体

普通入站只处理 message_receive

  • friend 和 group 消息进入普通 Agent 流程;
  • temp 会话直接忽略;
  • Milky SSE GET /event 中的 message_recall、request、notice、lifecycle 和未知事件默认只观察,少数系统事件可作为上下文;
  • face segment 的正文占位符对非 emoji 表情 pack 优先使用随插件发布的本地 catalog 名称;未命中、冲突或目录不可用时回退原 face_id,缺失 ID 时使用 NOT SUPPORTED
  • 同一 chat 按顺序处理,wait 消息进入有界历史,trigger 时再交给 Hermes。

message_recall 的上下文行为如下:

  • 只有字段完整且 message_scenefriendgroup 时才登记;friend 写入 dm:<peer_id>,group 写入 group:<peer_id>,非法场景或 ID 只记录安全诊断;
  • 合法事件进入对应 chat 的有界 system context FIFO,在下一次同 chat triggerchannel_context 中按 ingress 顺序出现一次,格式为 <event message_recall> ...
  • operator_idoperator_id == sender_id 时显示 uid <sender_id> 撤回了消息 msg_seq <message_seq>;群聊仅在 operator_id != sender_id 时显示 管理员 uid <operator_id> 撤回了 uid <sender_id> 的消息 msg_seq <message_seq>,好友有不同操作人时不添加管理员角色;
  • 撤回事件不创建普通 Agent turn、不发送回复、不调用主动撤回工具,也不调用 get_message 或下载资源;插件只展示撤回元数据,不承诺恢复被撤回消息正文;
  • 该路径仍是 observe-only,不经过普通消息的 Gate/Will,也不扣 reply cost。fixture 和 fake host 测试不代表真实 Milky 服务端能力已被集成验证。

Agent 发送本地媒体时,在回复中写入:

MEDIA:<local_path>

例如 MEDIA:~/path/to/clip.mp4。显式调用 Hermes send_message 时,把同一指令放在 message 参数中。图片、语音和视频使用 Milky native segment,文档使用独立 file upload。

如果无需回复,只返回 [SILENT],不附加其他内容;该标记由 Hermes core 抑制消息投递,Milky plugin 不单独解析它。

需要模拟自然聊天节奏时,可把区分大小写且未转义的 [SPLIT] 单独放在一行,或直接放在普通 正文行中。独立行标记及其分隔边界会被删除,行中标记只删除自身;空段不发送,文本按原顺序 最多发送三条。超过三段时尾部合并到第三段,每个文本单元仍遵守既有长度边界,若实际文本消息 会超过三条,则在网络访问前整体拒绝。需要显示字面量 [SPLIT] 时使用 [[SPLIT]];语法完整的 CQ-compatible 或 unknown type CQ 候选中的标记不触发分段,malformed 或未闭合 CQ-like 内容中的标记 按普通文本规则处理。普通长文本没有有效 [SPLIT] 时继续使用原有长度分块。

回复同时包含文本分段和 MEDIA: 附件时,Hermes 先投递全部文本,再按提取顺序投递图片、语音、 视频和文档;当前不支持文本段与附件交错,[SPLIT] 不改变 MEDIA: 的独立交接。

Caution

MEDIA: 会读取本地文件并上传;默认只限制常规、非空且不超过 33554432 字节(32 MiB) 的文件,可用 MILKY_MAX_LOCAL_MEDIA_BYTES838860833554432 字节之间调整, 没有固定的安全目录隔离。Base64 编码会带来约 4/3 的请求体放大;内网连接不代表 Milky、代理或下游平台没有更低的服务端限制。

CQ image 仅用于本地 file:// URI 的 sticker,例如:

[CQ:image,file=file:///path/to/sticker.ext,type=sticker]

普通图片请使用 MEDIA:<local_path>。sticker 会在发送前转换为 base64://

本地路径、Pathfile://localhost 只在 plugin 边界读取一次并受上述本地字节上限约束; 格式合法的 http(s):// 和显式 base64:// 会原样传递,plugin 不下载、读取或解码,也不应用 本地文件大小检查。

Slash command

纯文本 /... 消息会在 canonical、去重和 Gate 之后分流,不进入 Will 历史或普通 Agent 正文。 合法命令交给 Hermes 既有命令分发;插件自身提供无参数 /milky,用于以可读摘要返回 Milky 实现信息。

QQ ToolSpec

插件固定提供 25 个 QQ ToolSpec,覆盖:

  • 群组和成员查询;
  • 文件、转发消息和私聊文件链接查询;
  • 戳一戳、点赞、撤回、禁言、踢人、退群和删好友;
  • 好友请求、入群请求和群邀请的接受/拒绝。

请求/邀请的接受和拒绝不会由通知、普通正文、关键词或 Will 自动触发,必须由 Agent 显式提供 完整参数。未知执行结果返回 transport_unknown,不自动重试或更新本地状态。

入站文件只显示为安全占位符,例如 [file:file_id=<file_id>,file_name=<file_name>,file_hash=<file_hash>];它不会被当作本地路径 或出站文件。

连接与生命周期

连接时依次完成登录信息、群列表和每个群的 Bot 成员状态同步,之后才启动事件流并开放普通 消息入口。断开时会取消 event、pipeline、TTL 任务,解除 sender/command 绑定,并关闭 HTTP/SSE 资源。

出站成功使用远端 data.message_seq 的稳定字符串作为 message_id;协议拒绝、传输未知、 malformed 和 unsupported 会保持明确失败分类。缺少消息序号时不会伪造稳定去重 ID。

API 与开发

插件不是以 Python package entry point 发布;Hermes 从根目录加载 plugin.yaml,再调用唯一 公开入口 __init__.py::register(ctx)

对象 作用
__init__.py::register(ctx) 解析启动配置,注册 platform、/milky、ToolSpec、standalone sender 和 QQ 指引 section。
__init__.py::register_tools(ctx) 委托 outbound.tools 注册固定 ToolSpec;注册阶段不联网。
MilkyAdapter 管理连接、停止、入站交接和出站委托。
MilkyOutboundSender 校验 group:/dm: 目标,格式化消息并调用 Milky Action/upload。
SlashCommandService 管理活动 Milky client,处理 /milky

支持 register_system_prompt_section 的 Hermes 宿主会在 after_memory 登记 hermes-plugin-milky.qq-platform-guidance,并在连接完成后使用已确认的 QQ UID 和昵称渲染 媒体、CQ-compatible、无回复和 bundled skill 指引。旧宿主仍可完成平台注册,但只获得首句提示。

详细的稳定模块边界见 ARCHITECTURE.md;可观察行为和测试要求见 openspec/。新建的未归档 change 会放在 openspec/changes/

贡献

欢迎通过 GitHub Issues 提问、报告 问题或提交 pull request。贡献前请阅读 CONTRIBUTING.mdARCHITECTURE.md

贡献要求:

  • 行为变化先补充脱敏契约或 fixture,再实现并增加回归测试;
  • 使用 uv 管理 Python 环境和依赖,不使用 pippipx 或直接调用 python/python3
  • 遵循 Google Python Style Guide,并保持各模块依赖边界;
  • 运行 uv run pytest -quv run ruff check .uv run ruff format --check .uv buildgit diff --check
  • 不提交 token、Authorization header、真实 QQ/群 ID、真实媒体 URL/路径、文件内容或敏感正文;
  • 使用中文 Conventional Commits。

PR 应说明变更范围、实际执行的命令、测试结果和未解决风险。若行为契约发生变化,请同步 更新对应的 OpenSpec change;安全问题不要公开粘贴到 issue。

维护者、致谢与许可证

维护者:ByteColtX。问题、功能建议和安全联系入口见 CONTRIBUTING.md

感谢 Hermes Gateway 的 platform adapter contract、Milky v1.3 协议生态,以及提供协议 fixture、测试和文档改进的贡献者。

本项目使用 MIT License,版权所有 © 2026 ByteColtX。完整条款见 LICENSE

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages