Skip to content

feat: add Codex plugin adapter wrapping opencode-adapter#1517

Open
YodonTan wants to merge 6 commits into
GCWing:mainfrom
YodonTan:feat/codex-plugin-adapter
Open

feat: add Codex plugin adapter wrapping opencode-adapter#1517
YodonTan wants to merge 6 commits into
GCWing:mainfrom
YodonTan:feat/codex-plugin-adapter

Conversation

@YodonTan

@YodonTan YodonTan commented Jul 12, 2026

Copy link
Copy Markdown

Adds a codex-adapter crate in adapters/ that wraps the existing opencode-adapter through the PluginHostAdapter trait to support Codex .codex-plugin/plugin.json plugin sources.

Key changes:

  • adapters/codex-adapter/ — new crate with manifest parsing, plugin discovery, and Codex→OpenCode event name translation
  • assembly/codex_integration/ — thin assembly layer that discovers plugins at startup and registers skills in SkillRegistry
  • SkillRegistry.add_plugin_skill_root() — enables plugin- contributed skill directories
  • system.rs — wires initialize_plugin_support() at startup

Design:

  • Zero changes to opencode-adapter crate (wraps from outside)
  • Zero changes to runtime-ports contracts (reuses OpenCodeCompatible)
  • Adapter only translates manifests; hooks execution stays in assembly (per AGENTS.md 'adapter must not execute plugins')
  • Codex hook events mapped to OpenCode lifecycle event names

Tested with 3 real Codex plugins on disk including superpowers (224k+ GitHub stars, 14 skills). All 967 existing tests pass.

AI-assisted: fully tested via 15 codex-adapter unit tests + 4 e2e integration tests verifying plugin discovery, skill registration, and hooks execution.

Summary

Fixes #

Type and Areas

Type:

Areas:

Motivation / Impact

Verification

Reviewer Notes

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

@YodonTan YodonTan left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先CI吧

@limityan limityan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

整体结论:当前实现不建议合并。主要问题不是目录命名,而是 Codex/OpenCode adapter 的边界、信任链和 Runtime Host 契约都被破坏。

关键问题与风险

  1. Codex adapter 不应包装 OpenCode adapter

    • codex-adapter/Cargo.toml 直接依赖 bitfun-opencode-adapter,实现中持有 inner OpenCode adapter,并复用 opencode-compatible adapter ID。
    • node scripts/check-core-boundaries.mjs 已明确失败:生产 crate 不得依赖或直接导入 bitfun-opencode-adapter
    • 风险:两个本应同级的外部实现被强耦合,无法独立注册、演进和降级,OpenCode 行为变化也会隐式改变 Codex 语义。
  2. 生产接线绕过 Plugin Runtime Host 和 trust

    • assembly/core/agentic/codex_integration 直接消费 adapter 内部 discovery 类型,并把发现到的 skill root 注册到全局 SkillRegistry
    • adapter 输出中的 Unknown trust、trust epoch、diagnostics 和 quarantine 均未参与启用决策。
    • 路径也没有 canonicalize/范围校验,..、绝对路径或 symlink/junction 可逃逸插件目录。
    • 风险:未审批来源可直接进入 agent 上下文,并可能跨 workspace 残留或串用。
  3. advertised adapter 不能正确履行 Host 契约

    • read_plugins 忽略 request.plugin_ids,无条件追加所有 Codex source;Runtime Host 会以 source plugin_id outside request 拒绝过滤读取。
    • Codex source 的 dispatch 被全量交给 inner OpenCode adapter,而 inner 没有对应 projection,因此只能返回 opencode.source_mismatch
    • 当前生产初始化只注册 skills;hooksmcpServers 和 event mapping 都没有生产接线,实际能力与 PR 描述不一致。
  4. 发现模型和测试不可复现

    • 实现把 .agents/plugins 当成插件父目录扫描,但该位置通常是 marketplace.json;实际插件目录由 source.path 指定,并不保证位于其直接子目录。参考 Codex plugin 文档
    • 唯一生产调用传入 None,项目范围退化为进程 CWD;plugin roots 又存入全局 registry,缺少 workspace/remote scope、replace/remove 和去重。
    • E2E 测试硬依赖作者机器上的 test-codex-plugincodex-tools-plugin;干净 CI 无法复现。cargo fmt --all -- --check 当前也未通过,GitHub 尚无 checks。

建议修改方向

  • codex-adapteropencode-adapter 保持同级、互不依赖;二者分别只实现 BitFun 稳定的 PluginHostAdapter / runtime contracts,由 Host 或 assembly 独立注册和组合。
  • 由 managed plugin source/config 层注入“已启用插件清单”和真实 workspace identity;完整经过 integrity、trust、diagnostics、quarantine 后,再注册贡献。
  • 为 Codex 来源保留独立 identity;skill registry 按 user/project/remote workspace 管理可替换集合,并校验所有贡献路径仍位于 canonical plugin root 内。
  • 如果本 PR 只做 skills,建议明确收窄范围,并对 hooks/MCP/apps 返回 typed unsupported;否则需要补全注册、生命周期、权限、错误传播和回滚。
  • 使用临时目录 fixture,补齐 filtered read、Codex dispatch、trust、同名 skill、workspace 隔离、路径逃逸及 hooks/MCP unsupported 测试;随后通过 boundary check、fmt 和对应 Rust checks,并先 rebase 最新 main

@YodonTan

Copy link
Copy Markdown
Author

将问题解决了,重新看一下呢

@limityan limityan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审结论:最新提交 6310217e 修复了 Codex/OpenCode adapter 的直接依赖、独立 adapter ID 和 filtered read,但当前仍不建议合并。

仍需解决的问题

  1. 生产接线仍绕过 Plugin Runtime Host 和信任链

    • codex_integration::initialize_plugin_support 直接 discovery 并写入全局 SkillRegistry,没有调用新 adapter,也没有消费 trust、epoch、diagnostics 或 quarantine。
    • 风险:UnknownDeniedRevoked 来源仍可进入 agent 上下文。
    • 建议:由受管 source/config 层产生可信来源,所有贡献统一经 PluginRuntimeHost 和标准 read/dispatch 契约进入产品运行时。
  2. adapter 的来源身份和信任匹配不安全

    • content hash 只基于 plugin_id,trust refs 也只按 plugin_id 匹配,并忽略 source_trust_epoch
    • 风险:插件内容、路径或版本改变后仍可能继承旧信任;同名 user/project 插件也会发生身份冲突。
    • 建议:使用完整 source/path/version/content hash 作为身份,并严格校验 trust epoch。
  3. 发现模型与 Codex 官方 marketplace 模型不一致

    • 当前扫描 .agents/plugins/ 的直接子目录;该目录通常保存 marketplace.json,实际插件根由 plugins[].source.path 指定。
    • 风险:标准 repo/personal 安装会发现 0 个插件。
    • 建议:解析 marketplace,按其根目录解析并校验 source.path,不要把 marketplace 目录本身当插件父目录。
  4. 插件 skill roots 缺少 workspace 生命周期隔离

    • roots 保存在全局 Vec,没有 workspace key、replace/remove;所有本地 workspace 都扫描同一集合,remote 路径又未覆盖。
    • 风险:workspace A 的插件可能残留并暴露给 workspace B。
    • 建议:按 workspace identity 管理可替换集合,并在切换、关闭和刷新时清理;无法支持 remote 时应显式 gate。
  5. 新增测试不可复现并已阻断 CI

    • 测试硬断言 runner 已安装作者机器上的 test-codex-plugincodex-tools-plugin
    • Windows、Ubuntu、macOS Rust tests 均因 discovered 0 plugins 在同一断言失败。
    • 建议:改用临时目录 fixture,显式注入 discovery root,不依赖 HOME/CWD 或预装插件。

node scripts/check-core-boundaries.mjs 已通过,这是有效进展。但请完成以上修复、补齐 trust/workspace/path containment 测试,并 rebase 最新 main 后再请求复审。

Tant added 2 commits July 15, 2026 22:25
Adds a codex-adapter crate in adapters/ that wraps the existing
opencode-adapter through the PluginHostAdapter trait to support
Codex .codex-plugin/plugin.json plugin sources.

Key changes:
- adapters/codex-adapter/ — new crate with manifest parsing,
  plugin discovery, and Codex→OpenCode event name translation
- assembly/codex_integration/ — thin assembly layer that
  discovers plugins at startup and registers skills in SkillRegistry
- SkillRegistry.add_plugin_skill_root() — enables plugin-
  contributed skill directories
- system.rs — wires initialize_plugin_support() at startup

Design:
- Zero changes to opencode-adapter crate (wraps from outside)
- Zero changes to runtime-ports contracts (reuses OpenCodeCompatible)
- Adapter only translates manifests; hooks execution stays in assembly
  (per AGENTS.md 'adapter must not execute plugins')
- Codex hook events mapped to OpenCode lifecycle event names

Tested with 3 real Codex plugins on disk including superpowers
(224k+ GitHub stars, 14 skills). All 967 existing tests pass.

AI-assisted: fully tested via 15 codex-adapter unit tests + 4 e2e
integration tests verifying plugin discovery, skill registration,
and hooks execution.
- Remove codex-adapter's dependency on bitfun-opencode-adapter
- Implement standalone PluginHostAdapter with independent adapter_id
- Fix read_plugins() to respect request.plugin_ids filtering
- Fix dispatch() to handle Codex events, return source_mismatch for unknowns
- Use projection model (CodexProjection) matching opencode-adapter pattern
- Pass trust snapshots through source_trust_refs at construction
- Register codex-adapter in crate-layout boundary rules
- Pass check-core-boundaries.mjs
@YodonTan
YodonTan force-pushed the feat/codex-plugin-adapter branch from 6310217 to 80392d6 Compare July 15, 2026 15:38
Tant added 4 commits July 16, 2026 08:47
… blocking

discover_plugins() calls synchronous filesystem I/O (std::fs::read_dir, read_to_string).
Running this on the Tauri async command thread blocks the Tokio runtime,
causing the plugin settings UI to hang on 'Loading plugin status...'.
All 4 call sites now use tokio::task::spawn_blocking.
…grouped UI

- Backend: all commands now use { request: { ... } } wrapper structs matching frontend convention
- Backend: PluginStatusView.scope marks user vs workspace plugins
- Backend: discover_plugins scans both ~/.agents/plugins and <ws>/.agents/plugins
- Frontend: PluginsConfig uses useCurrentWorkspace() to pass workspacePath
- Frontend: plugins grouped by scope section (user / workspace)
- i18n: added userPlugins/workspacePlugins keys (en + zh-CN)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants