Skip to content

manifest.json 规范

每个插件包的 ZIP 根目录必须有一个 manifest.json。它是容器认识插件的入口——告诉容器这是什么插件、叫什么、支持哪些平台、内部有哪些文件。

字段 类型 必填 默认值 说明
id string 是 — reverse-DNS 风格插件 id
type string 是 — "friend" / "application" / "pack"
name string 是 — 展示名称
description string 是 — 一句话描述
version string 是 — 语义化版本号
author string 是 — 作者或组织名
icon string 否 null 包内图标资源的相对路径
system boolean 否 false 系统插件(不可卸载),社区插件别设
uninstallable boolean 否 true 是否允许用户卸载
defaultEnabled boolean 否 false 安装后是否默认启用
platforms object 否 空对象 平台兼容性矩阵,见下
"platforms": {
"supported": ["android", "wearos", "windows", "linux", "macos"],
"optimized": ["android"],
"fallback": { "windows": "无震动反馈" }
}
字段 类型 必填 说明
supported string[] 是 支持运行的平台 id 列表;当前平台不在里面则拒绝 enable
optimized string[] 否 最佳体验平台,信息性字段
fallback object 否 平台降级说明,{平台id: 说明文字}

合法平台 id:android / wearos / windows / linux / macos。传别的值会在加载时抛 ArgumentError。

公共字段由 PluginManifest.parseBase() 解析。id / type / name / description / version / author 这六个字段缺一个或类型不对都会抛 FormatException——插件加载失败,出现在插件管理页的“加载失败”列表里。platforms 缺失时退化为空(任何平台都不支持,但插件仍会加载展示)。

{
"id": "moodpet.friend.default_smiley",
"type": "friend",
"interfaces": {
"personality": "system_prompt.txt",
"expression": "emoji_mapping.json",
"identity": "assets/identity.json",
"voice": null,
"ui": null,
"rules": null
},
"dependencies": {
"minContainerVersion": "1.0.0",
"plugins": [],
"services": []
},
"configSchema": {
"greeting": {
"type": "string",
"default": "嗨,我在呢",
"label": "打招呼语"
}
}
}
字段 类型 必填 说明
personality string 是 system_prompt.txt 的相对路径,加载时必读
expression string 否 emoji_mapping.json 的相对路径,离线模式用
identity string 否 identity.json 的相对路径,展示元数据覆盖
voice string 否 语音配置相对路径(社区扩展)
ui string 否 UI 样式配置相对路径(社区扩展)
rules string 否 规则目录相对路径(社区扩展)

personality 是唯一必填的 interface——没有它 Friend 无法工作。其他都是可选的社区扩展点。

字段 类型 默认 说明
minContainerVersion string null 要求的最低容器版本(semver 字符串)
plugins string[] [] 依赖的其他插件 id
services string[] [] 依赖的容器服务名,如 ["tts"]

定义用户可编辑的插件配置项。每个 key 是配置字段名,value 是字段定义:

"configSchema": {
"greeting": {
"type": "string",
"default": "嗨,我在呢",
"label": "打招呼语",
"secret": false
},
"language": {
"type": "select",
"default": "zh",
"label": "语言",
"options": ["zh", "en"]
}
}
字段 类型 必填 说明
type string 是 "string" / "boolean" / "number" / "select"
default any 否 默认值
label string 否 设置 UI 里显示的标签
secret boolean 否 是否敏感值(API key 等),UI 会掩码显示
options string[] 否 type: "select" 时的可选项

容器的插件设置 UI 会根据 configSchema 自动生成表单。greeting 字段的 default 会被用作伙伴首次问候语。

{
"id": "moodpet.app.elevenlabs_tts",
"type": "application",
"entry": "main.dart",
"language": "dart",
"overrides": {
"services": { "tts": true },
"ui": {}
},
"provides": {
"triggers": ["on_reply"],
"actions": ["speak"],
"interfaces": ["tts"]
},
"dependencies": {
"minContainerVersion": "1.0.0",
"plugins": [],
"services": []
},
"requirements": {
"webview": null,
"permissions": ["internet"],
"minPlatformVersion": { "android": "8.0" },
"runtime": { "dart": ">=3.0" }
},
"resources": {
"minRam": 128,
"minDisk": 10,
"maxCpuCores": null
},
"configSchema": {
"apiKey": {
"type": "string",
"label": "ElevenLabs API Key",
"secret": true
}
}
}
字段 类型 必填 说明
entry string 是 入口文件相对路径,如 main.dart / python/main.py
language string 是 实现语言:dart / python / binary

容器按 language 选运行时:dart 走 Flutter 插件运行时,python 走 Python 子进程,binary 直接执行。entry 指向的文件必须在 ZIP 内存在,否则验证脚本报错。

声明这个插件接管哪些容器服务 / UI 页面:

字段 类型 说明
services object {服务名: bool},如 {"tts": true} 表示接管 TTS
ui object {页面名: bool},如 {"home_page": true} 表示接管首页

接管后,原内置服务/页面停止贡献,由这个插件替代。一个服务同时只能被一个启用的 Application 接管。

声明插件暴露的能力:

字段 类型 说明
triggers string[] 响应哪些事件触发,如 ["on_reply"]
actions string[] 提供哪些动作,如 ["speak"]
interfaces string[] 实现哪些接口,如 ["tts"]

其他插件或容器通过这些声明发现和调用本插件。

字段 类型 说明
webview string 需要的 WebView 版本
permissions string[] 需要的系统权限,如 ["internet", "microphone"]
minPlatformVersion object {平台id: 最低版本字符串}
runtime object 运行时依赖,{语言: 版本约束}
字段 类型 说明
minRam number 最低内存(MB)
minDisk number 最低磁盘(MB)
maxCpuCores number 最多使用 CPU 核数

和 Friend 的 configSchema 格式完全一样。Application 用它声明用户需要配置的字段(比如 API key)。

{
"id": "moodpet.pack.anime_collection",
"type": "pack",
"plugins": {
"friend": [
{ "id": "moodpet.friend.hatsune", "path": "friend/hatsune" },
{ "id": "moodpet.friend.rem", "path": "friend/rem" }
],
"application": [
{ "id": "moodpet.app.anime_tts", "path": "application/anime_tts" }
]
},
"recommended": {
"defaultFriend": "moodpet.friend.hatsune",
"defaultApplication": ["moodpet.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 列表

Pack 的 system 永远是 false,uninstallable 永远是 true,defaultEnabled 永远是 false——这三个字段在 PackManifest 构造函数里硬编码,manifest 里写了也会被忽略。

验证脚本会检查插件包内 manifest.json 的 id 和 type 必须和同目录 .meta.json 的 id 和 type 完全一致。不一致的话 CI 会红,PR 合不进去。

version 用语义化版本:MAJOR.MINOR.PATCH,比如 1.0.0、1.2.3。

  • 破坏性变更(manifest 字段不兼容、system_prompt 完全重写)→ 升 MAJOR
  • 新增功能(加 configSchema 字段、加 emoji)→ 升 MINOR
  • 修复(调文案、修 bug)→ 升 PATCH

客户端的 UpdateChecker 用 semver 比较判断有没有新版本——1.2.0 > 1.1.0 会提示更新。非数字段会退化成字符串比较,所以别用 1.0.0-beta 这种带后缀的格式(-beta 会被剥掉再比,可能误判)。