feat(sdk,plugins): ajoute capability tooling et services runtime publics (workspace/terminal/tasks)
- capability manifeste tooling supportée backend + transport runtime catalog - ctx.services publique côté SDK/runtime, gated par tooling - surface honnête: workspace, terminal, et tasks en observation/contrôle uniquement - docs/exemple/tests mis à jour - QA PASS sur feature/sdk-plugin-tooling-build-debug-surface
This commit is contained in:
@ -146,6 +146,8 @@ pub struct PluginRuntimePlugin {
|
||||
pub icon_url: Option<String>,
|
||||
/// Content hash.
|
||||
pub content_hash: String,
|
||||
/// Public manifest capabilities.
|
||||
pub capabilities: Vec<domain::PluginCapability>,
|
||||
/// Contributions.
|
||||
pub contributes: PluginContributionSet,
|
||||
}
|
||||
@ -824,6 +826,7 @@ async fn runtime_plugin_from_entry(
|
||||
bundle_url: bundle,
|
||||
icon_url,
|
||||
content_hash: descriptor.registry.content_hash.as_str().to_owned(),
|
||||
capabilities: descriptor.manifest.capabilities,
|
||||
contributes: descriptor.manifest.contributes,
|
||||
})
|
||||
}
|
||||
@ -1170,6 +1173,7 @@ impl PluginManifestValidator for JsonPluginManifestValidator {
|
||||
.map(|c| match c.as_str() {
|
||||
"ui" => Ok(domain::PluginCapability::Ui),
|
||||
"mcp" => Ok(domain::PluginCapability::Mcp),
|
||||
"tooling" => Ok(domain::PluginCapability::Tooling),
|
||||
_ => Err(PluginManifestError::Invalid(format!(
|
||||
"unknown capability: {c}"
|
||||
))),
|
||||
@ -1377,7 +1381,7 @@ mod tests {
|
||||
"engines": {"idea": ">=0.1.0 <1.0.0"},
|
||||
"main": "dist/index.js",
|
||||
"trustLevel": "full",
|
||||
"capabilities": ["ui", "mcp"],
|
||||
"capabilities": ["ui", "mcp", "tooling"],
|
||||
"contributes": {
|
||||
"menus": [{"id":"dev.acme.menu","label":"Graph","topLevel":true}],
|
||||
"menuItems": [{"id":"dev.acme.open","targetMenuId":"panels","label":"Open","command":"dev.acme.open"}],
|
||||
@ -1630,10 +1634,39 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(m.id.as_str(), "dev.acme.gitgraph");
|
||||
assert_eq!(
|
||||
m.capabilities,
|
||||
vec![
|
||||
domain::PluginCapability::Ui,
|
||||
domain::PluginCapability::Mcp,
|
||||
domain::PluginCapability::Tooling,
|
||||
]
|
||||
);
|
||||
assert_eq!(m.contributes.layouts.len(), 1);
|
||||
assert_eq!(m.contributes.mcp_servers.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_unknown_manifest_capability() {
|
||||
let mut value: serde_json::Value = serde_json::from_slice(&valid_manifest()).unwrap();
|
||||
value["capabilities"] = serde_json::json!(["ui", "android"]);
|
||||
|
||||
let err = validator()
|
||||
.validate(
|
||||
&serde_json::to_vec(&value).unwrap(),
|
||||
&domain::PluginPackageRef {
|
||||
plugin_id: None,
|
||||
root: "x".into(),
|
||||
},
|
||||
)
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
err,
|
||||
PluginManifestError::Invalid("unknown capability: android".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_unsafe_main_path_and_non_full_trust() {
|
||||
let mut value: serde_json::Value = serde_json::from_slice(&valid_manifest()).unwrap();
|
||||
@ -1695,6 +1728,28 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn runtime_catalog_carries_manifest_capabilities() {
|
||||
let packages = Arc::new(FakePackages::with_manifest(valid_manifest()));
|
||||
let registry = Arc::new(FakeRegistry {
|
||||
registry: Mutex::new(registry_with(PluginLifecycleState::Enabled)),
|
||||
});
|
||||
let usecase =
|
||||
ListPluginRuntimeContributions::new(packages, registry, Arc::new(validator()));
|
||||
|
||||
let catalog = usecase.execute().await.unwrap();
|
||||
|
||||
assert_eq!(catalog.plugins.len(), 1);
|
||||
assert_eq!(
|
||||
catalog.plugins[0].capabilities,
|
||||
vec![
|
||||
domain::PluginCapability::Ui,
|
||||
domain::PluginCapability::Mcp,
|
||||
domain::PluginCapability::Tooling,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn runtime_catalog_marks_invalid_active_plugin_and_keeps_bootstrap_alive() {
|
||||
let packages = Arc::new(FakePackages::with_manifest(br#"{"broken":true}"#.to_vec()));
|
||||
|
||||
Reference in New Issue
Block a user