Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

插件推送合同 —— 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.tsinstallPluginRegistryWindowApi 装好(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.registry localStorage 项。

实际执行激活插件的 build pipeline(features/plugins/runtime.ts 里的 runActivePluginPreCompile / runActivePluginPostCompile) 活在同一台浏览器,所以“在这激活“ = “下一次 build 加载”,生命周期 一致。


相关