name: gscore-adapter-development description: > 当用户要求"帮我写一个 GsCore 适配器"、"把 XXX 平台接入早柚核心 / gsuid-core"、 "怎么连接 core 的 WebSocket"、"MessageReceive / MessageSend 怎么填"、 "上报消息怎么写"、"core 发回来的消息怎么解析"、"base64:// 和 link:// 有什么区别"、 "按钮 / Markdown 怎么适配到我的平台"、"node 合并转发怎么处理"、"双 ID 平台 group_id 怎么拼"、 "QQ 官方 msg_id / msg_seq 时序问题"、"为什么我的命令前缀被吞了 / 没被识别"、 "适配器 token 鉴权 / 断线重连怎么写"、"log_ 日志包是什么"、 "进退群 / 戳一戳元事件怎么上报"、"wait_recall 回执 / unsend 撤回 / ban 禁言怎么在适配器实现"时触发此 SKILL。 凡是"把某个聊天平台接入 GsCore"或"调试 core 与适配器之间通信"的任务都应优先读取此 SKILL。
为 GsCore(早柚核心 / gsuid-core)机器人框架编写平台适配器的完整指南。适配器是运行在 Bot 平台一侧、通过 WebSocket 与 core 通信的连接器(区别于运行在 core 内部的"插件")。 涵盖:早柚协议总览与二进制帧、三类数据结构(Message / MessageReceive / MessageSend / Button)、 bot_id 的三层语义(路由 ID / 平台 ID / bot_self_id)、连接生命周期(token 鉴权 / 心跳 / 断线重连 / 收发双协程骨架)、上报消息(平台→core,每种 content 类型如何构造、user_pm 映射、is_tome 机制、 命令前缀处理)、发送消息(core→平台,recv 循环按 bot_id 路由、每种 type 的落地处理)、 base64:// 与 link:// 双形态图片处理、按钮与 Markdown 跨平台映射、node 合并转发、双 ID 平台 (villa / heybox)、QQ 官方时序、回调按钮上报、log_ 日志包、元事件上报(user_join_group / user_exit_group / poke 三种标准事件)、echo 撤回回执、撤回 / 禁言控制包、易错点红线清单与端到端完整示例。
GsCore 适配器开发完整指南(核心入口)
什么是"适配器"? 在 GsCore 生态里有两类扩展:
- 插件(Plugin):跑在 core 内部,用
SV+ 触发器响应命令、画图、读写数据库——见同目录gscore-plugin-development。- 适配器(Adapter):跑在 某个聊天平台一侧(NoneBot2 / Koishi / 原生 SDK / 你自己的 Bot 进程), 通过 WebSocket 把平台收到的消息上报给 core,再把 core 下发的消息翻译成平台 API 调用发出去。 本 SKILL 只讲适配器。
一句话:适配器是 core 与聊天平台之间的「翻译官 + 邮差」,它不处理任何业务逻辑,只做 协议转换和消息搬运。
本 SKILL 按章节拆分为「主入口 +
references/子文档」。需要某专题细节时,顺着下文相对路径 按需ReadFile对应文件,不要一次性把所有内容塞进上下文。
文档目录索引
| 章节 | 主题 | 链接 |
|---|---|---|
| 一 | 早柚协议总览(WebSocket、/ws/{bot_id} 路由、二进制帧、收发全景图、与插件的区别) |
references/01-protocol-overview.md |
| 二 | 数据结构详解(Message / MessageReceive / MessageSend / Button 全字段表 + bot_id 三层语义) |
references/02-data-structures.md |
| 三 | 连接生命周期(token 鉴权、心跳、断线重连、收发双协程骨架、最小可运行客户端) | references/03-connection-lifecycle.md |
| 四 | 上报消息(平台→core,MessageReceive 每种 content 类型构造 + user_pm 映射 + is_tome 机制) |
references/04-report-message.md |
| 五 | 发送消息(core→平台,recv 循环按 bot_id 路由 + 每种 type 落地处理) |
references/05-send-message.md |
| 六 | 按钮与 Markdown 适配(Button 全字段、单行/多行布局、各平台映射实例、template_* 模板) |
references/06-buttons-and-markdown.md |
| 七 | 图片与多媒体(base64:// vs link:// 双形态、image_size、语音/视频/文件、上传图床) |
references/07-image-and-media.md |
| 八 | 特殊平台适配要点(双 ID 平台 / group 段 / QQ 官方 msg_id-msg_seq 时序 / 回调按钮上报 / 文件上报) |
references/08-special-platforms.md |
| 九 | 端到端完整示例(最小适配器 → OneBot v11 全功能适配器) | references/09-full-adapter-example.md |
| 十 | 易错点与红线清单(二进制帧、bot_id 路由、双形态图片、node、log 包、msg_id 时序…) | references/10-pitfalls.md |
| 十一 | 元事件上报与控制消息(meta 标准三事件 进群/退群/戳一戳 上报、echo 撤回回执、excute_delete_message 主动撤回、excute_ban_user 禁言) |
references/11-meta-and-control.md |
推荐开发流程(按需跳转)
- 先建立心智模型:读 一、协议总览,搞清「适配器干什么、数据怎么流」。
- 背下数据结构:读 二、数据结构,尤其是 bot_id 的三层语义——这是最容易搞错的地方。
- 先把连接跑起来:照 三、连接生命周期 的双协程骨架建立 WS 连接,能 ping 通即可。
- 打通上报链路:读 四、上报消息,让平台的文本消息能传到 core 并触发命令。
- 打通下发链路:读 五、发送消息,让 core 回复的文本/图片能发回平台。
- 补齐富媒体:图片走 七、图片与多媒体,按钮/MD 走 六、按钮与 Markdown。
- 处理平台怪癖:双 ID、QQ 时序、回调按钮等看 八、特殊平台。
- 接元事件与撤回/禁言:要上报进群/退群/戳一戳三种标准元事件、或支持插件
wait_recall/unsend/ban,看 十一、元事件与控制消息。 - 对照完整示例:随时参考 九、端到端示例。
- 交付前自查:逐条过 十、易错点红线 与 十一、自查清单。
关键概念速记(先看这一段再决定读哪一章)
- 两条独立链路:上报(平台→core,发
MessageReceive)和下发(core→平台,收MessageSend), 在适配器里通常是两个并行协程:一个监听平台事件往 core 推,一个监听 core 下发往平台发。详见 §1.3。 - 帧是二进制不是文本:core 用
websocket.receive_bytes()读、send_bytes()写,适配器必须发二进制帧 (msgspec.json.encode(...)得到bytes直接ws.send(bytes))。发文本帧会解析失败。详见 §1.2 与 §10 红线 1。 - bot_id 有三层,别搞混:① 路由
/ws/{bot_id}(连接级,如NoneBot2,对应Event.WS_BOT_ID); ② 每条消息的bot_id(平台级,如onebot/qqgroup/onebot:red,下发时按它路由到对应平台); ③bot_self_id(机器人账号 ID)。详见 §2.2。 bot_id含:会被 core 拆分:core 用:前的部分做event.bot_id,完整值留在real_bot_id(如onebot:red→event.bot_id='onebot')。这是同一协议多实现共用触发器的机制。详见 §2.2。- 图片永远是双形态:core 下发的
image既可能是base64://...也可能是link://...(开了"自动转链接"时), 适配器两种都必须处理,否则用户一开转链接就发不出图。详见 §7.1 与 §10 红线 3。 is_tome靠at段触发:上报时若把一条at段的data填成bot_self_id,core 会判定"@了机器人" (is_tome=True);私聊(direct)则 core 自动置is_tome=True。详见 §4.4。- 命令前缀处理在两边都有:core 端会按
command_start削掉前缀;适配器上报前不要自作主张删命令前缀 (除非平台特性需要,如 QQ 官方把/当指令)。详见 §4.5。 log_{LEVEL}是日志回显包:core 想在适配器侧打日志时,发一条bot_id == 路由BOT_ID且content[0].type为log_INFO/WARNING/ERROR/SUCCESS的包,适配器只需按等级打印data,不要当普通消息发。详见 §5.6。- 双 ID 平台用
-拼接 group_id:米游社大别野、黑盒等需要两个 ID 才能定位会话的平台,上报时group_id = f"{villa_id}-{room_id}",下发时再split('-')拆回。core 还会把group类型段附在末尾辅助定位。详见 §8.1。 node是合并转发,不能嵌套:node的data是List[Message],多数平台不支持原生合并转发, 需要遍历逐条发送。详见 §5.4。- 元事件 / 撤回 / 禁言走专门通道:标准元事件仅三种(
user_join_group/user_exit_group/poke,data字段跨平台统一,其他事件不做适配),上报为单段Message("meta-<事件名>", data);MessageSend.echo非空时发完消息必须回执recall_message_id;excute_delete_message/excute_ban_user是下行控制包,按bot_id调平台撤回/禁言 API、不当普通消息发。详见 §11。
关联文档(同仓库其他位置)
- 插件开发(core 内部业务逻辑,与适配器互补):
docs/skills/gscore-plugin-development/SKILL.md - 协议原始描述(精简版,本 SKILL 是其超集):
GenshinUID-docs/docs/CodeAdapter/Protocol.md、Pack.md - core 侧关键源码定位:
- WebSocket 入口 / token 鉴权 /
/api/send_msg:gsuid_core/core.py - 数据结构定义:
gsuid_core/models.py、gsuid_core/message_models.py - 上报内容解析为
Event:gsuid_core/handler.py的msg_process()/get_user_pml() - 下发消息编码(
base64:///link:///node/image_size):gsuid_core/segment.py、gsuid_core/bot.py的target_send() - 日志回显包:
gsuid_core/gs_logger.py
- WebSocket 入口 / token 鉴权 /
- 官方参考实现(强烈建议对照阅读):
- 多平台全功能适配器:
GenshinUID/GenshinUID/client.py(下发 + 撤回回执)+__init__.py(上报) - 元事件多适配器映射拆分:
GenshinUID/GenshinUID/meta_event.py - 撤回/禁言平台 API 分支:
GenshinUID/GenshinUID/send_utils.py的del_msg/excute_ban_user - 撤回 / 元事件协议契约:
gsuid_core/RECALL_AND_META_EVENTS.md - 最小可运行测试客户端:
gsuid_core/client.py
- 多平台全功能适配器: