# 接入软件 > 面板里「接入软件」这一页怎么用,以及怎么让别人(或者你自己)把一个软件真正接进来。 ## 这一页是干什么的 把「能和 AI记忆 配合的外部软件 / 通道」集中列出来:QQ 机器人、其他聊天通道、消息桥、导出工具…… 页面上有: - 右上角一行小字 **申请收录软件 ↗**:和插件市场一样,点了直接去 GitHub 提交收录申请 (仓库里的 Issue 模板 `integration_submission.md`)。 - 一个**搜索框**:按名称、说明、作者、分类、标签、能力搜;空格分隔多个关键词 = 必须同时命中。 - **卡片列表**:每个软件一张卡,显示名称、版本、分类、标签、说明、作者、主页链接。 - **「怎么把一个软件接进来?」**:折起来的一段说明,展开有步骤和示例清单。 ## 一、只登记(零代码,谁都能做) 软件本身不用改任何东西,只要放一份**清单 JSON**: 1. 打开数据目录下的 `integrations` 文件夹(面板里「这里还空着」那段会显示完整路径, 默认是 `/companion-memory/integrations`,一般是 `C:\Users\你的用户名\.dsh\companion-memory\integrations`)。 2. 新建一个 `.json`,也可以先在页面点「生成示例清单」拿 `example.json` 照着改。 3. 回面板点「刷新」,卡片就出现在列表里。 字段(只有 `id` 和 `name` 是必须的,其余写了更好搜): | 字段 | 说明 | | --- | --- | | `id` | 唯一标识,建议英文短名(文件名兜底) | | `name` | 显示名称 | | `description` | 一句话说明它能干什么(也可写 `desc`) | | `version` | 版本号 | | `author` | 作者 / 维护者 | | `category` | 分类,例如 通道 / 工具 / 记忆 | | `tags` | 字符串数组,方便搜索 | | `capabilities` | 字符串数组,例如 `["读消息", "发消息"]` | | `homepage` | 主页链接(只认 http/https) | | `entry` | 预留:以后版本用来自动加载桥接脚本,**这一版不会执行** | | `plugin` | **可选,插件型应用的推荐写法**:填提供这个应用的 DSH 插件模块名(例如 `@local/ai-voice`)。写了以后,卡片开关会直接加载/卸载整个插件,而不是只切应用内部的功能开关。 | 示例(和面板里「生成示例清单」生成的那份一致): ```json { "id": "example-software", "name": "示例软件", "description": "把这份 JSON 改成你要接入的软件:说清它是什么、能干什么。", "version": "0.1.0", "author": "你的名字", "category": "通道", "tags": ["示例", "改我"], "capabilities": ["读消息", "发消息"], "homepage": "https://github.com/your-name/your-integration" } ``` > 清单只是一份**描述**,插件不会执行里面的任何代码;一份 JSON 写坏了只会被跳过,不影响其它条目。 ### 开关和打开后的页面,插件自带 不用在清单里写 `statusUrl` / `enabledUrl`,也不用自己做 UI:每张卡片右下角的「开关」滑条和「打开」按钮由 AI记忆 插件统一生成,开关状态默认由插件记住(`<数据根目录>/integrations-state.json`,默认开)。点「打开」进入的应用页也是同一套「← 返回 + 应用名 + 右上角总开关」样式;应用没有自带界面时,插件会显示一个自带页面(说明 + 能力 + 开关)。只有应用自己想接管开关时,才需要写 `statusUrl` / `enabledUrl`。 **插件型应用(清单里写了 `plugin` 的)走另一套**:卡片开关 = 官方插件页那个开关,直接控制插件的加载/卸载。 - 关 → 改 profile 的 `cordis.patch.yml`,宿主热加载后插件真的卸载(它的接口变成 404),卡片还在、「打开」按钮隐藏; - 开 → 插件重新加载,卡片恢复,「打开」按钮回来; - 插件内部如果还有功能开关(例如 AI语音 页面里的总开关),也联动:关 = 卸载插件并退回上一页,开由卡片开关负责; - 插件卸载不会删数据:音频、参考音、配置这些都留在各自的数据目录里。 以后新插件想接入时,只要在清单里加一行 `"plugin": "<插件模块名>"`,卡片就会自动按这套运行,不需要改 AI记忆 的代码。 ## 二、桥接(软件把内容写进 AI记忆) 想让 QQ 消息、邮件、日程这些东西真的进入某个对话的记忆,做法是让那个软件调本插件的本地接口 (同源 / 回环请求,和面板用的是同一套,默认只接受 loopback 或受信任的宿主来源): ```http POST /companion/api/memory/add content-type: application/json { "session": "<目标对话的 sessionId>", "text": "原话或重要信息,会原样进活跃记忆", "tags": ["来源:QQ", "群聊"] } ``` 其它常用的写入点: | 路由 | 用途 | | --- | --- | | `POST /companion/api/memory/add` | 加一条活跃记忆 | | `POST /companion/api/emotion` | 更新情绪表 | | `POST /companion/api/speaker` | 登记/切换说话人(多人场景) | | `POST /companion/api/doc` | 写人格文档字段 | | `GET /companion/api/state` | 读当前对话的整体状态 | | `POST /companion/api/session/say` | 往指定对话里发一条用户消息 | 要点: - 所有写入接口都要带 `session`(query 参数或 JSON body),并且要**先在那个对话里开启记忆**,否则会返回「本对话未开启伴侣记忆」。 - 桥接进程如果是别的程序(例如 QQ 插件),照旧走 localhost 就行;跨机器访问默认会被同源校验挡掉。 - 数据仍然只落在`/companion-memory/sessions/<对话>/`,不会外发。 ## 三、做成 DSH 插件(长期方案) 如果那个软件本来就在 DSH 里跑(比如 QQ 插件),最稳的是**它自己做一个 DSH 插件 / 扩展**, 在进程内直接调本插件暴露的能力,而不是在「接入软件」页面里执行代码: - 监听消息事件 → 调 `/companion/api/memory/add` 之类接口把内容写进记忆; - 需要面板里的可视化,就照这份仓库的 `client.js` 写一个 `conversation.view` 或侧边栏面板; - 需要区分群友,就先用 `/companion/api/speaker` 登记说话人,再记记忆和好感度。 这样:「接入软件」页面 = **目录与说明**,真正的桥接 = **各自插件自己的事**。 插件这边永远不执行别人的代码,安全边界清楚。 ## 常见问题 - **放好清单了还是空?** 点「刷新」;如果提示「清单接口还没生效」,说明插件的宿主侧还没重载——重载一次 AI记忆 插件或重启 DSH 即可。 - **坏 JSON 会让整页挂掉吗?** 不会。单份坏清单只跳过它自己。 - **能重复吗?** 同一个 `id` 的多份清单都会显示;建议一个软件一份。 - **能删除吗?** 直接删掉 `integrations` 里的那个 JSON,再点刷新。