docs(plugins): 依赖与存储文档(L8/L9)+ 检验器入库并升级契约 0.3.0 规则
This commit is contained in:
+16
-5
@@ -1,9 +1,9 @@
|
||||
# 插件系统(harness 插件契约)
|
||||
|
||||
> **教程入口**:[docs/plugins/README.md](./plugins/README.md) —— L0 第一个插件 → L1 工具命令 → L2 设置 → L3 UI 槽位 → L4 React 组件 → L5 自诊断;视觉规范 [DESIGN.md](./plugins/DESIGN.md);脚手架 [packages/plugin-template](../packages/plugin-template/)。本文件是契约全集(参考手册)。
|
||||
> **教程入口**:[docs/plugins/README.md](./plugins/README.md) —— L0 第一个插件 → L1 工具命令 → L2 设置 → L3 UI 槽位 → L4 React 组件 → L5 自诊断 → L8 依赖互调 → L9 存储;视觉规范 [DESIGN.md](./plugins/DESIGN.md);脚手架 [packages/plugin-template](../packages/plugin-template/)。本文件是契约全集(参考手册)。
|
||||
>
|
||||
> 状态:v0.8 进行中(M0–M3 已落地;M4 更新管道 / M6 模板与外置示例 / M7 pi 原生目录管控见 roadmap)
|
||||
> 契约版本:`HARNESS_CONTRACT_VERSION = 0.2.0`(`src/main/plugins/plugin-host.ts`;manifest.minContract 与之比对,不满足拒载)
|
||||
> 契约版本:`HARNESS_CONTRACT_VERSION = 0.3.0`(`src/main/plugins/plugin-host.ts`;manifest.minContract 与之比对,不满足拒载。0.3.0 新增:依赖声明/服务互调/SQLite 存储)
|
||||
|
||||
## 两层能力模型
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
"panel": true, // 在右侧 SidePanel 出现一个 tab
|
||||
"entry": { "page": "index.html", "main": "main.mjs", "renderer": "renderer.mjs" }, // 内置插件省略 entry
|
||||
"replacesNative": false,
|
||||
"dependencies": { "fetch-tools": "^1.0.0" }, // 必需依赖:id → semver 范围(* ^ ~ >= 精确);缺失/停用/版本不符 → 激活失败并提示
|
||||
"optionalDependencies": { "embed-store": "~2.1.0" }, // 可选依赖:缺失只降级(requirePlugin 返回 undefined)
|
||||
"updateURL": "https://…/index.json"
|
||||
}
|
||||
```
|
||||
@@ -53,14 +55,23 @@ export default definePlugin((api) => {
|
||||
api.ui.registerToolbarButton({ id: 'gen', title: '生成标题', openView: { view: 'hotwords' } })
|
||||
api.ui.openView('hotwords', { tab: 2 }) // 深链打开插件页
|
||||
|
||||
// 插件私有 KV(userData/aso-plugin-storage.json,按 pluginId 隔离)
|
||||
api.storage.set('lastQuery', 'xxx')
|
||||
// 插件私有存储(SQLite,userData/plugin-data/<id>/data.db;API 全 async,宿主共享 worker 执行)
|
||||
await api.storage.declareSchema({ tables: [{ name: 'notes', description: '…', columns: [{ name: 'id', type: 'TEXT', description: '…' }] }] })
|
||||
await api.storage.kv.set('lastQuery', 'xxx') // KV(宿主管理的 kv 表,JSON 编码)
|
||||
const rows = await api.storage.db.query('SELECT * FROM notes LIMIT 10')
|
||||
api.storage.dir() // 自由文件目录
|
||||
|
||||
// 跨插件互调(依赖声明即访问授权;拓扑波次保证依赖先激活)
|
||||
api.service('fetch', (url: string) => fetch(url).then((r) => r.text())) // 暴露服务
|
||||
const deps = api.requirePlugin('fetch-tools') // 未声明依赖 → 抛错;可选未就绪 → undefined
|
||||
|
||||
return () => { /* dispose:宿主在 session_shutdown / 禁用 / 重载时调用 */ }
|
||||
})
|
||||
```
|
||||
|
||||
实现:harness 在 pi `extensionFactories` 挂**一个聚合 extension**,工厂内创建真实 `ExtensionAPI` 上下文后扇出给所有已启用插件——工具注册走 pi 原生路径(提示词注入、审批拦截、事件时序由 pi 管)。
|
||||
实现:harness 在 pi `extensionFactories` 挂**一个聚合 extension**,工厂内创建真实 `ExtensionAPI` 上下文后扇出给所有已启用插件——工具注册走 pi 原生路径(提示词注入、审批拦截、事件时序由 pi 管)。激活顺序 = **必需依赖图的拓扑波次**(依赖先、依赖者后,同波并行;环整环报错;异步工厂限时 10s)。
|
||||
|
||||
依赖与存储细则:见 [L8 依赖与互调](./plugins/10-dependencies.md)、[L9 存储](./plugins/11-storage.md)。
|
||||
|
||||
## 插件页(iframe)契约(`@aso/plugin-sdk/client`)
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ import { readFile } from 'node:fs/promises'
|
||||
const text = await readFile(path, 'utf8')
|
||||
```
|
||||
|
||||
**存储也不例外**:`api.storage.*`(SQLite)在宿主的共享 worker 线程里执行,
|
||||
主进程只做异步 RPC——大查询不会卡聊天流(见 [L9](./11-storage.md))。
|
||||
自己开的文件句柄同理:全 async。
|
||||
|
||||
### 2. 激活限时 10 秒(宿主强制)
|
||||
|
||||
插件工厂若返回 Promise,宿主限时 10s;超时或 reject 即把插件标记为失败
|
||||
|
||||
@@ -52,7 +52,30 @@
|
||||
| 设置页按钮点了没反应 | 没挂 `onSettingsAction` | 按 key 订阅动作回调 |
|
||||
| 左侧导航「Agent 能力」没有插件入口 | `settingsNav` 未开启 | 插件行 → 入口开关打开 |
|
||||
|
||||
## 6. 样式不对
|
||||
## 6. 依赖与互调(契约 0.3.0)
|
||||
|
||||
| 症状 | 原因 | 修复 |
|
||||
|---|---|---|
|
||||
| 行红字「缺少依赖插件 x(^1.0.0),请安装后重载」 | 必需依赖未安装 | 把依赖插件放入任一插件目录,点「重载」;宿主不自动安装 |
|
||||
| 行红字「依赖插件 x 已停用,请先启用」 | 必需依赖被禁用 | 到该依赖插件行打开「启动」;启用后本插件自动恢复 |
|
||||
| 行红字「依赖插件 x 需要 ^2.0,当前 v1.4.0」 | 版本不满足范围 | 升级依赖插件,或放宽自己 manifest 的范围 |
|
||||
| 行红字「循环依赖: a → b → a」 | 必需依赖成环 | 解环(改为 optionalDependencies 或重构边界) |
|
||||
| `requirePlugin` 抛「未声明对 x 的依赖」 | 未在 dependencies/optionalDependencies 声明 | 依赖声明即访问授权——manifest 里加上,并满足其 `minContract` |
|
||||
| `requirePlugin` 返回 undefined(可选依赖) | 可选依赖缺失/停用/未就绪 | 预期行为;走降级路径 |
|
||||
| 改了依赖方代码,依赖方行为没变 | 没重载 | 重载是宿主级动作,点同一个「重载」即可 |
|
||||
|
||||
## 7. 存储(SQLite)
|
||||
|
||||
| 症状 | 原因 | 修复 |
|
||||
|---|---|---|
|
||||
| `plugin:check` 报「使用了 api.storage.db 但未调用 declareSchema」 | 用了 SQLite 却没声明机器可读 schema | 激活期调用 `api.storage.declareSchema`,表/字段 description 写清楚(Agent 内省与设置页展示同源) |
|
||||
| `api.storage.*` 报「存储操作超时(…5000ms)」 | worker 挂死或查询过重 | 检查 SQL 是否全表扫描/锁表;重启应用可恢复 worker |
|
||||
| 报「database is locked」 | 跨进程/工具直接打开了同一个 data.db | 用宿主 API 访问,不要同时用外部 sqlite 工具长连接 |
|
||||
| KV 读回来的值不对 | value 不可 JSON 序列化(Date/Map) | 存前转 JSON 兼容类型;大二进制放文件、路径存 KV |
|
||||
| 想彻底重来 | — | 设置 → 插件 → 二级页「存储区」→ 清除数据(二次确认,整目录删除) |
|
||||
| 表结构要改 | — | `PRAGMA user_version` 自管迁移(见 [L9](./11-storage.md) §4) |
|
||||
|
||||
## 8. 样式不对
|
||||
|
||||
| 症状 | 原因 | 修复 |
|
||||
|---|---|---|
|
||||
@@ -62,14 +85,14 @@
|
||||
| 图标是拼图(fallback) | manifest.icon 不在 lucide 白名单 | 改成白名单内的 lucide 名(DESIGN.md §3;`plugin:check` 会 warn) |
|
||||
| 按钮不是胶囊形 / 圆角不对 | 手写 rounded-control 当按钮 | renderer 用组件库 `Button`(pill 体系);圆角体系 chip6/control8/card10/window14 |
|
||||
|
||||
## 7. 检验器对照
|
||||
## 9. 检验器对照
|
||||
|
||||
`pnpm plugin:check <目录>` 输出的每条 error/warn 都带修复指引;完整规则表见 [L7](./08-performance.md)。速记:
|
||||
|
||||
- error = 装不了或必然出问题(同步 IO、console.*、React 副本、hex、超尺寸、契约非法)
|
||||
- warn = 应当修(缺 minContract、疑似 React 副本、三态缺失、阻塞对话框、icon 不在白名单、产物未构建)
|
||||
- error = 装不了或必然出问题(同步 IO、console.*、React 副本、hex、超尺寸、契约非法、依赖声明非法、用 db 未声明 schema、requirePlugin 未声明依赖)
|
||||
- warn = 应当修(缺 minContract、疑似 React 副本、三态缺失、阻塞对话框、icon 不在白名单、产物未构建、声明依赖但 minContract 过低)
|
||||
|
||||
## 8. 还不行?
|
||||
## 10. 还不行?
|
||||
|
||||
1. `pnpm plugin:check <目录>` → 0 error
|
||||
2. 重载插件 → 看 `userData/logs/main-*.log` 里 `plugin activated pluginId=<id>` 之后你自己的 `api.log` 输出
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# L8 插件依赖与服务互调
|
||||
|
||||
> 插件不是孤岛:A 依赖 B/C 时,声明、激活顺序、可用性判定、调用规范由宿主统一保证。
|
||||
> 契约 0.3.0 起;全部机制在 `dependencies` / `optionalDependencies` + `api.service` / `api.requirePlugin` 四个名字里。
|
||||
|
||||
## 1. 声明依赖(manifest.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "wiki-assistant",
|
||||
"version": "1.2.0",
|
||||
"minContract": "0.3.0",
|
||||
"dependencies": {
|
||||
"fetch-tools": "^1.0.0",
|
||||
"browser": "*"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"embed-store": "~2.1.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 值是 **semver 范围**,支持五种写法:`*`(任意)、`^1.2.0`(同主版本)、`~1.2.0`(同次版本)、`>=1.2.0`(下限)、`1.2.0`(精确)。
|
||||
- `dependencies` 是**必需依赖**:缺失 / 已停用 / 版本不符 / 自身装载失败 → 本插件激活失败。
|
||||
- `optionalDependencies` 是**可选依赖**:不就绪只降级,`api.requirePlugin(id)` 返回 `undefined`。
|
||||
- **依赖声明即访问授权**:`requirePlugin` 只对声明过的 id 放行,未声明直接抛错。
|
||||
|
||||
## 2. 运行时判定(软绑定,无强行绑定)
|
||||
|
||||
宿主在每次激活轮(启停/重载/重建运行时)做三步:
|
||||
|
||||
1. **静态预检**:逐项检查必需依赖——
|
||||
|
||||
| 状态 | 判定 | 插件行展示的错误 |
|
||||
|---|---|---|
|
||||
| missing | resolved 表里没有该 id | `缺少依赖插件 fetch-tools(^1.0.0),请安装后重载` |
|
||||
| disabled | 在禁用列表里 | `依赖插件 browser 已停用,请先启用` |
|
||||
| version | 不满足范围 | `依赖插件 fetch-tools 需要 ^1.0.0,当前 v0.9.0` |
|
||||
| error | 依赖自身装载失败 | `依赖插件 fetch-tools 装载失败,无法激活` |
|
||||
|
||||
2. **环检测**:必需依赖图存在环 → 整环不激活,每个成员报 `循环依赖: a → b → a`。
|
||||
3. **拓扑波次激活**:依赖先激活、依赖者后激活,无依赖关系的插件**同波并行**(异步工厂限时 10s,挂死不拖垮后续波次)。依赖激活失败时,依赖方报 `依赖插件 x 未能激活`。
|
||||
|
||||
行为语义(有意为之):
|
||||
|
||||
- A 声明依赖 B:**禁用 B → A 激活失败**(错误栏写明原因);**重新启用 B → A 自动恢复**(重建运行时天然重放)。
|
||||
- **禁用 A 不影响 B**——依赖不级联、不偷改用户的选择。
|
||||
- **不自动安装**:缺什么报什么,装不装由用户决定(错误文案就是行动指引)。
|
||||
|
||||
## 3. 服务互调(api.service / api.requirePlugin)
|
||||
|
||||
所有插件的 main 工厂运行在同一 pi 上下文,互调是**同进程直调**(无 IPC、无序列化),宿主只提供注册表与门控:
|
||||
|
||||
```ts
|
||||
// fetch-tools 的 main.mjs —— 暴露服务
|
||||
export default definePlugin((api) => {
|
||||
api.service('fetch', async (url: string, init?: RequestInit) => {
|
||||
const res = await fetch(url, init)
|
||||
return res.text()
|
||||
})
|
||||
})
|
||||
|
||||
// wiki-assistant 的 main.mjs —— 消费服务
|
||||
export default definePlugin(async (api) => {
|
||||
const fetchTools = api.requirePlugin('fetch-tools') as
|
||||
| { fetch: (url: string, init?: RequestInit) => Promise<string> }
|
||||
| undefined
|
||||
if (!fetchTools) {
|
||||
// 可选依赖未就绪:降级路径(必需依赖不会走到这里——激活前置检已拦)
|
||||
}
|
||||
api.pi.registerTool({
|
||||
name: 'wiki_lookup',
|
||||
// ...
|
||||
execute: async (args) => {
|
||||
// 服务方法约定 async;调用方自行限时(与宿主性能护栏同构)
|
||||
const body = await withTimeout(fetchTools!.fetch(args.url), 8_000, 'wiki_lookup')
|
||||
// ...
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
规则:
|
||||
|
||||
- `api.service(name, impl)`:按名键控;重载/停用时随注册表清空,重激活即重新注册。
|
||||
- `api.requirePlugin(id)`:返回 `{ serviceName: impl }`;未声明 → 抛错;必需依赖未就绪 → 抛错;可选未就绪 → `undefined`。
|
||||
- **服务方法约定全 async**,调用方用 `withTimeout` 限时、必要时 `withRetry`(见 L7)——被调插件慢不能变成调用方卡死。
|
||||
- 依赖可以指向内置插件(如 `browser`),内置与外置同一注册表。
|
||||
|
||||
## 4. UI 展示
|
||||
|
||||
- 管理页插件行名称旁出现**链接图标**,悬停 Tooltip 列出每个依赖:id / 范围 / 必需或可选 / 实时状态(可用·绿 / 未安装·橙 / 已停用·橙 / 版本不符·橙 / 装载失败·红)。
|
||||
- 依赖问题的详细错误在该插件行红字与二级页展示;「去启用」到对应插件的行上操作。
|
||||
|
||||
## 5. 检验器
|
||||
|
||||
`pnpm plugin:check` 会校验:依赖 id 合法、范围语法、不能依赖自身、不能同时出现在必需与可选、声明了依赖但 `minContract < 0.3.0`(旧宿主会静默忽略声明)、调用了 `requirePlugin` 却未声明依赖。
|
||||
@@ -0,0 +1,88 @@
|
||||
# L9 插件存储(SQLite)
|
||||
|
||||
> 每个插件一块**私有**持久化空间:一个 SQLite 库 + 一个自由文件目录。
|
||||
> KV 简单状态、SQL 结构化数据、文件随便放;schema 必须机器可读声明——它是 Agent 自我迭代与 UI 展示的同一份事实源。
|
||||
|
||||
## 1. 空间布局
|
||||
|
||||
```
|
||||
userData/plugin-data/<plugin-id>/
|
||||
data.db ← SQLite 库(WAL 模式):kv 表(宿主管理)+ 插件自建表
|
||||
data.db-wal ← WAL 伴生文件
|
||||
<其余自由文件> ← api.storage.dir() 指向这里,插件自行读写
|
||||
```
|
||||
|
||||
- **每插件一库**(不是共享大库):导出/清除/损坏恢复都以插件为单位,跨插件天然隔离。
|
||||
- 卸载/移除插件**不删数据**(重装即恢复);删除只在设置页点「清除数据」(二次确认)时发生。
|
||||
|
||||
## 2. API(全部 async——底层在宿主共享 worker 线程执行,永不阻塞主进程)
|
||||
|
||||
```ts
|
||||
export default definePlugin(async (api) => {
|
||||
// ① 声明机器可读 schema(使用 db 前必须声明;plugin:check 强制)
|
||||
api.storage.declareSchema({
|
||||
kv: { description: '会话级偏好:ui.<key> = 用户界面偏好' },
|
||||
tables: [
|
||||
{
|
||||
name: 'notes',
|
||||
description: '用户笔记',
|
||||
columns: [
|
||||
{ name: 'id', type: 'TEXT', description: '主键,ulid' },
|
||||
{ name: 'title', type: 'TEXT', description: '标题,非空' },
|
||||
{ name: 'created_at', type: 'INTEGER', description: '创建时间,Unix 毫秒' }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// ② KV:宿主管理的 kv 表(value 走 JSON 编码,适合设置类小状态)
|
||||
const last = await api.storage.kv.get<string>('ui.lastQuery')
|
||||
await api.storage.kv.set('ui.lastQuery', 'postgres')
|
||||
await api.storage.kv.delete('ui.lastQuery')
|
||||
const keys = await api.storage.kv.keys()
|
||||
|
||||
// ③ 自建表:SQL 自由发挥
|
||||
await api.storage.db.exec('CREATE TABLE IF NOT EXISTS notes (...)') // DDL,激活期执行
|
||||
await api.storage.db.run('INSERT INTO notes (id, title) VALUES (?, ?)', ['n1', '标题'])
|
||||
const rows = await api.storage.db.query('SELECT * FROM notes WHERE title LIKE ?', ['%标%'])
|
||||
// 原子批量:worker 端 BEGIN/COMMIT,任一失败整体回滚
|
||||
await api.storage.db.batch([
|
||||
{ sql: 'INSERT INTO notes (id, title) VALUES (?, ?)', params: ['n2', 'a'] },
|
||||
{ sql: 'UPDATE notes SET title = ? WHERE id = ?', params: ['b', 'n2'] }
|
||||
])
|
||||
|
||||
// ④ 自由文件(日志快照、导出等)
|
||||
const dir = api.storage.dir() // userData/plugin-data/<id>/
|
||||
})
|
||||
```
|
||||
|
||||
## 3. schema 声明为什么是硬性要求
|
||||
|
||||
插件会被 **Agent 自我迭代**。迭代前 Agent 需要知道「库里有什么」:
|
||||
|
||||
- `declareSchema` 的内容随 `plugins:list` 下发——管理页「存储区」卡片与(未来的)Agent 内省工具读的是**同一份**数据;
|
||||
- 每张表、每个字段的 `description` 必填,`plugin:check` 会拒绝「用了 db 却不声明 schema」的插件;
|
||||
- 写给 Agent 读的 description 请具体(「创建时间,Unix 毫秒」而不是「时间」)。
|
||||
|
||||
## 4. 迁移(表结构变更)
|
||||
|
||||
宿主不解释 schema,迁移由插件自管,惯用法:
|
||||
|
||||
```ts
|
||||
const row = await api.storage.db.query('PRAGMA user_version')
|
||||
const v = Number(row[0]?.user_version ?? 0)
|
||||
if (v < 1) {
|
||||
await api.storage.db.exec('ALTER TABLE notes ADD COLUMN tag TEXT')
|
||||
await api.storage.db.exec('PRAGMA user_version = 1')
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 设置页管理
|
||||
|
||||
- 二级页「存储区」卡片:schema 表格化展示(表/列/类型/描述)+ **数据目录**(资源管理器打开)+ **清除数据**(二次确认,连接关闭后整目录删除)。
|
||||
|
||||
## 6. 边界
|
||||
|
||||
- 存储只在 **main 层**提供;renderer 组件 / iframe 页需要数据时,让 main 侧经状态胶囊/设置值转发(受控 IPC 通道属后续契约)。
|
||||
- KV 的 value 必须可 JSON 序列化(Date/Map 请先转换);大二进制放文件,路径存 KV。
|
||||
- 跨插件**不直读对方库**:需要别人的数据 = 声明依赖 + 走对方服务(见 L8)。
|
||||
@@ -15,6 +15,8 @@
|
||||
| [L5 自诊断](./06-self-diagnosis.md) | 日志规范、排障闭环、Agent 自迭代约定 | 可被 Agent 维护的插件 |
|
||||
| [L6 公共组件库](./07-ui-components.md) | @aso/plugin-sdk/ui:统一三态(等待/失败/空)与基础控件 | 与宿主零差异的 UI |
|
||||
| [L7 性能与检验](./08-performance.md) | 主线程不阻塞、超时重试、plugin:check 机器关卡 | 可发布、不卡宿主的插件 |
|
||||
| [L8 依赖与互调](./10-dependencies.md) | dependencies 声明、拓扑激活、api.service/requirePlugin | 可组合、可协作的插件 |
|
||||
| [L9 存储](./11-storage.md) | 每插件 SQLite 库 + KV + schema 声明 + 数据管理 | 有持久化、可被 Agent 迭代的插件 |
|
||||
|
||||
> **排障中?** 直接跳 [常见错误速查](./09-troubleshooting.md)——症状 → 原因 → 修复三段式速查表。
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
| v0.4.0 | 工具与审批 | 工具调用卡片(参数/结果折叠展示)、tool_call 拦截 → Approval Card、defineTool 业务工具骨架(本地可跑的演示工具) |
|
||||
| v0.5.0 | 打磨 | 深浅主题、GSAP 动效细节、快捷键、错误态/空态、队列可视化、自动滚动策略 |
|
||||
| v0.8.0 | 动态插件系统(M0–M3) | 两层能力模型(内置组件级/外置 iframe)、pi 原生契约聚合 extension、@aso/plugin-sdk、plugin://peer:// 协议、视图切换+聊天保活+徽标、侧栏/面板/胶囊/深链槽位、浏览器面板插件化、插件重载 |
|
||||
| v0.9.0 | 插件一等公民 + 可观测 | entry.renderer 宿主内 React 组件(Blob 装载+单实例 React)、.pi/extensions 一等插件源(build 开关门控)、声明式设置体系(13 控件+一级导航入口)、统一日志系统(滚动文件/api.log/IPC 追踪/渲染层错误归档)、渐进式教程 docs/plugins/ + DESIGN.md + plugin-template、性能/样式标准与检验器(激活 10s/装载 8s 护栏、@aso/plugin-sdk/ui 组件库+三态、withTimeout/withRetry、plugin:check)、状态胶囊详情面板(ZCode Git 工具式:头部+分组+行尾彩色数值,B3 浮动态并入顶栏胶囊)、图标统一 lucide 白名单、面板平铺标签条 |
|
||||
| v0.9.0 | 插件一等公民 + 可观测 | entry.renderer 宿主内 React 组件(Blob 装载+单实例 React)、.pi/extensions 一等插件源(build 开关门控)、声明式设置体系(13 控件+一级导航入口)、统一日志系统(滚动文件/api.log/IPC 追踪/渲染层错误归档)、插件依赖与服务互调(dependencies/optionalDependencies + api.service/requirePlugin + 拓扑波次激活 + 环检测)、插件 SQLite 存储(每插件一库 userData/plugin-data/<id>/data.db + 共享 worker 线程 + 机器可读 declareSchema + 设置页存储区卡片)、渐进式教程 docs/plugins/ + DESIGN.md + plugin-template、性能/样式标准与检验器(激活 10s/装载 8s 护栏、@aso/plugin-sdk/ui 组件库+三态、withTimeout/withRetry、plugin:check)、状态胶囊详情面板(ZCode Git 工具式:头部+分组+行尾彩色数值,B3 浮动态并入顶栏胶囊)、图标统一 lucide 白名单、面板平铺标签条 |
|
||||
| 未来 | | 插件管理与 zip 导入(M4)、ed25519 签名在线更新(M5)、外置插件模板与开发工作流(M6)、pi 原生扩展目录管控(M7)、B3/B4/B5 槽位、electron-builder 打包与自动更新、i18n(中/英)、sqlite 持久化与迁移、本地备份恢复、热点词/生成/模板业务插件、手动模式编排 UI、RPC 子进程隔离模式 |
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user