# @eficy/opencode2-plugin 中文文档

规范地址：https://npmcn.com/package/%40eficy/opencode2-plugin/

版本：0\.5\.9
npm 元数据更新时间：2026-11-04T12:43:18.308Z
中文译文更新时间：2026-11-13T13:14:20.537Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40eficy/opencode2-plugin
原文对照：https://npmcn.com/package/%40eficy/opencode2-plugin/?lang=original
项目主页：https://github.com/yee94/opencode-eficy/tree/main/packages/opencode2-plugin#readme
源码仓库：https://github.com/yee94/opencode-eficy

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：2.5 MB，17 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：未声明
- 运行依赖：2 个
- 首次发布：2026-10-28T06:00:13.383Z
- 最新版本发布：2026-11-04T12:43:18.094Z
- 近 30 天下载量：3578（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：21（近 12 个月 21 个）

## 中文简介

自成一体的Eficy TSX预览、技能和OpenCode 2验证器

## 安装

```sh
npm install @eficy/opencode2-plugin
```

也可以使用：`pnpm add @eficy/opencode2-plugin`、`yarn add @eficy/opencode2-plugin`、`bun add @eficy/opencode2-plugin`

## README

# Eficy：单文件交互预览

提供 `eficy` 技能、报告模板、`eficy_validate` 校验工具与 `.eficy` GUI 预览。服务端插件 ID 为 `eficy`，SDK 使用 `@opencode/plugin` 2.2.0。iframe 内置 Eficy/React；组件、图标、图表及 CSS 通过固定版本 HTTPS 地址按需加载。

插件图标为透明底的文档 E，使用 `currentColor` 单色 SVG。源文件为 [`icon.svg`](https://npmcn.com/package/%40eficy/opencode2-plugin/icon.svg)，`package.json` 顶层 `icon` 内嵌同一图形的 data URI，不依赖远程图片；`.eficy` 文件类型图标保持原有配色。

## 安装（OpenCode 2）

默认提供完整 Eficy + shadcn 页面与报告引导，支持 HTTPS 模块与 CSS 导入、HTML 单文件导出，以及按客户端能力提供的 PDF/长图导出。在连接服务的全局 `opencode.json(c)` 中加入 npm 包，保留已有配置：

```json
{
  "$schema": "https://opencode.ai/config.json",
  "plugins": ["@eficy/opencode2-plugin@0.5.9"]
}
```

配置保存后由 OpenCode 重新加载插件。终端可使用 skill 和校验工具；可视化预览需要支持标准 `./gui-experimental` 入口的 GUI 宿主。GUI API 仍为实验性接口，本版本针对 `@opencode/plugin` 2.2.0 构建。

也可用本仓库 `pnpm pack:all` 生成 tgz，安装后将对应 `node_modules/@eficy/opencode2-plugin` 绝对路径加入全局 `plugins`。

## 本地构建与安装

本目录为独立发布包，开发命令从仓库根目录执行：

```sh
pnpm install --frozen-lockfile
pnpm build
pnpm typecheck
pnpm test
```

将目录绝对路径加入连接服务的**全局** `opencode.json(c)`，保留已有配置：

```json
{
  "$schema": "https://opencode.ai/config.json",
  "plugins": ["/path/to/opencode-eficy/packages/opencode2-plugin"]
}
```

包的 `.` 导出服务端入口，`./gui-experimental` 导出预构建 GUI bundle。远程连接时应在远端服务安装同一包；仅本地放置 GUI 产物不会给远端 agent 注册技能。GUI 开关不取消服务端 skill/tool 注册。

## 生成与预览

向 agent 请求：

> 使用 eficy 技能生成一个带计数按钮和姓名输入框的 demo.eficy，保存并返回链接。

`.eficy` 是单文件 TSX，默认导出一个 React 组件，支持静态 `eficy`、`shadcn` 与 HTTPS ESM/CSS 导入。文件类型由最后一层后缀识别。完整 Signals 示例见 [`skills/eficy/SKILL.md`](https://npmcn.com/package/%40eficy/opencode2-plugin/skills/eficy/SKILL.md)。保存后点击文件链接或文件树即可预览。

`import * as ui from 'shadcn'` 提供 `ui.Recharts` 与 `ui.Lucide`。图表使用 `@eficy/charts@0.1.0` 的 Recharts namespace，UI 与图标使用 `@eficy/shadcn-ui@1.1.3`，共享宿主 React/ReactDOM；ChartTooltip/ChartLegend 与图表使用同一实例。适配模块仅在导入 `shadcn` 时加载。图表 CDN 地址尚待发布与浏览器验证。

源码变化会重新求值模块，模块级 Signal 状态可能重置；同内容更新不应重载。预览状态不是持久数据。文件读取失败、语法或渲染失败必须显示错误；真实浏览器保存更新、交互和恢复流程由集成验收确认。

Panel 创建时立即在外层真实 DOM 显示居中的 SVG 与提示，覆盖文件读取、iframe 启动、源码编译和 HTTPS 组件/样式加载，直到当前版本内容实际提交。首次加载提示只显示在居中画面，顶部状态区用于文件错误和重试。SVG/样式与 iframe 自带加载画面共用，独立使用 frame 时仍有加载提示。文案沿用宿主 `ctx.t` 的语言，动画遵循 `prefers-reduced-motion`。

iframe 在外层占位获得绘制机会后才创建；等待期间使用 `visibility:hidden` 保留实际尺寸，不使用 `display:none`。外层依据经过 source、frameId 与 revision 校验的 `status` 消息收起加载画面；iframe 的 `load`、runtime 的 `ready` 和导出的 `render-state` 都不是内容就绪信号。首次内容提交前不展示内部初始化占位，已有内容在后台更新期间保持可交互。文件错误显示外层重试；启动、依赖和渲染错误解除遮挡并显示 iframe 内错误与重试。重试重建文档、分配新 frameId 并重新发送最新源码，旧文档消息、过期 revision 和已关闭 Panel 的异步结果不能影响新加载。

当前版本提交时，在用户组件的 layout effect 之前启用样式并解除根节点隐藏，保证首次布局测量有效；同次提交的 layout effect 收起加载画面。加载画面采用独立固定定位，不参与内容布局，也不覆盖已有可交互内容。

### 加载回归与阶段注入

运行 `pnpm build && pnpm typecheck` 后，用 `pnpm exec vitest run tests/preview-loading.test.ts tests/bootstrap-loading.test.ts tests/frame.test.ts tests/frame-runtime.test.ts tests/gui.test.ts` 验证 Panel、父子消息边界和真实 runtime；bootstrap 用例执行生成的内联运行时，避免只测源码而漏掉旧构建产物。

浏览器夹具可独立控制以下边界，无需改原报告或添加生产开关：

-   文件：在宿主 `file.sync`/`readFile` 返回一个可手动 resolve/reject 的 Promise；等待期间外层 SVG 可见、顶部无重复加载文字。reject 后应看到错误与重试。
-   启动：暂存 iframe 的 `srcdoc` setter 写入，释放时调用原 setter；期间 iframe 隐藏但宽高非零。收到 `ready` 后 SVG 仍须可见。
-   依赖/模块：仅给夹具读取到的源码前置一个等待消息的顶层 Promise；释放前保持加载，释放后等待 `status:committed`，不能以 `render-state` 或 `ready` 提前结束。
-   CSS/渲染：在浏览器网络层暂存样式响应，或用测试组件抛出可控 Suspense Promise；错误响应/渲染异常必须露出错误与重试，成功 layout commit 才收起加载。
-   更新/取消：第一次提交后再次阻塞模块，旧按钮仍应可点击；等待期间关闭或切换文件，再释放旧 Promise，不得改变新 Panel。

生产 GUI 产物为 `packages/opencode2-plugin/dist/gui-experimental.cjs`。运行时与 GUI 必须同次构建，正在修改期间的中间产物不用于验收。

## 内置报告与组件说明

`eficy` 技能用于页面、分析报告、看板和图表，简单查找、列举和问答直接回复。默认采用 shadcn 组件、暗色主题和报告阅读布局，也支持用户指定风格。包内提供按需参考的组件说明、报告规范，以及 [经营分析](https://npmcn.com/package/%40eficy/opencode2-plugin/samples/analytics.eficy)、[履约分析](https://npmcn.com/package/%40eficy/opencode2-plugin/samples/operations.eficy) 和 [交互工作台](https://npmcn.com/package/%40eficy/opencode2-plugin/samples/workbench.eficy) 示例。

调用 `eficy_template({ preset: "analytics" | "operations" })` 获取 JSON 字符串，用 `JSON.parse(result).source` 取得完整 TSX，按实际数据与问题修改后保存并交付链接。模板包含明确标注的演示数据；工具不写文件。默认不校验或截图；用户要求验证或出现具体报错时再检查，通过即停止，失败最多修复并复验一次，仍失败则保留文件并说明阻塞。

页面内的 `<a href>` 本地文件链接通过标准 `ctx.links.open` 交给宿主：支持绝对路径、`file://` URL 和相对当前文件目录的路径，继续在文件标签页中渲染。消息中的文件链接也进入同一文件预览链路。iframe 不自行跳转到本地路径；文件不存在或当前服务无权访问时按宿主文件错误显示。

## 校验与隔离边界

`eficy_validate({ path, source })` 只处理 `source` 中的完整 TSX，不读取目标路径、不执行代码、不解析网络或磁盘依赖。返回 JSON 字符串，在代码中先解析再读取 `valid`。Sucrase 执行真正的 TSX 语法解析；同一语法 token 流用于检查默认导出和 import 边界。源码限制为 **128 KiB UTF-8**。失败返回 `valid: false`、`code` 和 `error`，区分缺失输入、路径、超限、语法、默认导出、导入与 frame 文档边界问题。

格式要求直接 `export default`；支持固定版本的 HTTPS 浏览器模块与 CSS 侧效导入。相对本地模块、未映射的 npm 包名、动态 import、`require`、`loadModule` 不支持。外部 React 库需保留 React external，使用 frame 的共享实例；初始化、import map 和挂载由 frame 管理。静态校验通过不证明 CDN 可达或模块包含所需导出。

静态校验不是类型检查或安全沙箱，也不能证明默认导出值可渲染。源码在客户端编译并在隔离 iframe 运行，不发送到 CDN；网络用于获取外部资源。iframe 权限、CSP、消息来源校验和资源清理由 frame 承担，不授予父页 DOM、宿主 SDK 或 Node API 能力。首次加载需要网络及资源端 CORS 支持，浏览器缓存不等于完整离线保证。

iframe 采用 `allow-scripts allow-forms`，不授予 same-origin 权限。`allow-forms` 让 React 的 `onSubmit` 可以收到原生表单事件，CSP 的 `form-action 'none'` 仍禁止网络表单提交。消息通过 source 与独立 frameId 校验；opaque origin 的首次握手只能使用通配目标，不传递宿主凭据。

文件读取错误由插件外层展示；格式校验、依赖和 React 渲染错误由插件 iframe 内的兜底页展示，不依赖宿主替换。两层与加载态共用插图布局：80px 高的 SVG 中心固定在预览中点上方 64px，标题和原因从中点上方 4px 起向下独立滚动，长错误不会挤动插图。错误页使用本地化标题、纯文本原因与中性实心重试按钮；`frame-boundary` 会说明应移除文档/脚本标签并保留 TSX 默认组件导出，其他错误保留实际原因。修正源码并收到新版本后自动恢复；重试重启当前 iframe，不改变文件格式校验和隔离边界。导出的交互 HTML 复用同一布局。

## 导出报告

提供 `yuri.previewActions` v1 的宿主负责操作区排版：移动端标题行、PC 右上角悬浮位置，与源码切换并排。插件注册当前 iframe 的 `element/capture/render`，`render(surface)` 的 PDF/PNG 点击回调通过 `surface.snapshot()` 获取该实例最新内容，所有导出任务都使用 `surface.signal`。卸载、源码切换和重试撤销按钮；两份预览互不串用快照或源码。未提供该契约时使用内联悬浮菜单。

入口仅显示 16px 下载图标，36px 触控区域采用淡黑半透明背景，无明显边框和强阴影；「导出」文字仅保留于本地化 aria-label/title。点击后才出现菜单，忙碌圆环与成功小勾号均在入口原位显示。

预览右上角悬浮的「导出」下拉菜单支持 PDF、PNG 长图和交互 HTML 单文件，不占用整行、不移动报告。PDF/PNG 保留当前页面的筛选、输入和展开状态，HTML 包含可重新运行的页面源码。菜单支持 Escape 归还入口焦点、外点（含 iframe）收起；加载未就绪时禁用。PDF/PNG 通过官方 `Contract.define` / `ctx.use` 分别消费 Yuri 的两个客户端 GSAPI：`yuri.exportPDF` 和 `yuri.exportLongImage`。插件只有窗口 setup，原生渲染和保存由当前设备的宿主实现。

PDF/PNG 的契约独立判断 `active` 且 `value.version === 1`，不可用时隐藏对应菜单项。能力属于当前客户端设备，与连接本地、远端、LAN 或 Relay 服务无关。Electron 或安装了对应原生实现的移动壳可提供能力。能力撤销/替换取消对应格式的任务；另一格式变化不打断当前任务。快照开始与调用原生保存前重新检查对应能力及 generation，关闭预览或内容更新也会取消任务。能力恢复不会重挂 iframe 或丢失交互状态。

「导出 HTML」始终保留，预览就绪后可用，不依赖 PDF/PNG 契约。`frame.exportHTML()` 获取当前已渲染版本的源码，通过共用的 `src/frame-document.ts` 生成完整 HTML，内嵌 Eficy/React 运行时、编译器和启动逻辑。打开文件后自动挂载页面，Signals、computed、输入绑定和组件事件继续工作，不依赖宿主消息。独立模式不注册宿主消息或本地文件链接转发，重试按钮直接重新加载文档。主题继承当前预览；标题和源码经过 HTML/script 边界转义。

HTML 打开时从源码初始状态运行，不序列化已有 Signals 值。HTTPS 组件、CSS、图片和字体保留原 URL，加载它们仍需网络与 CORS；仅内置依赖的页面可离线运行。文件通过 SDK `ctx.system.save({ name, content })` 保存，桌面端弹保存框，网页端下载。生成文档前可以取消；保存框打开后由保存框确认或取消，SDK 返回的布尔值决定最终状态。

结构类型在 `src/export-types.ts` 中维护，契约声明在 `src/export-contract.ts`。公开输入为 `{ snapshot: { html, width, height }, filename }`；PDF 另有可选 `pageSize: 'a4' | 'letter'`，当前按钮使用 A4。每个能力提供 `version: 1`、各自的 `limits` 和各自的方法 `exportPDF` / `exportLongImage`，调用选项为 `{ signal, onProgress }`。插件按能力限制检查 HTML UTF-8 字节、宽高和像素总数；宿主仍独立执行资源及安全校验。

快照在 iframe 内通过 `html-to-image` 收集 DOM、计算样式、字体和图片（含 canvas 数据），将 SVG 的 foreignObject 内容转换为静态自包含 HTML，补齐序列化后的表单状态，再交给宿主。宿主原生导出页禁用脚本、外部网络和导航。插件不执行报告源码的第二次渲染，不生成最终 PDF/PNG；HTML 文件保存及浏览器下载由 SDK 处理。

导出进行中仅显示双 circle 圆环与中央取消图标；真实阶段通过读屏状态播报。仅当存在有效 `completed` 与正数 `total` 时显示确定进度（百分比供读屏），其余阶段旋转而不估算，并尊重减少动画偏好。方法完成返回 `{ status: 'saved' | 'cancelled' }`，以原生终态为准：保存已经提交后收到取消请求仍短暂显示成功勾号，原生确认取消才播报取消；已销毁工具栏不更新终态。失败 reject 携带 `EXPORT_*` code；`EXPORT_ABORTED` 显示取消，其他错误显示精简失败提示，详细错误通过官方 `{{error}}` 插值保留在 title 和 aria-live 中，可重新打开菜单重试。取消后的迟到进度不更新界面。

## 文件类型图标

GUI 同包携带 `.eficy` 的 E 字母文件图标，通过官方 `Registry.define` 注册到 Yuri 的可选 `yuri.file-icon` 扩展。文件树、标签页和文件引用共享此图标；关闭插件 GUI 后恢复宿主默认图标。图标随 GUI bundle 更新，不需要修改 Yuri 内置扩展名表。 这不是 OpenCode SDK 的内置文件图标接口，其他宿主若不消费该 registry，仍可使用 同一插件的预览和 skill。

```ts
const FileIcon = Registry.define<{
  id: string;
  extensions: readonly string[];
  svg: string;
  lightSvg?: string;
}>('yuri.file-icon');
ctx.add(FileIcon, { id: 'eficy', extensions: ['eficy'], svg: fileIcon });
```

## 版本与更新

内置依赖版本以 `package.json` 和锁文件为源，构建产出 `dist/runtime-manifest.json`，服务端将版本注入 skill。外部组件版本由文件中的 HTTPS URL 决定；更新后需重新验证导出、样式、React 兼容和交互。

更新包依赖后须重新构建内置运行时和 GUI，运行验证，更新插件版本，并把运行时产物、manifest 与 skill 同包发布。不能只改 skill 里的文字来宣称运行时已升级。解析器使用已固定 Sucrase 版本的内部 token API，升级 Sucrase 时同时验证 parser 测试和浏览器编译行为。

构建同时校验安装版本与 lock，版本号只来自 `package.json`，不在构建脚本另抄一份。官方 browser 1.2.4 的 standalone 仍含动态分块，因此先用标准 Webpack context 和单 chunk 构建合并官方文件，再作为文本内置于标准 GUI CJS；没有改写上游源码。生成资产内嵌同一 manifest，旧资产与新版本清单不匹配时构建失败。

## 验证范围

`tests/parser.test.ts` 覆盖真实语法、默认导出、导入策略、字节边界、文档标签与 skill 示例；`tests/server.test.ts` 使用真实 SDK 定义执行 skill/tool transforms，检查 manifest 注入和工具错误结果。先构建运行时，再运行测试。

`tests/legacy-report.test.ts` 使用真实内置 Eficy 编译器、上游 UI 与 Recharts，在 happy-dom 执行旧报告消费者，覆盖两个命名空间、嵌套 computed、component/batch 交互、ChartContainer 图形和 Tooltip 内容。测试只在模块解析边界用本机已安装的同版本库替代 HTTPS，布局尺寸由测试提供；CDN、import map 和实际布局仍需浏览器验收。可用 `EFICY_LEGACY_REPORT=/path/to/KF-ITERATION-REPORT.shadcn.eficy pnpm exec vitest run tests/legacy-report.test.ts` 直接运行原报告，文件按原文读取，验证四张图表与展开交互；未提供路径时跳过这一外部文件用例。

默认图表 fixture 用已安装 Recharts 模拟新包的 namespace/named exports；设置 `EFICY_CHARTS_FIXTURE=/path/to/charts/dist/index.js` 可用真实 charts standalone 替代。两种路径均检查 ChartTooltip/ChartLegend 与 namespace 的组件身份；fixture 仅用于测试，不是生产依赖。

自动测试不能替代浏览器验收。实际宿主应检查：文件链接与侧边文件树打开后的预览、Signals 交互、HTTPS 模块/CSS 加载、源码更新、错误与修复、跨文件/会话隔离和关闭清理。外部依赖断网或 404 时须显示可恢复错误，不承诺离线可用。

## 常见问题

### @eficy/opencode2-plugin 是什么？

自成一体的Eficy TSX预览、技能和OpenCode 2验证器

### 如何安装 @eficy/opencode2-plugin？

在项目目录运行 npm install @eficy/opencode2-plugin，或使用 pnpm add / yarn add / bun add。

### @eficy/opencode2-plugin 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/eficy\_\_opencode2-plugin 是否存在。

### @eficy/opencode2-plugin 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @eficy/opencode2-plugin 可以商用吗？

@eficy/opencode2-plugin 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @eficy/opencode2-plugin 的下载量有多少？

根据 npm 官方下载统计，@eficy/opencode2-plugin 在 2026/10/13 – 2026/11/11 这 30 天内被下载 3,578 次，日均约 119 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @eficy/opencode2-plugin 还在维护吗？

最新版本 0\.5\.9 发布于 2026/11/04（9 天前）；至今共发布 21 个版本，其中过去 12 个月发布了 21 个；首次发布于 2026/10/28。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

