插件推送合同 —— agent → /ops/plugins
window.aegis.* 的第二个表面,跟周度制作者数据资产复盘
平行。那一页讲推 maker-stats 数据快照,这一页讲推 WASM
插件包 —— 一个 agent 在制作者本机编译出来的二进制。
同一个架构、同一个信任模型:浏览器本地沙盒、无服务端 registry、 agent 干重活、制作者只审核结果。
数据流
+--------------------+ 通过 +----------------------+
| 本地 agent 编译 | chrome-mcp | window.aegis |
| WASM,打成 package | evaluate_script | .publishPlugin() |
| | 推 | |
+--------------------+ ────────────────► +----------+-----------+
|
v
localStorage:
aegis.plugins.registry
|
v
/ops/plugins 挂载时读,也
监听 aegis:plugins:updated
事件,版本表 + audit log
实时刷新。
激活的插件由浏览器内 build pipeline(ESPCTL MCP、Build Lab)在 pre/post-compile 时拉取。这里激活 = 下一次本浏览器 build 真的会跑。
浏览器 API 合同
window.aegis 下 6 个函数,App 启动时由
src/lib/user-settings/plugin-registry.ts 的
installPluginRegistryWindowApi 装好(idempotent):
| 函数 | 返回 | 备注 |
|---|---|---|
window.aegis.publishPlugin(pkg, actor?) | Promise<{ ok, error?, audit, record? }> | 校验 pkg.manifest、验 digest、持久化,派发 aegis:plugins:updated。async 因为 manifest 校验跑 crypto.subtle.digest。 |
window.aegis.activatePlugin(pluginId, version, options?) | { ok, error?, audit, record? } | options?: { actor?, scope?, rolloutPct? }。默认 actor='agent'、scope='all'、rolloutPct=100。 |
window.aegis.deactivatePlugin(pluginId, version, actor?) | { ok, error?, audit, record? } | |
window.aegis.rollbackPlugin(pluginId, version, actor?) | { ok, error?, audit, record? } | 把当前 active 版本回滚到传入的较早 version。 |
window.aegis.getPluginSnapshot() | PluginRegistrySnapshot | 读当前 versions[] + activeVersions{} + audits[]。 |
window.aegis.clearPluginRegistry() | void | 清空本地 registry。 |
监听更新:
window.addEventListener('aegis:plugins:updated', (event) => {
console.log('new plugin registry snapshot', event.detail);
});
Snapshot schema
interface PluginRegistrySnapshot {
versions: PluginVersionRecord[];
activeVersions: Record<PluginId, Version>;
audits: PluginLifecycleAudit[];
}
interface PluginVersionRecord {
pluginId: string;
version: string;
manifest: PluginManifest; // 见 contracts/manifest.ts
digest?: string;
publishedAt: string;
publishedBy: string;
updatedAt: string;
state: 'published' | 'active' | 'inactive' | 'rolled_back';
rollout: {
scope: 'all' | 'beta' | 'canary' | 'internal';
rolloutPct: number;
};
}
publishPlugin 接受的 SignedPluginPackage:
interface SignedPluginPackage {
manifest: PluginManifest;
artifactDigest?: string;
artifactUrl?: string;
}
manifest 必须通过 parsePluginManifest() 校验(plugin_id / version /
contract_version / hooks / capabilities / digest / runtime)。非法
manifest 直接 { ok: false, error: 'Manifest validation failed during publish.', audit }。
最小 agent 脚本
刚在本地编完一份 WASM 插件的浏览器驱动 agent 会做:
// agent 在本地 compile 成功之后的伪代码
const manifest = JSON.parse(fs.readFileSync('plugin-manifest.json', 'utf8'));
const wasm = fs.readFileSync('plugin.wasm');
const digest = await sha256(wasm);
const pkg = {
manifest: { ...manifest, digest: `sha256:${digest}` },
artifactDigest: `sha256:${digest}`,
artifactUrl: 'file:///tmp/plugin.wasm',
};
const result = await chromeMcp.evaluateScript(
`window.aegis.publishPlugin(${JSON.stringify(pkg)}, 'agent-compile-flow')`,
);
if (!result.ok) throw new Error(result.error);
// 然后激活:
await chromeMcp.evaluateScript(
`window.aegis.activatePlugin('${manifest.plugin_id}', '${manifest.version}')`,
);
/ops/plugins 通过 aegis:plugins:updated 事件立即出现新版本 + audit 行。
信任边界
浏览器本地的插件 registry 单制作者、单浏览器:
- 没有上传 UI(故意)。agent 就是 publisher。
- 没有公钥签名。Digest match(
crypto.subtle.digest)只证完整性、 不证身份 —— 合适,因为 publisher 是制作者自己的本地 agent。 - 没有服务端台账。每个浏览器各自一份
aegis.plugins.registrylocalStorage 项。
实际执行激活插件的 build pipeline(features/plugins/runtime.ts
里的 runActivePluginPreCompile / runActivePluginPostCompile)
活在同一台浏览器,所以“在这激活“ = “下一次 build 加载”,生命周期
一致。
相关
- 周度制作者数据资产复盘 —— 平行的 agent 推送合同,数据快照版本。
- Aegis Ops —— 把这两条合同串起来 的落地页。
/ops/plugins—— 消费这份 snapshot 的治理 UI。