mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Support npm marketplace plugin sources (#29375)
## Why
Marketplace source deserialization treated `{"source":"npm", ...}` as
unsupported. The loader logged and skipped the entry, so npm-backed
plugins never appeared in `plugin list --available` and `plugin add`
returned "plugin not found".
Codex plugins are installed from a plugin root, not from an npm
dependency tree. For npm-backed marketplace entries, Codex should fetch
the published package contents without running package scripts or
installing unrelated dependencies.
## What changed
- Add `npm` marketplace plugin sources with `package`, optional semver
`version` or version range, and optional HTTPS `registry`.
- Reject unsafe npm source fields before materialization, including
invalid package names, non-semver version selectors, plaintext or
credential-bearing registry URLs, and registry query/fragment data.
- Materialize npm plugins with `npm pack --ignore-scripts`, then unpack
the resulting tarball through the existing hardened plugin bundle
extractor.
- Enforce npm archive and extracted-size limits, require the standard
npm `package/` archive root, and verify the extracted `package.json`
name matches the requested package before installing.
- Keep plugin listings, install-source descriptions, CLI JSON/human
output, app-server v2 `PluginSource`, TUI source summaries, regenerated
schema fixtures, and app-server documentation in sync.
## Impact
Marketplaces can distribute Codex plugins from public or configured
private HTTPS npm registries using the same install flow as existing
materialized plugin sources. `npm` must be available on `PATH` when an
npm-backed plugin is installed.
Fixes #27831
## Validation
- `just write-app-server-schema`
- `just test -p codex-core-plugins -p codex-app-server-protocol -p
codex-app-server -p codex-cli`
- npm/schema/core-plugin coverage passed in the run.
- The full focused command finished with `1739 passed`, `11 failed`, and
`6 timed out`; the failures were unrelated local app-server environment
failures from `sandbox-exec: sandbox_apply: Operation not permitted`
plus one missing `test_stdio_server` helper binary.
- Installed an npm-published Codex plugin package through a throwaway
local marketplace and throwaway `CODEX_HOME` to exercise the real npm
materialization path end to end.
This commit is contained in:
committed by
GitHub
Unverified
parent
526f495f3a
commit
6509f3148a
@@ -285,6 +285,20 @@ pub async fn run_plugin_list(
|
||||
}
|
||||
parts.join(", ")
|
||||
}
|
||||
codex_core_plugins::marketplace::MarketplacePluginSource::Npm {
|
||||
package,
|
||||
version,
|
||||
registry,
|
||||
} => {
|
||||
let mut parts = vec![package.clone()];
|
||||
if let Some(version) = version {
|
||||
parts.push(format!("version `{version}`"));
|
||||
}
|
||||
if let Some(registry) = registry {
|
||||
parts.push(format!("registry `{registry}`"));
|
||||
}
|
||||
parts.join(", ")
|
||||
}
|
||||
};
|
||||
plugin_width = plugin_width.max(plugin.id.len());
|
||||
status_width = status_width.max(state.len());
|
||||
@@ -412,6 +426,13 @@ enum JsonPluginSource {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
sha: Option<String>,
|
||||
},
|
||||
Npm {
|
||||
package: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
version: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
registry: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
impl JsonPluginSource {
|
||||
@@ -437,6 +458,15 @@ impl JsonPluginSource {
|
||||
ref_name,
|
||||
sha,
|
||||
} => Self::Git { url, ref_name, sha },
|
||||
MarketplacePluginSource::Npm {
|
||||
package,
|
||||
version,
|
||||
registry,
|
||||
} => Self::Npm {
|
||||
package,
|
||||
version,
|
||||
registry,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user