feat(plugins): add AI tools and consent-gated data access
This commit is contained in:
71 files changed
+4613
-129
No files matched your search
@@ -53,6 +53,15 @@ impl PluginConnectionHandle {
|
||||
self.session.as_ref().is_none_or(|session| session.status().state == PluginSessionState::Running)
|
||||
}
|
||||
|
||||
/// The lifecycle payload this connection was opened with: provider,
|
||||
/// hydrated connection, and the runtime endpoint *after* DBX transport
|
||||
/// layers. Host-initiated calls that act on an open connection (for
|
||||
/// example plugin MCP tools) must reuse it instead of rebuilding a payload
|
||||
/// from the saved config, which would bypass the tunnel.
|
||||
pub fn lifecycle_params(&self) -> &serde_json::Value {
|
||||
&self.params
|
||||
}
|
||||
|
||||
pub async fn disconnect(&self) -> Result<(), String> {
|
||||
let Some(session) = &self.session else {
|
||||
return Ok(());
|
||||
|
||||
@@ -13,10 +13,12 @@ pub const SUPPORTED_PLUGIN_MANIFEST_VERSION: u32 = 1;
|
||||
/// 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";
|
||||
/// ungated `host.copy`). 1.4 adds consent-gated read-only data queries
|
||||
/// (`host.queryData` behind `host.data:read`). 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.4.0";
|
||||
/// Capabilities the host advertises to a plugin backend at `plugin/initialize`.
|
||||
pub const SUPPORTED_PLUGIN_HOST_FEATURES: &[&str] = &["host.requestUserInput"];
|
||||
pub const SUPPORTED_PLUGIN_PROTOCOL_VERSION: u32 = 1;
|
||||
@@ -34,6 +36,7 @@ pub const SUPPORTED_PLUGIN_PERMISSIONS: &[&str] = &[
|
||||
"host.storage",
|
||||
"host.ai",
|
||||
"host.clipboard:read",
|
||||
"host.data:read",
|
||||
];
|
||||
|
||||
/// Cap the number of `host.network:<origin>` entries so a manifest cannot bloat
|
||||
@@ -2240,27 +2243,27 @@ mod tests {
|
||||
assert_eq!(declared, SUPPORTED_PLUGIN_PERMISSIONS.iter().map(|value| value.to_string()).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
/// The reason for the 1.3.0 bump: `engines.host_api` is how a plugin states
|
||||
/// "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.
|
||||
/// `engines.host_api` is how a plugin states "I need the schema metadata
|
||||
/// API" / "I need clipboard reads" (1.3) or "I need data queries" (1.4), so
|
||||
/// the advertised version has to satisfy each floor 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)
|
||||
.expect("the advertised Host API version must be semver");
|
||||
assert!(
|
||||
semver::VersionReq::parse("^1.3").unwrap().matches(&advertised),
|
||||
"the host must satisfy the schema metadata API floor it asks plugins to declare"
|
||||
"the host must satisfy the schema metadata and clipboard-read 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"
|
||||
semver::VersionReq::parse("^1.4").unwrap().matches(&advertised),
|
||||
"the host must satisfy the data-query floor it asks plugins to declare"
|
||||
);
|
||||
|
||||
for requirement in ["^1.0", "^1.1", "^1.2", "^1.3", ">=1.1.0, <2.0.0"] {
|
||||
for requirement in ["^1.0", "^1.1", "^1.2", "^1.3", "^1.4", ">=1.1.0, <2.0.0"] {
|
||||
assert!(host_api_requirement_errors(requirement).is_empty(), "{requirement} must be satisfiable");
|
||||
}
|
||||
for requirement in [">=1.4.0", "^2.0"] {
|
||||
for requirement in [">=1.5.0", "^2.0"] {
|
||||
assert!(!host_api_requirement_errors(requirement).is_empty(), "{requirement} must be rejected");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user