Codex Handbook
app-server-protocol/src/protocol/v2/plugin.rs 869 lines
use super::AppSummary;use super::HookEventName;use super::HookHandlerType;use super::HookSource;use super::HookTrustStatus;use codex_protocol::protocol::SkillDependencies as CoreSkillDependencies;use codex_protocol::protocol::SkillInterface as CoreSkillInterface;use codex_protocol::protocol::SkillMetadata as CoreSkillMetadata;use codex_protocol::protocol::SkillScope as CoreSkillScope;use codex_protocol::protocol::SkillToolDependency as CoreSkillToolDependency;use codex_utils_absolute_path::AbsolutePathBuf;use schemars::JsonSchema;use serde::Deserialize;use serde::Serialize;use std::path::PathBuf;use ts_rs::TS;#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillsListParams {    /// When empty, defaults to the current session working directory.    #[serde(default, skip_serializing_if = "Vec::is_empty")]    pub cwds: Vec<PathBuf>,    /// When true, bypass the skills cache and re-scan skills from disk.    #[serde(default, skip_serializing_if = "std::ops::Not::not")]    pub force_reload: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillsListResponse {    pub data: Vec<SkillsListEntry>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillsExtraRootsSetParams {    pub extra_roots: Vec<AbsolutePathBuf>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillsExtraRootsSetResponse {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct HooksListParams {    /// When empty, defaults to the current session working directory.    #[serde(default, skip_serializing_if = "Vec::is_empty")]    pub cwds: Vec<PathBuf>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct HooksListResponse {    pub data: Vec<HooksListEntry>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceAddParams {    pub source: String,    #[ts(optional = nullable)]    pub ref_name: Option<String>,    #[ts(optional = nullable)]    pub sparse_paths: Option<Vec<String>>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceAddResponse {    pub marketplace_name: String,    pub installed_root: AbsolutePathBuf,    pub already_added: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceRemoveParams {    pub marketplace_name: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceRemoveResponse {    pub marketplace_name: String,    pub installed_root: Option<AbsolutePathBuf>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceUpgradeParams {    #[ts(optional = nullable)]    pub marketplace_name: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceUpgradeResponse {    pub selected_marketplaces: Vec<String>,    pub upgraded_roots: Vec<AbsolutePathBuf>,    pub errors: Vec<MarketplaceUpgradeErrorInfo>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceUpgradeErrorInfo {    pub marketplace_name: String,    pub message: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginListParams {    /// Optional working directories used to discover repo marketplaces. When omitted,    /// only home-scoped marketplaces and the official curated marketplace are considered.    #[ts(optional = nullable)]    pub cwds: Option<Vec<AbsolutePathBuf>>,    /// Optional marketplace kind filter. When omitted, only local marketplaces are queried, plus    /// the default remote catalog when enabled by feature flag.    #[ts(optional = nullable)]    pub marketplace_kinds: Option<Vec<PluginListMarketplaceKind>>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginInstalledParams {    /// Optional working directories used to discover repo marketplaces.    #[ts(optional = nullable)]    pub cwds: Option<Vec<AbsolutePathBuf>>,    /// Additional uninstalled plugin names that should be returned when present locally.    /// This is used by mention surfaces that intentionally expose install entrypoints.    #[ts(optional = nullable)]    pub install_suggestion_plugin_names: Option<Vec<String>>,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[ts(export_to = "v2/")]pub enum PluginListMarketplaceKind {    #[serde(rename = "local")]    #[ts(rename = "local")]    Local,    #[serde(rename = "vertical")]    #[ts(rename = "vertical")]    Vertical,    #[serde(rename = "workspace-directory")]    #[ts(rename = "workspace-directory")]    WorkspaceDirectory,    #[serde(rename = "shared-with-me")]    #[ts(rename = "shared-with-me")]    SharedWithMe,    #[serde(rename = "created-by-me-remote")]    #[ts(rename = "created-by-me-remote")]    CreatedByMeRemote,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginListResponse {    pub marketplaces: Vec<PluginMarketplaceEntry>,    #[serde(default)]    pub marketplace_load_errors: Vec<MarketplaceLoadErrorInfo>,    #[serde(default)]    pub featured_plugin_ids: Vec<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginInstalledResponse {    pub marketplaces: Vec<PluginMarketplaceEntry>,    #[serde(default)]    pub marketplace_load_errors: Vec<MarketplaceLoadErrorInfo>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceLoadErrorInfo {    pub marketplace_path: AbsolutePathBuf,    pub message: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginReadParams {    #[ts(optional = nullable)]    pub marketplace_path: Option<AbsolutePathBuf>,    #[ts(optional = nullable)]    pub remote_marketplace_name: Option<String>,    pub plugin_name: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginReadResponse {    pub plugin: PluginDetail,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginSkillReadParams {    pub remote_marketplace_name: String,    pub remote_plugin_id: String,    pub skill_name: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginSkillReadResponse {    pub contents: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareSaveParams {    pub plugin_path: AbsolutePathBuf,    #[ts(optional = nullable)]    pub remote_plugin_id: Option<String>,    #[ts(optional = nullable)]    pub discoverability: Option<PluginShareDiscoverability>,    #[ts(optional = nullable)]    pub share_targets: Option<Vec<PluginShareTarget>>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareSaveResponse {    pub remote_plugin_id: String,    pub share_url: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareUpdateTargetsParams {    pub remote_plugin_id: String,    pub discoverability: PluginShareUpdateDiscoverability,    pub share_targets: Vec<PluginShareTarget>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareUpdateTargetsResponse {    pub principals: Vec<PluginSharePrincipal>,    pub discoverability: PluginShareDiscoverability,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareListParams {}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareListResponse {    pub data: Vec<PluginShareListItem>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareCheckoutParams {    pub remote_plugin_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareCheckoutResponse {    pub remote_plugin_id: String,    pub plugin_id: String,    pub plugin_name: String,    pub plugin_path: AbsolutePathBuf,    pub marketplace_name: String,    pub marketplace_path: AbsolutePathBuf,    pub remote_version: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareDeleteParams {    pub remote_plugin_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[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 local_plugin_path: Option<AbsolutePathBuf>,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[ts(export_to = "v2/")]pub enum PluginShareDiscoverability {    #[serde(rename = "LISTED")]    #[ts(rename = "LISTED")]    Listed,    #[serde(rename = "UNLISTED")]    #[ts(rename = "UNLISTED")]    Unlisted,    #[serde(rename = "PRIVATE")]    #[ts(rename = "PRIVATE")]    Private,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[ts(export_to = "v2/")]pub enum PluginShareUpdateDiscoverability {    #[serde(rename = "UNLISTED")]    #[ts(rename = "UNLISTED")]    Unlisted,    #[serde(rename = "PRIVATE")]    #[ts(rename = "PRIVATE")]    Private,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[ts(export_to = "v2/")]pub enum PluginSharePrincipalType {    #[serde(rename = "user")]    #[ts(rename = "user")]    User,    #[serde(rename = "group")]    #[ts(rename = "group")]    Group,    #[serde(rename = "workspace")]    #[ts(rename = "workspace")]    Workspace,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareTarget {    pub principal_type: PluginSharePrincipalType,    pub principal_id: String,    pub role: PluginShareTargetRole,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginSharePrincipal {    pub principal_type: PluginSharePrincipalType,    pub principal_id: String,    pub role: PluginSharePrincipalRole,    pub name: String,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "lowercase")]#[ts(rename_all = "lowercase")]#[ts(export_to = "v2/")]pub enum PluginShareTargetRole {    Reader,    Editor,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "lowercase")]#[ts(rename_all = "lowercase")]#[ts(export_to = "v2/")]pub enum PluginSharePrincipalRole {    Reader,    Editor,    Owner,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "snake_case")]#[ts(rename_all = "snake_case")]#[ts(export_to = "v2/")]pub enum SkillScope {    User,    Repo,    System,    Admin,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillMetadata {    pub name: String,    pub description: String,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    /// Legacy short_description from SKILL.md. Prefer SKILL.json interface.short_description.    pub short_description: Option<String>,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    pub interface: Option<SkillInterface>,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    pub dependencies: Option<SkillDependencies>,    pub path: AbsolutePathBuf,    pub scope: SkillScope,    pub enabled: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillInterface {    #[ts(optional)]    pub display_name: Option<String>,    #[ts(optional)]    pub short_description: Option<String>,    #[ts(optional)]    pub icon_small: Option<AbsolutePathBuf>,    #[ts(optional)]    pub icon_large: Option<AbsolutePathBuf>,    #[ts(optional)]    pub brand_color: Option<String>,    #[ts(optional)]    pub default_prompt: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillDependencies {    pub tools: Vec<SkillToolDependency>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillToolDependency {    #[serde(rename = "type")]    #[ts(rename = "type")]    pub r#type: String,    pub value: String,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    pub description: Option<String>,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    pub transport: Option<String>,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    pub command: Option<String>,    #[serde(default, skip_serializing_if = "Option::is_none")]    #[ts(optional)]    pub url: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillErrorInfo {    pub path: PathBuf,    pub message: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillsListEntry {    pub cwd: PathBuf,    pub skills: Vec<SkillMetadata>,    pub errors: Vec<SkillErrorInfo>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct HooksListEntry {    pub cwd: PathBuf,    pub hooks: Vec<HookMetadata>,    pub warnings: Vec<String>,    pub errors: Vec<HookErrorInfo>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct HookMetadata {    pub key: String,    pub event_name: HookEventName,    pub handler_type: HookHandlerType,    pub matcher: Option<String>,    pub command: Option<String>,    pub timeout_sec: u64,    pub status_message: Option<String>,    pub source_path: AbsolutePathBuf,    pub source: HookSource,    pub plugin_id: Option<String>,    pub display_order: i64,    pub enabled: bool,    pub is_managed: bool,    pub current_hash: String,    pub trust_status: HookTrustStatus,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct HookErrorInfo {    pub path: PathBuf,    pub message: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginMarketplaceEntry {    pub name: String,    /// Local marketplace file path when the marketplace is backed by a local file.    /// Remote-only catalog marketplaces do not have a local path.    pub path: Option<AbsolutePathBuf>,    pub interface: Option<MarketplaceInterface>,    pub plugins: Vec<PluginSummary>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct MarketplaceInterface {    pub display_name: Option<String>,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[ts(export_to = "v2/")]pub enum PluginInstallPolicy {    #[serde(rename = "NOT_AVAILABLE")]    #[ts(rename = "NOT_AVAILABLE")]    NotAvailable,    #[serde(rename = "AVAILABLE")]    #[ts(rename = "AVAILABLE")]    Available,    #[serde(rename = "INSTALLED_BY_DEFAULT")]    #[ts(rename = "INSTALLED_BY_DEFAULT")]    InstalledByDefault,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]#[ts(export_to = "v2/")]pub enum PluginAuthPolicy {    #[serde(rename = "ON_INSTALL")]    #[ts(rename = "ON_INSTALL")]    OnInstall,    #[serde(rename = "ON_USE")]    #[ts(rename = "ON_USE")]    OnUse,}#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, JsonSchema, TS)]#[ts(export_to = "v2/")]pub enum PluginAvailability {    /// 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.    #[serde(rename = "AVAILABLE", alias = "ENABLED")]    #[ts(rename = "AVAILABLE")]    #[default]    Available,    #[serde(rename = "DISABLED_BY_ADMIN")]    #[ts(rename = "DISABLED_BY_ADMIN")]    DisabledByAdmin,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginSummary {    pub id: String,    /// Backend remote plugin identifier when available.    pub remote_plugin_id: Option<String>,    /// Version of the locally materialized plugin package when available.    #[serde(default)]    pub local_version: Option<String>,    pub name: String,    /// Remote sharing context associated with this plugin when available.    pub share_context: Option<PluginShareContext>,    pub source: PluginSource,    pub installed: bool,    pub enabled: bool,    pub install_policy: PluginInstallPolicy,    pub auth_policy: PluginAuthPolicy,    /// Availability state for installing and using the plugin.    #[serde(default)]    pub availability: PluginAvailability,    pub interface: Option<PluginInterface>,    #[serde(default)]    pub keywords: Vec<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginShareContext {    pub remote_plugin_id: String,    /// Version of the remote shared plugin release when available.    #[serde(default)]    pub remote_version: Option<String>,    pub discoverability: Option<PluginShareDiscoverability>,    pub share_url: Option<String>,    pub creator_account_user_id: Option<String>,    pub creator_name: Option<String>,    pub share_principals: Option<Vec<PluginSharePrincipal>>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginDetail {    pub marketplace_name: String,    pub marketplace_path: Option<AbsolutePathBuf>,    pub summary: PluginSummary,    pub share_url: Option<String>,    pub description: Option<String>,    pub skills: Vec<SkillSummary>,    pub hooks: Vec<PluginHookSummary>,    pub apps: Vec<AppSummary>,    pub app_templates: Vec<AppTemplateSummary>,    pub mcp_servers: Vec<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]#[serde(rename_all = "SCREAMING_SNAKE_CASE")]#[ts(export_to = "v2/")]pub enum AppTemplateUnavailableReason {    NotConfiguredForWorkspace,    NoActiveWorkspace,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct AppTemplateSummary {    pub template_id: String,    pub name: String,    pub description: Option<String>,    pub category: Option<String>,    pub canonical_connector_id: Option<String>,    pub logo_url: Option<String>,    pub logo_url_dark: Option<String>,    pub materialized_app_ids: Vec<String>,    pub reason: Option<AppTemplateUnavailableReason>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginHookSummary {    pub key: String,    pub event_name: HookEventName,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillSummary {    pub name: String,    pub description: String,    pub short_description: Option<String>,    pub interface: Option<SkillInterface>,    pub path: Option<AbsolutePathBuf>,    pub enabled: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginInterface {    pub display_name: Option<String>,    pub short_description: Option<String>,    pub long_description: Option<String>,    pub developer_name: Option<String>,    pub category: Option<String>,    pub capabilities: Vec<String>,    pub website_url: Option<String>,    pub privacy_policy_url: Option<String>,    pub terms_of_service_url: Option<String>,    /// Starter prompts for the plugin. Capped at 3 entries with a maximum of    /// 128 characters per entry.    pub default_prompt: Option<Vec<String>>,    pub brand_color: Option<String>,    /// Local composer icon path, resolved from the installed plugin package.    pub composer_icon: Option<AbsolutePathBuf>,    /// Remote composer icon URL from the plugin catalog.    pub composer_icon_url: Option<String>,    /// Local logo path, resolved from the installed plugin package.    pub logo: Option<AbsolutePathBuf>,    /// Remote logo URL from the plugin catalog.    pub logo_url: Option<String>,    /// Local screenshot paths, resolved from the installed plugin package.    pub screenshots: Vec<AbsolutePathBuf>,    /// Remote screenshot URLs from the plugin catalog.    pub screenshot_urls: Vec<String>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(tag = "type", rename_all = "camelCase")]#[ts(tag = "type")]#[ts(export_to = "v2/")]pub enum PluginSource {    #[serde(rename_all = "camelCase")]    #[ts(rename_all = "camelCase")]    Local { path: AbsolutePathBuf },    #[serde(rename_all = "camelCase")]    #[ts(rename_all = "camelCase")]    Git {        url: String,        path: Option<String>,        ref_name: Option<String>,        sha: Option<String>,    },    /// The plugin is available in the remote catalog. Download metadata is    /// kept server-side and is not exposed through the app-server API.    Remote,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillsConfigWriteParams {    /// Path-based selector.    #[ts(optional = nullable)]    pub path: Option<AbsolutePathBuf>,    /// Name-based selector.    #[ts(optional = nullable)]    pub name: Option<String>,    pub enabled: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct SkillsConfigWriteResponse {    pub effective_enabled: bool,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginInstallParams {    #[ts(optional = nullable)]    pub marketplace_path: Option<AbsolutePathBuf>,    #[ts(optional = nullable)]    pub remote_marketplace_name: Option<String>,    pub plugin_name: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginInstallResponse {    pub auth_policy: PluginAuthPolicy,    pub apps_needing_auth: Vec<AppSummary>,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginUninstallParams {    pub plugin_id: String,}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]pub struct PluginUninstallResponse {}impl From<CoreSkillMetadata> for SkillMetadata {    fn from(value: CoreSkillMetadata) -> Self {        Self {            name: value.name,            description: value.description,            short_description: value.short_description,            interface: value.interface.map(SkillInterface::from),            dependencies: value.dependencies.map(SkillDependencies::from),            path: value.path,            scope: value.scope.into(),            enabled: true,        }    }}impl From<CoreSkillInterface> for SkillInterface {    fn from(value: CoreSkillInterface) -> Self {        Self {            display_name: value.display_name,            short_description: value.short_description,            brand_color: value.brand_color,            default_prompt: value.default_prompt,            icon_small: value.icon_small,            icon_large: value.icon_large,        }    }}impl From<CoreSkillDependencies> for SkillDependencies {    fn from(value: CoreSkillDependencies) -> Self {        Self {            tools: value                .tools                .into_iter()                .map(SkillToolDependency::from)                .collect(),        }    }}impl From<CoreSkillToolDependency> for SkillToolDependency {    fn from(value: CoreSkillToolDependency) -> Self {        Self {            r#type: value.r#type,            value: value.value,            description: value.description,            transport: value.transport,            command: value.command,            url: value.url,        }    }}impl From<CoreSkillScope> for SkillScope {    fn from(value: CoreSkillScope) -> Self {        match value {            CoreSkillScope::User => Self::User,            CoreSkillScope::Repo => Self::Repo,            CoreSkillScope::System => Self::System,            CoreSkillScope::Admin => Self::Admin,        }    }}#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]#[serde(rename_all = "camelCase")]#[ts(export_to = "v2/")]/// Notification emitted when watched local skill files change.////// Treat this as an invalidation signal and re-run `skills/list` with the/// client's current parameters when refreshed skill metadata is needed.pub struct SkillsChangedNotification {}