人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手【免费下载链接】airi 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器目标是接近 Neuro-sama 的高度支持实时语音聊天、Minecraft 和 Factorio 游玩支持 Web / macOS / Windows。项目地址https://gitcode.com/moeru-ai/airi点击查看免费下载本篇以 Stage Tamagotchi 桌面应用内置的activation-planner-provider示例扩展为核心讲解 AIRI 插件体系Phase 2如何通过extension.airi.json清单中的kits.provides/kits.uses静态声明在扩展代码执行前完成依赖解析、冲突检测与加载排序并最终生成确定性的unloadOrder/loadOrder激活计划。读完本文你可以独立编写声明 Kit 依赖的 Provider/Consumer 扩展理解激活规划器Activation Planner的算法细节并能对照源码与测试用例验证其排序与诊断行为。示例扩展是什么activation-planner-provider是 Stage Tamagotchi 主进程扩展宿主Extension Host附带的一个最小示例位于Provider 目录包含 README、extension.airi.json 与 activation-planner-provider.mjsConsumer 目录与 Provider 并排存放负责声明对同一 Kit 的依赖两者的配合关系来自 示例总览devtools-sample-plugin验证基础扩展生命周期与权限activation-planner-provider与activation-planner-consumer则用于验证依赖规划dependency planning。Provider 在自己的清单中声明提供 Kitdev.airi.example-activation版本1.0.0Consumer 声明以版本区间^1.0.0使用同一个 Kit。Host 会保证先加载 Provider再加载 Consumer系统停止时则先停止 Consumer再停止 Provider并且当 Consumer 仍依赖它时Host 会拒绝禁用或卸载 Provider。需要强调一个边界该示例没有运行时的 Kit 实现。它的kits.provides条目只是一条静态的 Phase 2 声明运行时 Kit 注册runtime Kit registration属于 Phase 3不在当前示例范围内。示例入口 activation-planner-provider.mjs 的全部逻辑就是打印一条启动日志import { defineExtension } from proj-airi/plugin-sdk export default defineExtension({ id: activation-planner-provider, setup() { console.info([activation-planner-provider] setup) }, })实操步骤在 Extension Host Inspector 中复现按 Provider README 与 Consumer README 的步骤在 Stage Tamagotchi 中验证依赖规划打开 Stage Tamagotchi 内的/devtools/plugin-host页面Extension Host Inspector实现位于 plugin-host.vue可由 开发者设置页 跳转进入通过Import Folder导入activation-planner-provider目录再导入旁边的activation-planner-consumer目录启用 Provider启用 Consumer触发加载已启用的 ExtensionsLoad the enabled Extensions。导入的扩展目录会被复制到托管扩展根目录。从 宿主启动代码 看该根目录为userData/extensions/v1app.getPath(userData)之下每个扩展一个子目录清单文件名固定为extension.airi.json见 registry.ts 中的extensionManifestFileName。导入完成的扩展保持禁用状态需要显式启用后才会进入激活计划。两个清单文件的完整解读Provider 清单声明提供的 Kitextension.airi.json 完整内容{ manifestVersion: 2, kind: manifest.extension.airi.moeru.ai, id: activation-planner-provider, version: 1.0.0, engines: { airi: *, runtimes: [ electron ] }, entrypoints: { electron: ./activation-planner-provider.mjs }, permissions: {}, kits: { provides: [ { id: dev.airi.example-activation, version: 1.0.0, exposure: local-only } ] } }结合清单 schemashared/types.ts 中的extensionManifestV2Schema逐字段说明字段示例值约束与含义manifestVersion2必须是字面量2当前 Host 消费的契约版本kindmanifest.extension.airi.moeru.ai类型判别符用于识别 AIRI Extension 清单idactivation-planner-provider稳定的扩展标识最长 255 字符只允许小写字母/数字开头的[a-z0-9._-]文件安全命名且不能是 Windows 保留设备名version1.0.0扩展包版本必须是精确的语义化版本semver.valid校验engines.airi*AIRI 兼容区间任意合法 semver rangeHost 用semver.satisfies(airiVersion, range, { includePrerelease: true })校验engines.runtimes[electron]支持运行时取值为electron/node/web不可重复entrypoints.electron./activation-planner-provider.mjs运行时入口相对路径以清单所在目录解析每个声明的 runtime 都必须有对应 entrypoint 或defaultpermissions{}权限上限声明本示例不申请任何权限kits.provides[].iddev.airi.example-activationKit 契约标识非空字符串kits.provides[].version1.0.0Provider 实现的精确版本同样是 exact semantic version 校验kits.provides[].exposurelocal-only传输边界取值为local-only/remote-observable/remote-callableschema 还要求provides与uses中同一个 Kit id 只能声明一次Declare each provided Kit once.整个清单为strictObject出现未定义字段会直接解析失败。清单解析入口是 manifest.ts 中的parseExtensionManifest——实际路径为 packages/plugin-sdk/src/plugin-host/shared/manifest.ts解析失败时保留字段路径用于诊断。Consumer 清单声明依赖的 KitConsumer 的 extension.airi.json 与 Provider 结构几乎相同差异集中在kits{ kits: { uses: [ { id: dev.airi.example-activation, version: ^1.0.0 } ] } }uses条目的字段对应ExtensionUsedKitDeclaration类型id要消费的 Kit 契约标识与 Provider 声明的 id 完全匹配versionConsumer 接受的语义化版本区间如^1.0.0与provides的精确版本形成区间 vs 精确值的匹配关系optional可选默认false为true时允许该 Kit 缺失或不兼容扩展仍可启动为false本示例情况时Provider 缺失或版本不兼容会直接阻断激活计划。Consumer 示例同样不做运行时 Kit 调用kits.uses只建立静态的 Phase 2 依赖关系。激活规划器从声明到确定性执行顺序上述静态声明由 planExtensionActivation 消费——准确路径是 packages/plugin-sdk/src/plugin-host/activation-plan.ts。它接收完整的当前快照与目标意图返回一份确定性计划或一组结构化诊断全程没有运行时副作用不修改配置或生命周期状态。输入与输出ActivationPlannerInput的字段installedManifests当前可用的全部已安装清单loadedManifests当前存活会话使用的清单proposedEnabledExtensionIds变更后的完整启用意图不是增量restartExtensionIds可选本次需要重启的已加载扩展hostProvidedKitsHost 自身保留并提供、扩展不可抢占的 Kit 契约runtime/airiVersion/systemEnabled运行时、AIRI 版本与系统级开关。成功时返回的ExtensionActivationPlan包含unloadOrder当前会话的停止顺序Consumer 优先、loadOrder目标会话的启动顺序Provider 优先、restartExtensionIds自动扩展为依赖闭包以及每条 Kit 依赖的resolutions解析记录谁消费、要什么区间、解析到哪个 Provider、是否可选。规划流程的四个阶段合法性与兼容性诊断。逐条检查重复安装/重复加载的扩展 id、启用但未安装的扩展、incompatible-runtime清单engines.runtimes不含目标运行时、incompatible-airi-version当前 AIRI 版本不满足engines.airi区间。诊断码全集见源码中的ActivationDiagnosticCodeduplicate-installed-extension、duplicate-loaded-extension、enabled-extension-not-installed、incompatible-airi-version、incompatible-runtime、duplicate-extension-provider、host-kit-id-conflict、missing-required-kit、incompatible-kit-version、dependency-cycle、restart-extension-not-loaded。Provider 收集与冲突检测。先放入 Host 保留的 Kit再按启用扩展的字典序扫描kits.provides扩展试图提供与 Host 相同 id 的 Kit 会报host-kit-id-conflict两个扩展提供同一 id 会报duplicate-extension-provider。对示例而言dev.airi.example-activation唯一由activation-planner-provider提供解析结果为{ kind: extension, extensionId: activation-planner-provider, version: 1.0.0 }。依赖解析与建图。遍历每个启用扩展的kits.uses找不到 Provider 记录unresolved/missing非可选时产生missing-required-kit诊断版本不满足区间semver.satisfies(provider.version, declaration.version)则记录unresolved/incompatible-version非可选时产生incompatible-kit-version诊断。只有兼容且非可选且 Provider 是扩展的依赖才进入依赖图Consumer → Provider 边。Consumer^1.0.0对 Provider1.0.0满足区间因此图中建立activation-planner-consumer → activation-planner-provider边。环检测与拓扑排序。对目标图与存活图分别做 Tarjan 强连通分量检测dependency-cycle诊断无环后做拓扑排序生成targetLoadOrderunloadOrder取当前加载顺序的逆序过滤出需要停止的扩展。这正是 README 中Host 先加载 Provider 再加载 Consumer、停止时先停 Consumer 再停 Provider的来源。对应测试用例在 activation-plan.test.tsloads a required Provider before its Consumer用例断言loadOrder为[provider-extension, consumer-extension]且 resolution 指向扩展 Provider另有uses global Extension ID order when newly ready nodes compete with unrelated nodes验证同一拓扑层级内按扩展 id 字典序打破平局以及rejects a missing required Kit验证缺失必需 Kit 时返回ok: false与missing-required-kit诊断。Host 如何消费这份计划Stage Tamagotchi 主进程侧的 setupExtensionHostServiceInternal 是规划的调用方。其planActivation内部函数把注册表清单、存活清单、配置中的启用集合、Host 内置 Kit、runtimeelectron与app.getVersion()一并传给planExtensionActivation计划一旦不通过ok: false就直接抛出包含全部诊断消息的 Error——这就是Consumer 仍需要时Host 拒绝禁用/卸载 Provider的实现路径把去掉 Provider 后的启用集合作为proposedEnabledExtensionIds去规划Consumer 的必需依赖解析不到规划失败。计划通过后由executeActivationPlan按unloadOrder停止旧会话、按loadOrder启动新会话并处理失败传播若某个 Provider 加载失败所有以它为必需依赖的 Consumer 会被标记required-provider-failed跳过启动见skippedExtensionIds与报告字段。整个启用/禁用/加载/卸载操作都被activationMutex串行化保证规划快照与执行不交叉。阶段边界与延伸阅读本示例验证的是Phase 2 的静态规划kits.provides/kits.uses只影响规划期冲突检测与加载顺序不产生任何运行时 Kit 绑定运行时的 Kit 注册Phase 3是后续能力编写扩展时不应期待defineExtension中直接拿到对端 Kit。若只想验证基础生命周期与权限而非依赖规划使用并排的 devtools-sample-plugin 示例导入后点击Enable and Load确认导入默认禁用未加载、加载后状态变为loaded、会话阶段变为ready。想继续深挖规划算法建议按此顺序阅读activation-plan.ts规划与诊断→ activation-plan.test.ts期望行为快照→ shared/types.ts清单 schema 与字段约束→ host/index.tsElectron 侧执行与失败传播。以上路径均以仓库根目录为起点可直接在当前仓库中定位对照。赞分享人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手【免费下载链接】airi 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器目标是接近 Neuro-sama 的高度支持实时语音聊天、Minecraft 和 Factorio 游玩支持 Web / macOS / Windows。项目地址https://gitcode.com/moeru-ai/airi点击查看免费下载相关推荐AIRI Stage Tamagotchi 插件扩展指南activation-planner-consumer 示例与 Kit 静态依赖规划解析AIRI Stage Tamagotchi 插件扩展指南activation planner consumer 示例与 Kit 静态依赖规划解析 本文以 St人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手后端AIRI Extension Host 示例插件在 Stage Tamagotchi 中验证扩展生命周期、权限声明与依赖激活规划AIRI Extension Host 示例插件在 Stage Tamagotchi 中验证扩展生命周期、权限声明与依赖激活规划 本文以 AIRImoeru人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手后端AIRI 桌面端Stage Tamagotchi开发指南Electron 应用的运行、验证与构建AIRI 桌面端Stage Tamagotchi开发指南Electron 应用的运行、验证与构建 本篇指南面向需要修改或扩展 AIRI 桌面端的开发者系人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手后端上一篇APKMirror安卓应用安全下载与管理APK文件的终极指南下一篇如何用APKMirror客户端安全高效管理安卓应用下载创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考