3 Commits

  • [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.
  • [plugins] Add dark-mode logo metadata (#29488)
    Adds additive dark-mode plugin logo metadata across manifests, remote
    catalogs, and the app-server protocol while keeping uninstalled Git
    listings free of synthetic local paths.
    
    Supersedes #28945. This replacement uses an upstream branch so trusted
    CI can use the repository-provided remote Bazel configuration.
    
    ## Current state
    
    Plugin interfaces expose only the default logo asset. Clients therefore
    cannot select a dedicated dark-mode logo even when a plugin provides
    one.
    
    ## What this PR changes
    
    - Adds nullable `logoDark` and `logoUrlDark` fields to
    `PluginInterface`.
    - Resolves local `interface.logoDark` assets and maps remote
    `logo_url_dark` values.
    - Removes path-backed interface assets, including `logoDark`, from
    uninstalled Git fallback listings until the plugin has a real local
    root.
    - Updates the bundled plugin validator and manifest reference.
    - Regenerates the app-server JSON schemas and TypeScript types.
    
    Local manifests expose `interface.logoDark` as a package-relative asset
    path. Remote catalog responses expose `logo_url_dark`. These values map
    into separate app-server fields so clients can preserve local-path and
    remote-URL handling.
    
    ## Risk
    
    The fields are additive and nullable, so existing clients retain their
    current logo behavior. The main risks are an incomplete mapping path or
    exposing a synthetic local path for an uninstalled Git plugin.
    Local-manifest, remote-catalog, fallback-listing, protocol
    serialization, and app-server integration tests cover those paths.
    
    Spiciness: 2/5
    
    ## Testing
    
    - `just write-app-server-schema`
    - `just fmt`
    - Regression test first failed with `logo_dark` resolved to
    `/assets/logo-dark.png`, then passed after the fallback-listing fix.
    - `just test -p codex-core-plugins` (267 tests passed)
    - `just test -p codex-app-server 'suite::v2::plugin'` (114 tests passed)
    - `just test -p codex-app-server-protocol -p codex-core-plugins -p
    codex-plugin -p codex-skills` (517 tests passed before the follow-up)
    - `just test -p codex-tui plugin` (47 tests passed)
    - Validated a local plugin manifest containing `interface.logoDark` with
    the bundled validator.
    
    ## Manual verification
    
    Create a local plugin with both `interface.logo` and
    `interface.logoDark`, then call `plugin/list` or `plugin/read`. Confirm
    the response contains separate `logo` and `logoDark` paths. For a remote
    catalog entry, confirm `logoUrlDark` is populated from `logo_url_dark`.
    For an uninstalled Git marketplace entry, confirm path-backed interface
    assets remain absent until installation.
    
    Issue: N/A - coordinated maintainer change.
  • [codex] Add installed-plugin mention API (#22448)
    ## Summary
    - add app-server `plugin/installed` for mention-oriented plugin loading
    - return installed plugins plus explicitly requested install-suggestion
    rows
    - keep remote handling on installed-state data instead of the broad
    catalog listing path
    
    ## Why
    The `@` mention surface only needs plugins that are usable now, plus a
    small product-approved set of install suggestions. It does not need the
    full catalog-shaped `plugin/list` payload that the Plugins page uses.
    
    ## Validation
    - `just write-app-server-schema`
    - `just fmt`
    - `cargo test -p codex-app-server-protocol`
    - `cargo test -p codex-core-plugins`
    - `cargo test -p codex-app-server --test all plugin_installed_`
    
    ## Notes
    - The package-wide `cargo test -p codex-app-server` run still hits an
    existing unrelated stack overflow in
    `in_process::tests::in_process_start_clamps_zero_channel_capacity`.
    - Companion webview PR: https://github.com/openai/openai/pull/915672