mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-12 19:14:51 +08:00
feat(commands): surface broken plugin warnings in /plugins list
Implements ROADMAP #40: Show warnings for broken/missing plugin manifests instead of silently failing. - Add PluginLoadFailure import - New render_plugins_report_with_failures() function - Shows ⚠️ warnings for failed plugin loads with error details - Updates ROADMAP.md to mark #40 in progress Ultraclaw droid session: ultraclaw-03-broken-plugins
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -5,3 +5,7 @@ archive/
|
|||||||
# Claude Code local artifacts
|
# Claude Code local artifacts
|
||||||
.claude/settings.local.json
|
.claude/settings.local.json
|
||||||
.claude/sessions/
|
.claude/sessions/
|
||||||
|
# Claw Code local artifacts
|
||||||
|
.claw/settings.local.json
|
||||||
|
.claw/sessions/
|
||||||
|
status-help.txt
|
||||||
|
|||||||
75
ROADMAP.md
75
ROADMAP.md
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@ use std::fmt;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use plugins::{PluginError, PluginManager, PluginSummary};
|
use plugins::{PluginError, PluginLoadFailure, PluginManager, PluginSummary};
|
||||||
use runtime::{
|
use runtime::{
|
||||||
compact_session, CompactionConfig, ConfigLoader, ConfigSource, McpOAuthConfig, McpServerConfig,
|
compact_session, CompactionConfig, ConfigLoader, ConfigSource, McpOAuthConfig, McpServerConfig,
|
||||||
ScopedMcpServerConfig, Session,
|
ScopedMcpServerConfig, Session,
|
||||||
@@ -2210,10 +2210,15 @@ pub fn handle_plugins_slash_command(
|
|||||||
manager: &mut PluginManager,
|
manager: &mut PluginManager,
|
||||||
) -> Result<PluginsCommandResult, PluginError> {
|
) -> Result<PluginsCommandResult, PluginError> {
|
||||||
match action {
|
match action {
|
||||||
None | Some("list") => Ok(PluginsCommandResult {
|
None | Some("list") => {
|
||||||
message: render_plugins_report(&manager.list_installed_plugins()?),
|
let report = manager.installed_plugin_registry_report()?;
|
||||||
|
let plugins = report.summaries();
|
||||||
|
let failures = report.failures();
|
||||||
|
Ok(PluginsCommandResult {
|
||||||
|
message: render_plugins_report_with_failures(&plugins, failures),
|
||||||
reload_runtime: false,
|
reload_runtime: false,
|
||||||
}),
|
})
|
||||||
|
}
|
||||||
Some("install") => {
|
Some("install") => {
|
||||||
let Some(target) = target else {
|
let Some(target) = target else {
|
||||||
return Ok(PluginsCommandResult {
|
return Ok(PluginsCommandResult {
|
||||||
@@ -2667,6 +2672,48 @@ pub fn render_plugins_report(plugins: &[PluginSummary]) -> String {
|
|||||||
lines.join("\n")
|
lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn render_plugins_report_with_failures(
|
||||||
|
plugins: &[PluginSummary],
|
||||||
|
failures: &[PluginLoadFailure],
|
||||||
|
) -> String {
|
||||||
|
let mut lines = vec!["Plugins".to_string()];
|
||||||
|
|
||||||
|
// Show successfully loaded plugins
|
||||||
|
if plugins.is_empty() {
|
||||||
|
lines.push(" No plugins installed.".to_string());
|
||||||
|
} else {
|
||||||
|
for plugin in plugins {
|
||||||
|
let enabled = if plugin.enabled {
|
||||||
|
"enabled"
|
||||||
|
} else {
|
||||||
|
"disabled"
|
||||||
|
};
|
||||||
|
lines.push(format!(
|
||||||
|
" {name:<20} v{version:<10} {enabled}",
|
||||||
|
name = plugin.metadata.name,
|
||||||
|
version = plugin.metadata.version,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show warnings for broken plugins
|
||||||
|
if !failures.is_empty() {
|
||||||
|
lines.push("".to_string());
|
||||||
|
lines.push("Warnings:".to_string());
|
||||||
|
for failure in failures {
|
||||||
|
lines.push(format!(
|
||||||
|
" ⚠️ Failed to load {} plugin from `{}`",
|
||||||
|
failure.kind,
|
||||||
|
failure.plugin_root.display()
|
||||||
|
));
|
||||||
|
lines.push(format!(" Error: {}", failure.error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
fn render_plugin_install_report(plugin_id: &str, plugin: Option<&PluginSummary>) -> String {
|
fn render_plugin_install_report(plugin_id: &str, plugin: Option<&PluginSummary>) -> String {
|
||||||
let name = plugin.map_or(plugin_id, |plugin| plugin.metadata.name.as_str());
|
let name = plugin.map_or(plugin_id, |plugin| plugin.metadata.name.as_str());
|
||||||
let version = plugin.map_or("unknown", |plugin| plugin.metadata.version.as_str());
|
let version = plugin.map_or("unknown", |plugin| plugin.metadata.version.as_str());
|
||||||
|
|||||||
Reference in New Issue
Block a user