From 14f3eb901c051dafeaf034f93f46b2d1bb40489f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Dec 2025 01:05:19 +0000 Subject: [PATCH] feat: Add Claude Code v2.0.55+ feature integrations New commands for latest Claude Code features: - `lsp-diagnostic` - Process LSP diagnostic events, learn from errors - `suggest-ultrathink` - Recommend ultrathink mode for complex tasks - `async-agent` - Coordinate async sub-agent spawn/sync/complete Hook integrations: - PostToolUse LSP matcher for diagnostics - PreToolUse Task matcher spawns async agents - PostToolUse Task matcher tracks agent completion Ultrathink detection patterns: - algorithm, optimize, refactor, debug, performance - concurrent, async, architecture, security - cryptograph, distributed, consensus, neural, ml --- crates/ruvector-cli/src/cli/hooks.rs | 239 +++++++++++++++++++++++++++ crates/ruvector-cli/src/main.rs | 10 ++ 2 files changed, 249 insertions(+) diff --git a/crates/ruvector-cli/src/cli/hooks.rs b/crates/ruvector-cli/src/cli/hooks.rs index 5cc9ef06..44f7ab83 100644 --- a/crates/ruvector-cli/src/cli/hooks.rs +++ b/crates/ruvector-cli/src/cli/hooks.rs @@ -270,6 +270,47 @@ pub enum HooksCommands { notification_type: Option, }, + // === Claude Code v2.0.55+ Features === + /// Process LSP diagnostic events (requires Claude Code 2.0.55+) + LspDiagnostic { + /// File with diagnostic + #[arg(long)] + file: Option, + + /// Diagnostic severity (error, warning, info, hint) + #[arg(long)] + severity: Option, + + /// Diagnostic message + #[arg(long)] + message: Option, + }, + + /// Recommend ultrathink mode for complex tasks + SuggestUltrathink { + /// Task description + task: Vec, + + /// File being worked on + #[arg(long)] + file: Option, + }, + + /// Coordinate async sub-agent execution + AsyncAgent { + /// Agent action (spawn, sync, complete) + #[arg(long, default_value = "spawn")] + action: String, + + /// Agent ID + #[arg(long)] + agent_id: Option, + + /// Task description + #[arg(long)] + task: Option, + }, + // === V3 Intelligence Features === /// Record error pattern for learning RecordError { @@ -1130,6 +1171,11 @@ pub fn init_hooks(force: bool, postgres: bool, _config: &Config) -> Result<()> { "type": "command", "command": "ruvector hooks swarm-recommend \"$TOOL_INPUT_SUBAGENT_TYPE\"", "timeout": 2000 + }, { + // Claude Code v2.0.55+: Register async sub-agent + "type": "command", + "command": "ruvector hooks async-agent --action spawn --agent-id \"$TOOL_INPUT_SUBAGENT_TYPE\" --task \"$TOOL_INPUT_PROMPT\"", + "timeout": 1000 }] }], // Post-tool hooks: record outcomes for learning @@ -1147,6 +1193,22 @@ pub fn init_hooks(force: bool, postgres: bool, _config: &Config) -> Result<()> { "command": "ruvector hooks post-command \"$TOOL_INPUT_COMMAND\" --success=$TOOL_STATUS", "timeout": 3000 }] + }, { + // Claude Code v2.0.55+: LSP diagnostics integration + "matcher": "LSP", + "hooks": [{ + "type": "command", + "command": "ruvector hooks lsp-diagnostic --file \"$TOOL_INPUT_FILE\" --severity \"$TOOL_INPUT_SEVERITY\" --message \"$TOOL_INPUT_MESSAGE\"", + "timeout": 2000 + }] + }, { + // Claude Code v2.0.55+: Async sub-agent completion tracking + "matcher": "Task", + "hooks": [{ + "type": "command", + "command": "ruvector hooks async-agent --action complete --agent-id \"$TOOL_INPUT_SUBAGENT_TYPE\"", + "timeout": 2000 + }] }], // Session lifecycle hooks "SessionStart": [{ @@ -1793,6 +1855,183 @@ pub fn swarm_stats_cmd(_config: &Config) -> Result<()> { Ok(()) } +// === Claude Code v2.0.55+ Feature Commands === + +/// Process LSP diagnostic events +pub fn lsp_diagnostic_cmd( + file: Option<&str>, + severity: Option<&str>, + message: Option<&str>, + _config: &Config, +) -> Result<()> { + let mut intel = Intelligence::new(get_intelligence_path()); + + // Parse stdin for full diagnostic info + let stdin_input = try_parse_stdin(); + + let file = file + .or_else(|| stdin_input.as_ref().and_then(|i| i.tool_input.as_ref() + .and_then(|t| t.get("file").and_then(|f| f.as_str())))) + .unwrap_or("unknown"); + + let severity = severity.unwrap_or("error"); + let message = message.unwrap_or(""); + + // Learn from diagnostic patterns + let state = format!("lsp:{}:{}", severity, file.split('/').last().unwrap_or(file)); + intel.learn(&state, "diagnostic", severity, if severity == "error" { -0.5 } else { 0.0 }); + intel.save()?; + + // Output JSON for context injection + if severity == "error" { + let output = HookOutput { + hook_specific_output: Some(HookSpecificOutput { + additional_context: Some(format!( + "LSP reports {} in {}: {}. Consider fixing before proceeding.", + severity, file, message + )), + ..Default::default() + }), + ..Default::default() + }; + println!("{}", serde_json::to_string(&output)?); + } + + Ok(()) +} + +/// Recommend ultrathink mode for complex tasks +pub fn suggest_ultrathink_cmd(task: &str, file: Option<&str>, _config: &Config) -> Result<()> { + let intel = Intelligence::new(get_intelligence_path()); + + // Complexity indicators that suggest ultrathink + let complexity_patterns = [ + ("algorithm", 0.8), + ("optimize", 0.7), + ("refactor", 0.6), + ("debug", 0.7), + ("performance", 0.7), + ("concurrent", 0.8), + ("async", 0.6), + ("architecture", 0.8), + ("security", 0.7), + ("cryptograph", 0.9), + ("distributed", 0.8), + ("consensus", 0.9), + ("neural", 0.8), + ("ml", 0.7), + ("complex", 0.6), + ]; + + let task_lower = task.to_lowercase(); + let mut complexity_score = 0.0; + let mut matched_patterns = Vec::new(); + + for (pattern, weight) in complexity_patterns { + if task_lower.contains(pattern) { + complexity_score += weight; + matched_patterns.push(pattern); + } + } + + // Check file extension for inherent complexity + if let Some(f) = file { + if f.ends_with(".rs") || f.ends_with(".cpp") || f.ends_with(".go") { + complexity_score += 0.2; + } + } + + // Check learned patterns + let state = format!("task:{}", task_lower.split_whitespace().next().unwrap_or("unknown")); + let (_, q_value) = intel.suggest(&state, &["ultrathink".to_string(), "normal".to_string()]); + if q_value > 0.5 { + complexity_score += 0.3; + } + + let recommend_ultrathink = complexity_score >= 0.6; + + println!("{}", serde_json::to_string_pretty(&serde_json::json!({ + "task": task, + "complexity_score": complexity_score, + "recommend_ultrathink": recommend_ultrathink, + "matched_patterns": matched_patterns, + "suggestion": if recommend_ultrathink { + "Consider using 'ultrathink' for this complex task" + } else { + "Standard reasoning should suffice" + } + }))?); + + Ok(()) +} + +/// Coordinate async sub-agent execution +pub fn async_agent_cmd( + action: &str, + agent_id: Option<&str>, + task: Option<&str>, + _config: &Config, +) -> Result<()> { + let mut intel = Intelligence::new(get_intelligence_path()); + + match action { + "spawn" => { + let default_id = format!("async-{}", std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis()); + let agent_id = agent_id.unwrap_or(&default_id); + let task = task.unwrap_or("unknown"); + + // Register async agent + intel.swarm_register(agent_id, "async-subagent", vec!["parallel".to_string()]); + intel.learn(&format!("async:{}", agent_id), "spawned", "active", 0.0); + intel.save()?; + + println!("{}", serde_json::to_string_pretty(&serde_json::json!({ + "action": "spawn", + "agent_id": agent_id, + "task": task, + "status": "spawned", + "coordination": "async" + }))?); + } + "sync" => { + // Record coordination between async agents + if let Some(id) = agent_id { + intel.learn(&format!("async:{}", id), "sync", "waiting", 0.1); + intel.save()?; + + println!("{}", serde_json::to_string_pretty(&serde_json::json!({ + "action": "sync", + "agent_id": id, + "status": "synchronizing" + }))?); + } + } + "complete" => { + if let Some(id) = agent_id { + intel.learn(&format!("async:{}", id), "complete", "finished", 1.0); + intel.save()?; + + println!("{}", serde_json::to_string_pretty(&serde_json::json!({ + "action": "complete", + "agent_id": id, + "status": "completed", + "reward": 1.0 + }))?); + } + } + _ => { + println!("{}", serde_json::json!({ + "error": format!("Unknown action: {}. Use spawn, sync, or complete.", action) + })); + } + } + + Ok(()) +} + // === Optimization Commands === /// Generate shell completions diff --git a/crates/ruvector-cli/src/main.rs b/crates/ruvector-cli/src/main.rs index 9261b9a0..2c9f0fc1 100644 --- a/crates/ruvector-cli/src/main.rs +++ b/crates/ruvector-cli/src/main.rs @@ -288,6 +288,16 @@ async fn main() -> Result<()> { HooksCommands::TrackNotification { notification_type } => { cli::hooks::track_notification_cmd(notification_type.as_deref(), &config) } + // Claude Code v2.0.55+ features + HooksCommands::LspDiagnostic { file, severity, message } => { + cli::hooks::lsp_diagnostic_cmd(file.as_deref(), severity.as_deref(), message.as_deref(), &config) + } + HooksCommands::SuggestUltrathink { task, file } => { + cli::hooks::suggest_ultrathink_cmd(&task.join(" "), file.as_deref(), &config) + } + HooksCommands::AsyncAgent { action, agent_id, task } => { + cli::hooks::async_agent_cmd(&action, agent_id.as_deref(), task.as_deref(), &config) + } HooksCommands::RecordError { command, stderr } => { cli::hooks::record_error_cmd(&command, &stderr, &config) }