Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion codex-rs/app-server-protocol/schema/json/ClientRequest.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/v2/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ pub enum PluginListMarketplaceKind {
#[serde(rename = "shared-with-me")]
#[ts(rename = "shared-with-me")]
SharedWithMe,
#[serde(rename = "created-by-me-remote")]
#[ts(rename = "created-by-me-remote")]
CreatedByMeRemote,
Comment on lines +168 to +170

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Update the Python SDK enum for this new kind

Adding the created-by-me-remote wire value here updates the Rust protocol and TS/schema fixtures, but the Python SDK artifact is still stale: sdk/python/src/openai_codex/generated/v2_all.py's PluginListMarketplaceKind only contains local, vertical, workspace-directory, and shared-with-me. Typed Python clients cannot construct or validate the new marketplaceKinds value even though the app-server README now documents that clients can request it.

Useful? React with 👍 / 👎.

}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
Expand Down
2 changes: 2 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/v2/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2907,6 +2907,7 @@ fn plugin_list_params_serializes_marketplace_kind_filter() {
PluginListMarketplaceKind::Vertical,
PluginListMarketplaceKind::WorkspaceDirectory,
PluginListMarketplaceKind::SharedWithMe,
PluginListMarketplaceKind::CreatedByMeRemote,
]),
})
.unwrap(),
Expand All @@ -2917,6 +2918,7 @@ fn plugin_list_params_serializes_marketplace_kind_filter() {
"vertical",
"workspace-directory",
"shared-with-me",
"created-by-me-remote",
],
}),
);
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/app-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ Example with notification opt-out:
- `marketplace/add` — add a remote plugin marketplace from an HTTP(S) Git URL, SSH Git URL, or GitHub `owner/repo` shorthand, then persist it into the user marketplace config. Returns the installed root path plus whether the marketplace was already present.
- `marketplace/remove` — remove a configured marketplace by name from the user marketplace config, and delete its installed marketplace root when one exists.
- `marketplace/upgrade` — upgrade all configured Git plugin marketplaces, or one named marketplace when `marketplaceName` is provided. Returns selected marketplace names, upgraded roots, and per-marketplace errors.
- `plugin/list` — list discovered plugin marketplaces and plugin state, including effective marketplace install/auth policy metadata, plugin `availability` (`AVAILABLE` by default or `DISABLED_BY_ADMIN` for remote plugins blocked upstream), fail-open `marketplaceLoadErrors` entries for marketplace files that could not be parsed or loaded, and best-effort `featuredPluginIds` for the official curated marketplace. `interface.category` uses the marketplace category when present; otherwise it falls back to the plugin manifest category (**under development; do not call from production clients yet**).
- `plugin/list` — list discovered plugin marketplaces and plugin state, including effective marketplace install/auth policy metadata, plugin `availability` (`AVAILABLE` by default or `DISABLED_BY_ADMIN` for remote plugins blocked upstream), fail-open `marketplaceLoadErrors` entries for marketplace files that could not be parsed or loaded, and best-effort `featuredPluginIds` for the official curated marketplace. Clients can explicitly request the remote `workspace-directory`, `shared-with-me`, or `created-by-me-remote` marketplace kinds. `interface.category` uses the marketplace category when present; otherwise it falls back to the plugin manifest category (**under development; do not call from production clients yet**).
- `plugin/installed` — list installed plugin rows plus any explicitly requested local install-suggestion plugin names, without fetching the broader remote catalog. Mention surfaces can use this narrower view when they need plugin mention payloads rather than plugin-page discovery data (**under development; do not call from production clients yet**).
- `plugin/read` — read one plugin by `marketplacePath` plus `pluginName`, returning marketplace info, a list-style `summary`, manifest descriptions/interface metadata, and bundled skills/hooks/apps/MCP server names. Remote plugin details expose the canonical `shareUrl` supplied by the remote catalog when available; it is `null` for local plugins or when the catalog omits it. This field is separate from `summary.shareContext`, which continues to describe user and workspace sharing state. Returned plugin skills include their current `enabled` state after local config filtering; bundled hooks are returned as lightweight declaration summaries keyed for correlation with `hooks/list`. Use `plugin/install`'s `appsNeedingAuth` to drive post-install authentication and `app/list`'s `isAccessible` to determine current connector accessibility (**under development; do not call from production clients yet**).
- `plugin/skill/read` — read remote plugin skill markdown on demand by `remoteMarketplaceName`, `remotePluginId`, and `skillName`. This lets clients preview uninstalled remote plugin skills without downloading the plugin bundle.
Expand Down
14 changes: 13 additions & 1 deletion codex-rs/app-server/src/request_processors/plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use codex_app_server_protocol::PluginShareTargetRole;
use codex_config::types::McpServerConfig;
use codex_core_plugins::OPENAI_CURATED_MARKETPLACE_NAME;
use codex_core_plugins::PluginListBackgroundTaskOptions;
use codex_core_plugins::remote::REMOTE_CREATED_BY_ME_MARKETPLACE_NAME;
use codex_core_plugins::remote::REMOTE_GLOBAL_MARKETPLACE_NAME;
use codex_core_plugins::remote::REMOTE_WORKSPACE_MARKETPLACE_NAME;
use codex_core_plugins::remote::REMOTE_WORKSPACE_SHARED_WITH_ME_MARKETPLACE_NAME;
Expand Down Expand Up @@ -156,6 +157,7 @@ fn remote_installed_plugin_visible_marketplaces(config: &Config) -> Vec<&'static
let mut marketplaces = Vec::new();
if config.features.enabled(Feature::RemotePlugin) {
marketplaces.push(REMOTE_GLOBAL_MARKETPLACE_NAME);
marketplaces.push(REMOTE_CREATED_BY_ME_MARKETPLACE_NAME);
}
marketplaces.push(REMOTE_WORKSPACE_MARKETPLACE_NAME);
if config.features.enabled(Feature::PluginSharing) {
Expand Down Expand Up @@ -552,6 +554,9 @@ impl PluginRequestProcessor {
let plugins_input = config.plugins_config_input();
let include_shared_with_me =
marketplace_kinds.contains(&PluginListMarketplaceKind::SharedWithMe);
let include_created_by_me_remote = marketplace_kinds
.contains(&PluginListMarketplaceKind::CreatedByMeRemote)
&& config.features.enabled(Feature::RemotePlugin);
let include_global_remote =
!explicit_marketplace_kinds && config.features.enabled(Feature::RemotePlugin);
let remote_plugin_service_config = RemotePluginServiceConfig {
Expand Down Expand Up @@ -661,6 +666,9 @@ impl PluginRequestProcessor {
if include_global_remote {
remote_sources.push(RemoteMarketplaceSource::Global);
}
if include_created_by_me_remote {
remote_sources.push(RemoteMarketplaceSource::CreatedByMeRemote);
}
if marketplace_kinds.contains(&PluginListMarketplaceKind::WorkspaceDirectory) {
remote_sources.push(RemoteMarketplaceSource::WorkspaceDirectory);
}
Expand Down Expand Up @@ -711,7 +719,11 @@ impl PluginRequestProcessor {
}
}
}
if include_local || include_shared_with_me || include_global_remote {
if include_local
|| include_created_by_me_remote
|| include_shared_with_me
|| include_global_remote
{
plugins_manager.maybe_start_plugin_list_background_tasks_for_config(
&plugins_input,
auth.clone(),
Expand Down
Loading
Loading