[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
This commit is contained in:
xli-oai
2026-05-18 03:11:54 -07:00
committed by GitHub
parent 22dd9ad392
commit da14dd2add
22 changed files with 1609 additions and 82 deletions

View File

@@ -1589,6 +1589,31 @@
],
"type": "object"
},
"PluginInstalledParams": {
"properties": {
"cwds": {
"description": "Optional working directories used to discover repo marketplaces.",
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
},
"installSuggestionPluginNames": {
"description": "Additional uninstalled plugin names that should be returned when present locally. This is used by mention surfaces that intentionally expose install entrypoints.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
}
},
"type": "object"
},
"PluginListMarketplaceKind": {
"enum": [
"local",
@@ -4638,6 +4663,30 @@
"title": "Plugin/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/installed"
],
"title": "Plugin/installedRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginInstalledParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/installedRequest",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -757,6 +757,30 @@
"title": "Plugin/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"plugin/installed"
],
"title": "Plugin/installedRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/PluginInstalledParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/installedRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -11825,6 +11849,56 @@
"title": "PluginInstallResponse",
"type": "object"
},
"PluginInstalledParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"cwds": {
"description": "Optional working directories used to discover repo marketplaces.",
"items": {
"$ref": "#/definitions/v2/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
},
"installSuggestionPluginNames": {
"description": "Additional uninstalled plugin names that should be returned when present locally. This is used by mention surfaces that intentionally expose install entrypoints.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
}
},
"title": "PluginInstalledParams",
"type": "object"
},
"PluginInstalledResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"marketplaceLoadErrors": {
"default": [],
"items": {
"$ref": "#/definitions/v2/MarketplaceLoadErrorInfo"
},
"type": "array"
},
"marketplaces": {
"items": {
"$ref": "#/definitions/v2/PluginMarketplaceEntry"
},
"type": "array"
}
},
"required": [
"marketplaces"
],
"title": "PluginInstalledResponse",
"type": "object"
},
"PluginInterface": {
"properties": {
"brandColor": {

View File

@@ -1464,6 +1464,30 @@
"title": "Plugin/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/installed"
],
"title": "Plugin/installedRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginInstalledParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/installedRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -8374,6 +8398,56 @@
"title": "PluginInstallResponse",
"type": "object"
},
"PluginInstalledParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"cwds": {
"description": "Optional working directories used to discover repo marketplaces.",
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
},
"installSuggestionPluginNames": {
"description": "Additional uninstalled plugin names that should be returned when present locally. This is used by mention surfaces that intentionally expose install entrypoints.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
}
},
"title": "PluginInstalledParams",
"type": "object"
},
"PluginInstalledResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"marketplaceLoadErrors": {
"default": [],
"items": {
"$ref": "#/definitions/MarketplaceLoadErrorInfo"
},
"type": "array"
},
"marketplaces": {
"items": {
"$ref": "#/definitions/PluginMarketplaceEntry"
},
"type": "array"
}
},
"required": [
"marketplaces"
],
"title": "PluginInstalledResponse",
"type": "object"
},
"PluginInterface": {
"properties": {
"brandColor": {

View File

@@ -0,0 +1,33 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AbsolutePathBuf": {
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
}
},
"properties": {
"cwds": {
"description": "Optional working directories used to discover repo marketplaces.",
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
},
"installSuggestionPluginNames": {
"description": "Additional uninstalled plugin names that should be returned when present locally. This is used by mention surfaces that intentionally expose install entrypoints.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
}
},
"title": "PluginInstalledParams",
"type": "object"
}

View File

@@ -0,0 +1,525 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AbsolutePathBuf": {
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
},
"MarketplaceInterface": {
"properties": {
"displayName": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"MarketplaceLoadErrorInfo": {
"properties": {
"marketplacePath": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"message": {
"type": "string"
}
},
"required": [
"marketplacePath",
"message"
],
"type": "object"
},
"PluginAuthPolicy": {
"enum": [
"ON_INSTALL",
"ON_USE"
],
"type": "string"
},
"PluginAvailability": {
"oneOf": [
{
"enum": [
"DISABLED_BY_ADMIN"
],
"type": "string"
},
{
"description": "Plugin-service currently sends `\"ENABLED\"` for available remote plugins. Codex app-server exposes `\"AVAILABLE\"` in its API; the alias keeps decoding compatible with that upstream response.",
"enum": [
"AVAILABLE"
],
"type": "string"
}
]
},
"PluginInstallPolicy": {
"enum": [
"NOT_AVAILABLE",
"AVAILABLE",
"INSTALLED_BY_DEFAULT"
],
"type": "string"
},
"PluginInterface": {
"properties": {
"brandColor": {
"type": [
"string",
"null"
]
},
"capabilities": {
"items": {
"type": "string"
},
"type": "array"
},
"category": {
"type": [
"string",
"null"
]
},
"composerIcon": {
"anyOf": [
{
"$ref": "#/definitions/AbsolutePathBuf"
},
{
"type": "null"
}
],
"description": "Local composer icon path, resolved from the installed plugin package."
},
"composerIconUrl": {
"description": "Remote composer icon URL from the plugin catalog.",
"type": [
"string",
"null"
]
},
"defaultPrompt": {
"description": "Starter prompts for the plugin. Capped at 3 entries with a maximum of 128 characters per entry.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
},
"developerName": {
"type": [
"string",
"null"
]
},
"displayName": {
"type": [
"string",
"null"
]
},
"logo": {
"anyOf": [
{
"$ref": "#/definitions/AbsolutePathBuf"
},
{
"type": "null"
}
],
"description": "Local logo path, resolved from the installed plugin package."
},
"logoUrl": {
"description": "Remote logo URL from the plugin catalog.",
"type": [
"string",
"null"
]
},
"longDescription": {
"type": [
"string",
"null"
]
},
"privacyPolicyUrl": {
"type": [
"string",
"null"
]
},
"screenshotUrls": {
"description": "Remote screenshot URLs from the plugin catalog.",
"items": {
"type": "string"
},
"type": "array"
},
"screenshots": {
"description": "Local screenshot paths, resolved from the installed plugin package.",
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": "array"
},
"shortDescription": {
"type": [
"string",
"null"
]
},
"termsOfServiceUrl": {
"type": [
"string",
"null"
]
},
"websiteUrl": {
"type": [
"string",
"null"
]
}
},
"required": [
"capabilities",
"screenshotUrls",
"screenshots"
],
"type": "object"
},
"PluginMarketplaceEntry": {
"properties": {
"interface": {
"anyOf": [
{
"$ref": "#/definitions/MarketplaceInterface"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"path": {
"anyOf": [
{
"$ref": "#/definitions/AbsolutePathBuf"
},
{
"type": "null"
}
],
"description": "Local marketplace file path when the marketplace is backed by a local file. Remote-only catalog marketplaces do not have a local path."
},
"plugins": {
"items": {
"$ref": "#/definitions/PluginSummary"
},
"type": "array"
}
},
"required": [
"name",
"plugins"
],
"type": "object"
},
"PluginShareContext": {
"properties": {
"creatorAccountUserId": {
"type": [
"string",
"null"
]
},
"creatorName": {
"type": [
"string",
"null"
]
},
"discoverability": {
"anyOf": [
{
"$ref": "#/definitions/PluginShareDiscoverability"
},
{
"type": "null"
}
]
},
"remotePluginId": {
"type": "string"
},
"remoteVersion": {
"default": null,
"description": "Version of the remote shared plugin release when available.",
"type": [
"string",
"null"
]
},
"sharePrincipals": {
"items": {
"$ref": "#/definitions/PluginSharePrincipal"
},
"type": [
"array",
"null"
]
},
"shareUrl": {
"type": [
"string",
"null"
]
}
},
"required": [
"remotePluginId"
],
"type": "object"
},
"PluginShareDiscoverability": {
"enum": [
"LISTED",
"UNLISTED",
"PRIVATE"
],
"type": "string"
},
"PluginSharePrincipal": {
"properties": {
"name": {
"type": "string"
},
"principalId": {
"type": "string"
},
"principalType": {
"$ref": "#/definitions/PluginSharePrincipalType"
},
"role": {
"$ref": "#/definitions/PluginSharePrincipalRole"
}
},
"required": [
"name",
"principalId",
"principalType",
"role"
],
"type": "object"
},
"PluginSharePrincipalRole": {
"enum": [
"reader",
"editor",
"owner"
],
"type": "string"
},
"PluginSharePrincipalType": {
"enum": [
"user",
"group",
"workspace"
],
"type": "string"
},
"PluginSource": {
"oneOf": [
{
"properties": {
"path": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": {
"enum": [
"local"
],
"title": "LocalPluginSourceType",
"type": "string"
}
},
"required": [
"path",
"type"
],
"title": "LocalPluginSource",
"type": "object"
},
{
"properties": {
"path": {
"type": [
"string",
"null"
]
},
"refName": {
"type": [
"string",
"null"
]
},
"sha": {
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"git"
],
"title": "GitPluginSourceType",
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"type",
"url"
],
"title": "GitPluginSource",
"type": "object"
},
{
"description": "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.",
"properties": {
"type": {
"enum": [
"remote"
],
"title": "RemotePluginSourceType",
"type": "string"
}
},
"required": [
"type"
],
"title": "RemotePluginSource",
"type": "object"
}
]
},
"PluginSummary": {
"properties": {
"authPolicy": {
"$ref": "#/definitions/PluginAuthPolicy"
},
"availability": {
"allOf": [
{
"$ref": "#/definitions/PluginAvailability"
}
],
"default": "AVAILABLE",
"description": "Availability state for installing and using the plugin."
},
"enabled": {
"type": "boolean"
},
"id": {
"type": "string"
},
"installPolicy": {
"$ref": "#/definitions/PluginInstallPolicy"
},
"installed": {
"type": "boolean"
},
"interface": {
"anyOf": [
{
"$ref": "#/definitions/PluginInterface"
},
{
"type": "null"
}
]
},
"keywords": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
},
"localVersion": {
"default": null,
"description": "Version of the locally materialized plugin package when available.",
"type": [
"string",
"null"
]
},
"name": {
"type": "string"
},
"remotePluginId": {
"description": "Backend remote plugin identifier when available.",
"type": [
"string",
"null"
]
},
"shareContext": {
"anyOf": [
{
"$ref": "#/definitions/PluginShareContext"
},
{
"type": "null"
}
],
"description": "Remote sharing context associated with this plugin when available."
},
"source": {
"$ref": "#/definitions/PluginSource"
}
},
"required": [
"authPolicy",
"enabled",
"id",
"installPolicy",
"installed",
"name",
"source"
],
"type": "object"
}
},
"properties": {
"marketplaceLoadErrors": {
"default": [],
"items": {
"$ref": "#/definitions/MarketplaceLoadErrorInfo"
},
"type": "array"
},
"marketplaces": {
"items": {
"$ref": "#/definitions/PluginMarketplaceEntry"
},
"type": "array"
}
},
"required": [
"marketplaces"
],
"title": "PluginInstalledResponse",
"type": "object"
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
export type PluginInstalledParams = {
/**
* Optional working directories used to discover repo marketplaces.
*/
cwds?: Array<AbsolutePathBuf> | null,
/**
* Additional uninstalled plugin names that should be returned when present locally.
* This is used by mention surfaces that intentionally expose install entrypoints.
*/
installSuggestionPluginNames?: Array<string> | null, };

View File

@@ -0,0 +1,7 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { MarketplaceLoadErrorInfo } from "./MarketplaceLoadErrorInfo";
import type { PluginMarketplaceEntry } from "./PluginMarketplaceEntry";
export type PluginInstalledResponse = { marketplaces: Array<PluginMarketplaceEntry>, marketplaceLoadErrors: Array<MarketplaceLoadErrorInfo>, };

View File

@@ -265,6 +265,8 @@ export type { PluginHookSummary } from "./PluginHookSummary";
export type { PluginInstallParams } from "./PluginInstallParams";
export type { PluginInstallPolicy } from "./PluginInstallPolicy";
export type { PluginInstallResponse } from "./PluginInstallResponse";
export type { PluginInstalledParams } from "./PluginInstalledParams";
export type { PluginInstalledResponse } from "./PluginInstalledResponse";
export type { PluginInterface } from "./PluginInterface";
export type { PluginListMarketplaceKind } from "./PluginListMarketplaceKind";
export type { PluginListParams } from "./PluginListParams";