feat(plugins): bridge clipboard reads with consent gate

This commit is contained in:
Jinpy authored and GitHub committed 2026-09-24 16:16:49 +08:00
1 parent 1335ec032c
commit 92f92f6cdb
18 files changed
+424 -12

No files matched your search

@@ -10,10 +10,12 @@ pub const SUPPORTED_PLUGIN_MANIFEST_VERSION: u32 = 1;
/// 1.1 adds the plugin-initiated `host/requestUserInput` method (see
/// `plugins/runtime.rs`). 1.2 adds the plugin-initiated plan Host API
/// (`host.getPlanCapabilities` / `host.explainPlan`). 1.3 adds read-only table
/// schema metadata (`host.getTableMetadata`). All are additive: older plugins
/// keep working, and a plugin that wants either capability must check the
/// advertised version (or the matching `capabilities` / `host.features`
/// entry) before calling it.
/// schema metadata (`host.getTableMetadata` behind `host.schema:read`) and the
/// plugin-initiated clipboard Host API (`host.clipboardRead` behind the
/// `host.clipboard:read` permission; clipboard writes reuse the existing
/// ungated `host.copy`). All are additive: older plugins keep working, and a
/// plugin that wants a capability must check the advertised version (or the
/// matching `capabilities` / `host.features` entry) before calling it.
pub const SUPPORTED_PLUGIN_HOST_API_VERSION: &str = "1.3.0";
/// Capabilities the host advertises to a plugin backend at `plugin/initialize`.
pub const SUPPORTED_PLUGIN_HOST_FEATURES: &[&str] = &["host.requestUserInput"];
@@ -31,6 +33,7 @@ pub const SUPPORTED_PLUGIN_PERMISSIONS: &[&str] = &[
"host.schema:read",
"host.storage",
"host.ai",
"host.clipboard:read",
];
/// Cap the number of `host.network:<origin>` entries so a manifest cannot bloat
@@ -2211,8 +2214,9 @@ mod tests {
}
/// The reason for the 1.3.0 bump: `engines.host_api` is how a plugin states
/// "I need the schema metadata API", so the advertised version has to
/// satisfy `^1.3` while a floor this host cannot meet stays rejected.
/// "I need the schema metadata API" or "I need clipboard reads", so the
/// advertised version has to satisfy `^1.3` while a floor this host cannot
/// meet stays rejected.
#[test]
fn host_api_advertises_the_floor_a_schema_metadata_plugin_declares() {
let advertised = semver::Version::parse(SUPPORTED_PLUGIN_HOST_API_VERSION)
@@ -2221,6 +2225,10 @@ mod tests {
semver::VersionReq::parse("^1.3").unwrap().matches(&advertised),
"the host must satisfy the schema metadata API floor it asks plugins to declare"
);
assert!(
semver::VersionReq::parse("^1.3").unwrap().matches(&advertised),
"the host must satisfy the clipboard-read floor it asks plugins to declare"
);
for requirement in ["^1.0", "^1.1", "^1.2", "^1.3", ">=1.1.0, <2.0.0"] {
assert!(host_api_requirement_errors(requirement).is_empty(), "{requirement} must be satisfiable");