mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat: Expose plugin share metadata in shareContext (#21495)
Extends PluginSummary.shareContext with shareUrl and reader shareTargets
This commit is contained in:
committed by
GitHub
Unverified
parent
3444b0d60a
commit
114bac1409
+15
@@ -12187,6 +12187,21 @@
|
||||
},
|
||||
"remotePluginId": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareTargets": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/PluginSharePrincipal"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"shareUrl": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
+15
@@ -8798,6 +8798,21 @@
|
||||
},
|
||||
"remotePluginId": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareTargets": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginSharePrincipal"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"shareUrl": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -248,6 +248,21 @@
|
||||
},
|
||||
"remotePluginId": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareTargets": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginSharePrincipal"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"shareUrl": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -255,6 +270,33 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginSharePrincipal": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"principalId": {
|
||||
"type": "string"
|
||||
},
|
||||
"principalType": {
|
||||
"$ref": "#/definitions/PluginSharePrincipalType"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"principalId",
|
||||
"principalType"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginSharePrincipalType": {
|
||||
"enum": [
|
||||
"user",
|
||||
"group",
|
||||
"workspace"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginSource": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -302,6 +302,21 @@
|
||||
},
|
||||
"remotePluginId": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareTargets": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginSharePrincipal"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"shareUrl": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -309,6 +324,33 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginSharePrincipal": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"principalId": {
|
||||
"type": "string"
|
||||
},
|
||||
"principalType": {
|
||||
"$ref": "#/definitions/PluginSharePrincipalType"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"principalId",
|
||||
"principalType"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginSharePrincipalType": {
|
||||
"enum": [
|
||||
"user",
|
||||
"group",
|
||||
"workspace"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginSource": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -183,6 +183,21 @@
|
||||
},
|
||||
"remotePluginId": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareTargets": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginSharePrincipal"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"shareUrl": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -215,6 +230,33 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginSharePrincipal": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"principalId": {
|
||||
"type": "string"
|
||||
},
|
||||
"principalType": {
|
||||
"$ref": "#/definitions/PluginSharePrincipalType"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"principalId",
|
||||
"principalType"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginSharePrincipalType": {
|
||||
"enum": [
|
||||
"user",
|
||||
"group",
|
||||
"workspace"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginSource": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// 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 { PluginSharePrincipal } from "./PluginSharePrincipal";
|
||||
|
||||
export type PluginShareContext = { remotePluginId: string, creatorAccountUserId: string | null, creatorName: string | null, };
|
||||
export type PluginShareContext = { remotePluginId: string, shareUrl: string | null, creatorAccountUserId: string | null, creatorName: string | null, shareTargets: Array<PluginSharePrincipal> | null, };
|
||||
|
||||
@@ -539,8 +539,10 @@ pub struct PluginSummary {
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct PluginShareContext {
|
||||
pub remote_plugin_id: String,
|
||||
pub share_url: Option<String>,
|
||||
pub creator_account_user_id: Option<String>,
|
||||
pub creator_name: Option<String>,
|
||||
pub share_targets: Option<Vec<PluginSharePrincipal>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
|
||||
@@ -108,8 +108,10 @@ fn share_context_for_source(
|
||||
.cloned()
|
||||
.map(|remote_plugin_id| PluginShareContext {
|
||||
remote_plugin_id,
|
||||
share_url: None,
|
||||
creator_account_user_id: None,
|
||||
creator_name: None,
|
||||
share_targets: None,
|
||||
}),
|
||||
MarketplacePluginSource::Git { .. } => None,
|
||||
}
|
||||
@@ -1473,8 +1475,15 @@ fn remote_plugin_share_context_to_info(
|
||||
) -> PluginShareContext {
|
||||
PluginShareContext {
|
||||
remote_plugin_id: context.remote_plugin_id,
|
||||
share_url: context.share_url,
|
||||
creator_account_user_id: context.creator_account_user_id,
|
||||
creator_name: context.creator_name,
|
||||
share_targets: context.share_targets.map(|targets| {
|
||||
targets
|
||||
.into_iter()
|
||||
.map(plugin_share_principal_from_remote)
|
||||
.collect()
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ use codex_app_server_protocol::PluginListMarketplaceKind;
|
||||
use codex_app_server_protocol::PluginListParams;
|
||||
use codex_app_server_protocol::PluginListResponse;
|
||||
use codex_app_server_protocol::PluginMarketplaceEntry;
|
||||
use codex_app_server_protocol::PluginSharePrincipal;
|
||||
use codex_app_server_protocol::PluginSharePrincipalType;
|
||||
use codex_app_server_protocol::PluginSource;
|
||||
use codex_app_server_protocol::PluginSummary;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
@@ -692,8 +694,10 @@ async fn plugin_list_returns_share_context_for_shared_local_plugin() -> Result<(
|
||||
.as_ref()
|
||||
.expect("expected share context");
|
||||
assert_eq!(share_context.remote_plugin_id, "plugins_123");
|
||||
assert_eq!(share_context.share_url, None);
|
||||
assert_eq!(share_context.creator_account_user_id, None);
|
||||
assert_eq!(share_context.creator_name, None);
|
||||
assert_eq!(share_context.share_targets, None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1735,6 +1739,18 @@ async fn plugin_list_fetches_shared_with_me_kind() -> Result<()> {
|
||||
Some("user-gavin__account-123")
|
||||
);
|
||||
assert_eq!(share_context.creator_name.as_deref(), Some("Gavin"));
|
||||
assert_eq!(
|
||||
share_context.share_url.as_deref(),
|
||||
Some("https://chatgpt.example/plugins/share/share-key-1")
|
||||
);
|
||||
assert_eq!(
|
||||
share_context.share_targets,
|
||||
Some(vec![PluginSharePrincipal {
|
||||
principal_type: PluginSharePrincipalType::User,
|
||||
principal_id: "user-ada__account-123".to_string(),
|
||||
name: "Ada".to_string(),
|
||||
}])
|
||||
);
|
||||
wait_for_remote_plugin_request_count(&server, "/ps/plugins/list", /*expected_count*/ 0).await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -2260,10 +2276,25 @@ fn workspace_remote_plugin_page_body(
|
||||
"name": "{plugin_name}",
|
||||
"scope": "WORKSPACE",
|
||||
"creator_account_user_id": "user-gavin__account-123",
|
||||
"share_url": "https://chatgpt.example/plugins/share/share-key-1",
|
||||
"installation_policy": "AVAILABLE",
|
||||
"authentication_policy": "ON_USE",
|
||||
"status": "ENABLED",
|
||||
"creator_name": "Gavin",
|
||||
"share_principals": [
|
||||
{{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-gavin__account-123",
|
||||
"role": "owner",
|
||||
"name": "Gavin"
|
||||
}},
|
||||
{{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-ada__account-123",
|
||||
"role": "reader",
|
||||
"name": "Ada"
|
||||
}}
|
||||
],
|
||||
"release": {{
|
||||
"display_name": "{display_name}",
|
||||
"description": "Track work",
|
||||
|
||||
@@ -23,6 +23,8 @@ use codex_app_server_protocol::PluginAuthPolicy;
|
||||
use codex_app_server_protocol::PluginInstallPolicy;
|
||||
use codex_app_server_protocol::PluginReadParams;
|
||||
use codex_app_server_protocol::PluginReadResponse;
|
||||
use codex_app_server_protocol::PluginSharePrincipal;
|
||||
use codex_app_server_protocol::PluginSharePrincipalType;
|
||||
use codex_app_server_protocol::PluginSkillReadParams;
|
||||
use codex_app_server_protocol::PluginSkillReadResponse;
|
||||
use codex_app_server_protocol::PluginSource;
|
||||
@@ -237,6 +239,21 @@ async fn plugin_read_returns_share_context_for_shared_remote_plugin() -> Result<
|
||||
"scope": "WORKSPACE",
|
||||
"creator_account_user_id": "user-gavin__account-123",
|
||||
"creator_name": "Gavin",
|
||||
"share_url": "https://chatgpt.example/plugins/share/share-key-1",
|
||||
"share_principals": [
|
||||
{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-gavin__account-123",
|
||||
"role": "owner",
|
||||
"name": "Gavin"
|
||||
},
|
||||
{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-ada__account-123",
|
||||
"role": "reader",
|
||||
"name": "Ada"
|
||||
}
|
||||
],
|
||||
"installation_policy": "AVAILABLE",
|
||||
"authentication_policy": "ON_USE",
|
||||
"release": {
|
||||
@@ -307,6 +324,18 @@ async fn plugin_read_returns_share_context_for_shared_remote_plugin() -> Result<
|
||||
Some("user-gavin__account-123")
|
||||
);
|
||||
assert_eq!(share_context.creator_name.as_deref(), Some("Gavin"));
|
||||
assert_eq!(
|
||||
share_context.share_url.as_deref(),
|
||||
Some("https://chatgpt.example/plugins/share/share-key-1")
|
||||
);
|
||||
assert_eq!(
|
||||
share_context.share_targets,
|
||||
Some(vec![PluginSharePrincipal {
|
||||
principal_type: PluginSharePrincipalType::User,
|
||||
principal_id: "user-ada__account-123".to_string(),
|
||||
name: "Ada".to_string(),
|
||||
}])
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -766,8 +795,10 @@ async fn plugin_read_returns_share_context_for_shared_local_plugin() -> Result<(
|
||||
.as_ref()
|
||||
.expect("expected share context");
|
||||
assert_eq!(share_context.remote_plugin_id, "plugins_123");
|
||||
assert_eq!(share_context.share_url, None);
|
||||
assert_eq!(share_context.creator_account_user_id, None);
|
||||
assert_eq!(share_context.creator_name, None);
|
||||
assert_eq!(share_context.share_targets, None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -662,8 +662,10 @@ fn expected_plugin_interface() -> PluginInterface {
|
||||
fn expected_share_context(plugin_id: &str) -> PluginShareContext {
|
||||
PluginShareContext {
|
||||
remote_plugin_id: plugin_id.to_string(),
|
||||
share_url: Some("https://chatgpt.example/plugins/share/share-key-1".to_string()),
|
||||
creator_account_user_id: None,
|
||||
creator_name: None,
|
||||
share_targets: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,8 +98,10 @@ pub struct RemotePluginSummary {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct RemotePluginShareContext {
|
||||
pub remote_plugin_id: String,
|
||||
pub share_url: Option<String>,
|
||||
pub creator_account_user_id: Option<String>,
|
||||
pub creator_name: Option<String>,
|
||||
pub share_targets: Option<Vec<RemotePluginSharePrincipal>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -363,6 +365,8 @@ struct RemotePluginDirectoryItem {
|
||||
creator_name: Option<String>,
|
||||
#[serde(default)]
|
||||
share_url: Option<String>,
|
||||
#[serde(default)]
|
||||
share_principals: Option<Vec<RemotePluginDirectorySharePrincipal>>,
|
||||
installation_policy: PluginInstallPolicy,
|
||||
authentication_policy: PluginAuthPolicy,
|
||||
#[serde(rename = "status", default)]
|
||||
@@ -370,6 +374,15 @@ struct RemotePluginDirectoryItem {
|
||||
release: RemotePluginReleaseResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
struct RemotePluginDirectorySharePrincipal {
|
||||
principal_type: RemotePluginSharePrincipalType,
|
||||
principal_id: String,
|
||||
#[serde(default)]
|
||||
role: Option<String>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
struct RemotePluginInstalledItem {
|
||||
#[serde(flatten)]
|
||||
@@ -831,8 +844,20 @@ fn remote_plugin_share_context(
|
||||
RemotePluginScope::Global => None,
|
||||
RemotePluginScope::Workspace => Some(RemotePluginShareContext {
|
||||
remote_plugin_id: plugin.id.clone(),
|
||||
share_url: plugin.share_url.clone(),
|
||||
creator_account_user_id: plugin.creator_account_user_id.clone(),
|
||||
creator_name: plugin.creator_name.clone(),
|
||||
share_targets: plugin.share_principals.as_ref().map(|principals| {
|
||||
principals
|
||||
.iter()
|
||||
.filter(|principal| principal.role.as_deref() == Some("reader"))
|
||||
.map(|principal| RemotePluginSharePrincipal {
|
||||
principal_type: principal.principal_type,
|
||||
principal_id: principal.principal_id.clone(),
|
||||
name: principal.name.clone(),
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,15 +107,17 @@ fn remote_plugin_json(plugin_id: &str) -> serde_json::Value {
|
||||
})
|
||||
}
|
||||
|
||||
fn remote_plugin_json_with_share_url(
|
||||
fn remote_plugin_json_with_share_url_and_principals(
|
||||
plugin_id: &str,
|
||||
share_url: Option<&str>,
|
||||
share_principals: serde_json::Value,
|
||||
) -> serde_json::Value {
|
||||
let mut plugin = remote_plugin_json(plugin_id);
|
||||
let serde_json::Value::Object(fields) = &mut plugin else {
|
||||
unreachable!("plugin json should be an object");
|
||||
};
|
||||
fields.insert("share_url".to_string(), json!(share_url));
|
||||
fields.insert("share_principals".to_string(), share_principals);
|
||||
plugin
|
||||
}
|
||||
|
||||
@@ -489,9 +491,23 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
|
||||
))
|
||||
.and(query_param_is_missing("pageToken"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"plugins": [remote_plugin_json_with_share_url(
|
||||
"plugins": [remote_plugin_json_with_share_url_and_principals(
|
||||
"plugins_123",
|
||||
Some("https://chatgpt.example/plugins/share/share-key-1"),
|
||||
json!([
|
||||
{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-owner",
|
||||
"role": "owner",
|
||||
"name": "Owner",
|
||||
},
|
||||
{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-reader",
|
||||
"role": "reader",
|
||||
"name": "Reader",
|
||||
},
|
||||
]),
|
||||
)],
|
||||
"pagination": {
|
||||
"next_page_token": "page-2"
|
||||
@@ -510,7 +526,29 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
|
||||
))
|
||||
.and(query_param("pageToken", "page-2"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"plugins": [remote_plugin_json_with_share_url("plugins_456", /*share_url*/ None)],
|
||||
"plugins": [remote_plugin_json_with_share_url_and_principals(
|
||||
"plugins_456",
|
||||
/*share_url*/ None,
|
||||
json!([
|
||||
{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-owner",
|
||||
"role": "owner",
|
||||
"name": "Owner",
|
||||
},
|
||||
{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-editor",
|
||||
"role": "editor",
|
||||
"name": "Editor",
|
||||
},
|
||||
{
|
||||
"principal_type": "user",
|
||||
"principal_id": "user-missing-role",
|
||||
"name": "Missing Role",
|
||||
},
|
||||
]),
|
||||
)],
|
||||
"pagination": empty_pagination_json(),
|
||||
})))
|
||||
.expect(1)
|
||||
@@ -540,8 +578,16 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
|
||||
name: "demo-plugin".to_string(),
|
||||
share_context: Some(RemotePluginShareContext {
|
||||
remote_plugin_id: "plugins_123".to_string(),
|
||||
share_url: Some(
|
||||
"https://chatgpt.example/plugins/share/share-key-1".to_string(),
|
||||
),
|
||||
creator_account_user_id: None,
|
||||
creator_name: None,
|
||||
share_targets: Some(vec![RemotePluginSharePrincipal {
|
||||
principal_type: RemotePluginSharePrincipalType::User,
|
||||
principal_id: "user-reader".to_string(),
|
||||
name: "Reader".to_string(),
|
||||
}]),
|
||||
}),
|
||||
installed: false,
|
||||
enabled: false,
|
||||
@@ -560,8 +606,10 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
|
||||
name: "demo-plugin".to_string(),
|
||||
share_context: Some(RemotePluginShareContext {
|
||||
remote_plugin_id: "plugins_456".to_string(),
|
||||
share_url: None,
|
||||
creator_account_user_id: None,
|
||||
creator_name: None,
|
||||
share_targets: Some(Vec::new()),
|
||||
}),
|
||||
installed: true,
|
||||
enabled: true,
|
||||
|
||||
Reference in New Issue
Block a user