feat: Track local paths for shared plugins (#20560)

When a local plugin is shared, Codex now records the local plugin path
by remote plugin id under CODEX_HOME/.tmp.

plugin/share/list includes the remote share URL and the matching local
plugin path when available, and plugin/share/delete
clears the local mapping after deleting the remote share.

Also add sharedURL to plugin/share/list.
This commit is contained in:
xl-openai
2026-05-01 00:50:12 -07:00
committed by GitHub
parent 96d2ea9058
commit 48791920a8
14 changed files with 589 additions and 76 deletions

View File

@@ -4651,7 +4651,7 @@ pub struct PluginShareListParams {}
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginShareListResponse {
pub data: Vec<PluginSummary>,
pub data: Vec<PluginShareListItem>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
@@ -4666,6 +4666,15 @@ pub struct PluginShareDeleteParams {
#[ts(export_to = "v2/")]
pub struct PluginShareDeleteResponse {}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginShareListItem {
pub plugin: PluginSummary,
pub share_url: String,
pub local_plugin_path: Option<AbsolutePathBuf>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "snake_case")]
#[ts(rename_all = "snake_case")]
@@ -10765,33 +10774,41 @@ mod tests {
}
#[test]
fn plugin_share_list_response_serializes_plugin_summaries() {
fn plugin_share_list_response_serializes_share_items() {
assert_eq!(
serde_json::to_value(PluginShareListResponse {
data: vec![PluginSummary {
id: "plugins~Plugin_00000000000000000000000000000000".to_string(),
name: "gmail".to_string(),
source: PluginSource::Remote,
installed: false,
enabled: false,
install_policy: PluginInstallPolicy::Available,
auth_policy: PluginAuthPolicy::OnUse,
availability: PluginAvailability::Available,
interface: None,
data: vec![PluginShareListItem {
plugin: PluginSummary {
id: "plugins~Plugin_00000000000000000000000000000000".to_string(),
name: "gmail".to_string(),
source: PluginSource::Remote,
installed: false,
enabled: false,
install_policy: PluginInstallPolicy::Available,
auth_policy: PluginAuthPolicy::OnUse,
availability: PluginAvailability::Available,
interface: None,
},
share_url: "https://chatgpt.example/plugins/share/share-key-1".to_string(),
local_plugin_path: None,
}],
})
.unwrap(),
json!({
"data": [{
"id": "plugins~Plugin_00000000000000000000000000000000",
"name": "gmail",
"source": { "type": "remote" },
"installed": false,
"enabled": false,
"installPolicy": "AVAILABLE",
"authPolicy": "ON_USE",
"availability": "AVAILABLE",
"interface": null,
"plugin": {
"id": "plugins~Plugin_00000000000000000000000000000000",
"name": "gmail",
"source": { "type": "remote" },
"installed": false,
"enabled": false,
"installPolicy": "AVAILABLE",
"authPolicy": "ON_USE",
"availability": "AVAILABLE",
"interface": null,
},
"shareUrl": "https://chatgpt.example/plugins/share/share-key-1",
"localPluginPath": null,
}],
}),
);