Skip to content

整合包开发

整合包(Pack)是一组 Friend + Application 的打包集合。它让用户一键装上一套搭配好的插件组合,不用一个个找。整合包本身不含可执行代码——它只是一个 manifest 加若干子插件目录。

  • 你做了好几个风格统一的 Friend,想打包成“系列”发布
  • 你做了一个 Friend 加一个配套的 Application(比如动漫风伙伴 + 动漫风 TTS),想让用户一次装齐
  • 你想给新用户一个“开箱即用”的推荐组合

整合包不是必须的——每个插件都能独立安装。它只是方便。

{
"id": "com.example.pack.anime_collection",
"type": "pack",
"name": "动漫合集",
"description": "三个动漫风格伙伴 + 一个动漫风 TTS",
"version": "1.0.0",
"author": "你的名字",
"icon": "icon.png",
"platforms": {
"supported": ["android", "windows", "linux", "macos"]
},
"plugins": {
"friend": [
{ "id": "com.example.friend.hatsune", "path": "friend/hatsune" },
{ "id": "com.example.friend.rem", "path": "friend/rem" },
{ "id": "com.example.friend.asuka", "path": "friend/asuka" }
],
"application": [
{ "id": "com.example.app.anime_tts", "path": "application/anime_tts" }
]
},
"recommended": {
"defaultFriend": "com.example.friend.hatsune",
"defaultApplication": ["com.example.app.anime_tts"]
}
}
字段 类型 说明
friend object[] 包含的 Friend 子插件列表
application object[] 包含的 Application 子插件列表

每条目:

字段 类型 必填 说明
id string 是 子插件 id
path string 是 子插件在 ZIP 内的目录路径

path 指向 ZIP 内的一个目录,目录内要有该子插件自己的 manifest.json 和资源文件。安装时容器把每个子插件目录复制到 plugins root——和单独安装那个插件效果一样。

字段 类型 说明
defaultFriend string 装完后默认激活的 Friend id
defaultApplication string[] 装完后默认启用的 Application id 列表

这是给用户的便利——装完整合包后不用手动去切 Friend 和启用 Application,容器自动按推荐设置。

Pack 的 system / uninstallable / defaultEnabled 在 PackManifest 构造函数里硬编码:

  • system: false(整合包永远不是系统插件)
  • uninstallable: true(用户可以卸载整合包)
  • defaultEnabled: false(整合包本身不需要 enable,是它的子插件需要)

manifest 里写了这三个字段也会被忽略。

整合包的 ZIP 里,manifest.json 在根目录,子插件是目录(不是 zip):

com.example.pack.anime_collection.moodpack (ZIP)
├── manifest.json
├── icon.png
├── friend/
│ ├── hatsune/
│ │ ├── manifest.json
│ │ ├── system_prompt.txt
│ │ ├── emoji_mapping.json
│ │ └── identity.json
│ ├── rem/
│ │ ├── manifest.json
│ │ ├── system_prompt.txt
│ │ └── emoji_mapping.json
│ └── asuka/
│ ├── manifest.json
│ ├── system_prompt.txt
│ └── emoji_mapping.json
└── application/
└── anime_tts/
├── manifest.json
└── main.dart

每个子插件目录的结构和它单独发布时完全一样——有自己的 manifest.json 和必需文件。path 字段对应 ZIP 内的路径,比如 friend/hatsune。

容器安装整合包时(installPack()):

  1. 读整合包的 manifest.json,解析 plugins.friend 和 plugins.application
  2. 对每个引用的子插件,把 <zip内path> 目录复制到 plugins root:
    • Friend → <safeId>.moodfriend/
    • Application → <safeId>.moodapp/
  3. 把整合包目录本身也复制到 plugins root:<safeId>.moodpack/
  4. 调 PluginManager.refresh() 重新扫描

如果某个子插件目录在 ZIP 里不存在,容器会跳过它(不报错,但不安装那个子插件)。所以打包时检查 path 和实际目录一致。

卸载整合包会删除整合包目录本身。子插件不会被自动卸载——它们已经是独立的插件了,用户可以在插件管理页单独管理。这个设计让用户可以“装整合包 → 只卸载不喜欢的子插件 → 保留其余”。

以“动漫合集”为例,准备文件:

anime_collection/
├── manifest.json
├── icon.png
├── friend/
│ ├── hatsune/
│ │ ├── manifest.json
│ │ ├── system_prompt.txt
│ │ └── identity.json
│ ├── rem/
│ │ ├── manifest.json
│ │ └── system_prompt.txt
│ └── asuka/
│ ├── manifest.json
│ └── system_prompt.txt
└── application/
└── anime_tts/
├── manifest.json
└── main.dart

打包:

Terminal window
cd anime_collection
zip -r ../com.example.pack.anime_collection.moodpack .
# 验证
unzip -l ../com.example.pack.anime_collection.moodpack
# manifest.json 在根目录,friend/hatsune/manifest.json 等在对应路径
  1. 子插件 id 要和 path 对应的目录内 manifest id 一致。验证脚本会交叉校验。
  2. 子插件可以是独立发布的插件的副本。你可以把已经单独发布过的 Friend 放进整合包——用户单独装或通过整合包装都是同一个 id,不会重复安装(容器按 id 去重,同 id 会覆盖旧版本)。
  3. 整合包的 platforms 应该是所有子插件的交集。如果某个子插件只支持 Android,整个整合包就不应该在 Windows 上展示给用户安装。
  4. ZIP 根目录直接放 manifest.json 和子插件目录,不要套一层外层目录。