feat(plugins): Add universal plugin support#113
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Add a canonical .agents/plugins plugin model based on the Codex manifest shape and generate deterministic runtime outputs for supported agent tools. Wire plugin declarations through config loading, lockfiles, install, sync, list, doctor, gitignore handling, and documentation. Reject same-project plugin installs that would overwrite their own source and cover the new behavior with regression tests. Co-Authored-By: Codex <codex@openai.com>
f70f2bf to
925d589
Compare
Keep plugin lock entries after bundle installation so later syncs can repair runtime projection failures. Validate same-project plugin declarations in doctor, emit a single conventional OpenCode module, escape generated OpenCode imports, and preserve empty resolved paths for root git plugins. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Use a manifest-shaped marketplace overlay so marketplace source and policy metadata do not leak into installed plugin manifests or generated Codex manifests. Reject same-project plugin declarations during frozen installs so frozen mode matches normal install, sync, and doctor behavior. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Report missing plugin bundles as errors, avoid OpenCode stubs for absent explicit modules, and reject user-scope plugin declarations until user-scope projections are defined. Document the project-scope-only plugin behavior in the public docs and specs. Co-Authored-By: GPT-5 Codex <codex@openai.com>
92df14a to
7b2c0fe
Compare
7b2c0fe to
a9a6f7b
Compare
a9a6f7b to
73edb08
Compare
Keep .agents/plugins/marketplace.json as authored canonical input instead of a generated or pruned runtime artifact. Tighten marketplace selector resolution and avoid treating unsupported source objects or URL-like paths as local filesystem paths. Preserve manifest-declared plugin names through validation, reject explicit path name mismatches, prefer directory-name plugin matches over root manifest matches, and keep same-project plugin aliases out of managed .agents/.gitignore entries. Report plugin sync issues from the repaired state, surface user-scope plugins as unsupported in doctor, and export public plugin config and lockfile types from the host package barrels. Extend the checked-in smoke example with a portable plugin fixture that exercises Claude, Cursor, Codex, Grok, and OpenCode plugin output generation and sync repair. Add regression coverage for git plugin lock metadata, explicit plugin path installs, manifest mismatches, plugin discovery precedence, public plugin type exports, and the reviewed sync and doctor plugin edge cases. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Local git integration fixtures can inherit developer signing settings and hang when git commit invokes external signing helpers. Configure the temporary repositories to disable commit signing so the tests exercise dotagents behavior instead of host git config. Co-Authored-By: Codex <noreply@openai.com>
Document the boundary for same-project plugin config checks. Missing canonical plugin directories should not be treated as same-project plugins, while explicit same-project source paths remain blocked before the path exists. Co-Authored-By: Codex <noreply@openai.com>
Move target definitions, subagent handling, and plugin runtime projection into separate modules. Keep the agents barrel as a compatibility layer while reducing the plugin writer surface area. Harden git-backed tests against local commit signing and update internal architecture docs to match the new layout. Co-Authored-By: Codex <noreply@openai.com>
Skip unsupported marketplace extension sources during plugin discovery while preserving fallback discovery paths. Validate frozen wildcard skill names before repository resolution and keep declared OpenCode projections during prune. Co-Authored-By: Codex <noreply@openai.com>
Claude Code validation rejects the agents field in plugin manifests. Keep canonical plugin agents available for runtimes that support them, but omit the field from generated Claude plugin manifests. Add regression coverage with a conventional agents directory and document the current Claude projection limit. Co-Authored-By: OpenAI Codex <noreply@openai.com>
Expose dotagents plugin bundle skills and Markdown agents through OpenCode native component directories instead of generating JavaScript plugin modules. Project Pi-supported plugin skills into .agents/skills so Pi can consume the same bundles through its supported surface. Update gitignore generation, QA fixtures, docs, and regression tests for the corrected runtime behavior. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Keep Pi plugin skill projections from adding .agents/.gitignore entries when the target skill path is user-authored or otherwise unmanaged. Persist resolved install lock entries before canonical subagent file writes so recovery state matches copied artifacts if those writes fail. Cover install, sync, remove, and doctor repair paths for the Pi collision behavior. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Reject plugin discovery symlinks that resolve outside the source root and skip unsafe manifest component paths before generating runtime projections. Validate Pi-projected skill names before using them as filesystem paths so plugin bundles cannot create links outside managed skill directories. Co-Authored-By: Codex <noreply@openai.com>
Reject backslash-rooted plugin component paths and add regressions for both backslash component paths and explicit plugin path symlink escapes. Simplify the runtime component path helpers while keeping component path ownership local to plugin runtime code. Co-Authored-By: Codex <noreply@openai.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2c1f230. Configure here.
Keep remove and doctor from treating same-project canonical plugin declarations as managed gitignore entries, even when a stale lockfile plugin row shares the name. Co-Authored-By: Codex <noreply@openai.com>
| for (const issue of pluginIssues) { | ||
| issues.push({ | ||
| type: "plugins", | ||
| name: issue.name, | ||
| message: issue.issue, | ||
| }); | ||
| } |
There was a problem hiding this comment.
Bug: When an unmanaged plugin marketplace file exists, dotagents sync generates two separate, slightly different warning messages for the same underlying issue, which can be confusing.
Severity: LOW
Suggested Fix
Refactor the logic to prevent verifyPluginOutputs from checking a file if writePluginOutputs has already reported a warning for it. This will avoid generating a second, redundant "out of date" message when the initial problem is that the file cannot be written to.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: packages/dotagents/src/cli/commands/sync.ts#L415-L421
Potential issue: If an unmanaged plugin marketplace file exists when `dotagents sync` is
run, the system generates two distinct messages for the same problem. First,
`writePluginOutputs` produces a warning that the file exists and is not managed. Then,
because the file was not updated, `verifyPluginOutputs` reports that the same file is
out of date. Both messages are added to the `issues` array and displayed to the user,
creating confusion. Unlike the subagent synchronization logic, the plugin logic lacks
deduplication to prevent this.
Also affects:
packages/dotagents/src/cli/commands/sync.ts:394~400

This adds first-class plugin support using
.agents/pluginsas the canonical local layout while treating the Codex plugin manifest and marketplace shape as the generalized input model. Plugin declarations now flow through config loading, lockfiles, install, sync, list, doctor, gitignore handling, and specs/docs.The implementation separates the host runtime concerns so the plugin work is easier to review and maintain:
targets/owns agent definitions plus MCP/hook config writers,subagents/owns subagent source/runtime handling, andplugins/owns plugin schema, storage, target selection, and runtime projection. The oldagents/index.tsremains as a compatibility barrel, but the implementation no longer concentrates plugins, subagents, target definitions, and config writers in one overloaded module tree.Plugin runtime output stays intentionally narrow per target. Claude and Cursor get generated native manifests inside each canonical plugin bundle plus runtime marketplaces that point at
./.agents/plugins/<name>, but Claude omits plugin agents because currentclaude plugin validaterejectsagentsin plugin manifests. Codex gets the repo-scoped.agents/plugins/marketplace.jsonplus a generated.codex-plugin/plugin.json; Grok gets a managed bundle copy. OpenCode does not get generated JavaScript or TypeScript plugin modules from dotagents bundles; supported bundle skills are symlinked into.opencode/skills/and Markdown agents into.opencode/agents/. Pi support is limited to the surface it can consume today: plugin skills are symlinked into.agents/skills/.The latest review and QA passes tightened the edge cases around that model: unsupported marketplace extension sources are skipped instead of crashing discovery, frozen wildcard lockfile skill names are validated before resolution/copy, plugin discovery rejects symlinks that resolve outside the source root, runtime component paths are checked before manifest/projection generation, OpenCode and Pi component projections avoid unmanaged collisions and repair dangling managed links,
.agents/.gitignoreignores projected Pi skill symlinks without hiding user-authored colliding skills, install preserves resolved lock entries before canonical subagent file writes, and Claude plugin manifests no longer project the invalidagentsfield.Validation includes focused plugin runtime/store regressions covering unsafe component paths, Pi skill-name traversal, and canonical/explicit/marketplace plugin symlink escapes; affected install/sync/remove/doctor/gitignore tests with 144 passing tests;
pnpm qa:example; Docker-backed OpenCode QA provingopencode debug skillandopencode agent listcan see projected plugin components;pnpm --filter @sentry/dotagents lint; andpnpm --filter @sentry/dotagents typecheck. Garfield passed after the latest checkpoint with independent verification, and Garfield Codify did not recommend new tooling beyond the regressions already added. A fullpnpm checkalso passed lint/typecheck and all package tests except one git-backedadd.test.tscase hitting Vitest default 10s timeout; that exact file passed when rerun with--testTimeout 90000.