diff --git a/.gitignore b/.gitignore index 2d3fa54..7b9a99c 100644 --- a/.gitignore +++ b/.gitignore @@ -186,3 +186,4 @@ idd-state.graphson todo.md *.spec.md journal.md +.aider* diff --git a/Cargo.lock b/Cargo.lock index e48268f..8f8ce98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1334,6 +1334,7 @@ dependencies = [ "indicatif 0.18.3", "libc", "memmap2", + "mimalloc", "notify", "num_cpus", "once_cell", @@ -1349,7 +1350,6 @@ dependencies = [ "sha2", "tempfile", "thiserror 2.0.17", - "tikv-jemallocator", "tokio", "tokio-test", "toml", @@ -4070,6 +4070,16 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libmimalloc-sys" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libredox" version = "0.1.11" @@ -4374,6 +4384,15 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "mimalloc" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8" +dependencies = [ + "libmimalloc-sys", +] + [[package]] name = "mime" version = "0.3.17" @@ -7626,26 +7645,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "tikv-jemalloc-sys" -version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a" -dependencies = [ - "libc", - "tikv-jemalloc-sys", -] - [[package]] name = "time" version = "0.3.44" diff --git a/Cargo.toml b/Cargo.toml index 99bb639..19567d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -240,8 +240,7 @@ rustc-hash = "2.1.1" bytes = "1.6" # Memory allocator + profiling -tikv-jemallocator = { version = "0.6.0", default-features = true } -tikv-jemalloc-ctl = "0.6.0" +mimalloc = "0.1.48" backtrace = "0.3" # Configuration diff --git a/crates/codegraph-core/Cargo.toml b/crates/codegraph-core/Cargo.toml index 4a0e939..c11df3d 100644 --- a/crates/codegraph-core/Cargo.toml +++ b/crates/codegraph-core/Cargo.toml @@ -36,7 +36,7 @@ clap = { workspace = true } colored = { workspace = true } indicatif = { workspace = true } once_cell = { workspace = true } -tikv-jemallocator = { workspace = true } +mimalloc = { workspace = true } hashbrown = { workspace = true } rustc-hash = { workspace = true } sha2 = { workspace = true } @@ -52,10 +52,10 @@ bytes = { workspace = true } bumpalo = "3.15" rkyv = { workspace = true } -[target.'cfg(unix)'.dependencies] +[target.'cfg(target_family = "unix")'.dependencies] libc = "0.2" -[target.'cfg(windows)'.dependencies] +[target.'cfg(target_family = "windows")'.dependencies] windows-sys = { version = "0.61", features = [ "Win32_Foundation", "Win32_System_Memory" @@ -71,6 +71,5 @@ name = "core_micro" harness = false [features] -# Enable jemalloc as the global allocator and expose jemalloc controls -default = ["jemalloc"] -jemalloc = [] +default = ["mimalloc"] +mimalloc = [] diff --git a/crates/codegraph-core/src/lib.rs b/crates/codegraph-core/src/lib.rs index ca416a4..93c2e53 100644 --- a/crates/codegraph-core/src/lib.rs +++ b/crates/codegraph-core/src/lib.rs @@ -51,7 +51,7 @@ pub use types::*; pub use versioning::*; pub use watch::*; -// Use jemalloc as the global allocator when the feature is enabled -#[cfg(feature = "jemalloc")] +// Use mimalloc as the global allocator when the feature is enabled +#[cfg(feature = "mimalloc")] #[global_allocator] -static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; diff --git a/crates/codegraph-mcp-autoagents/src/autoagents/agent_builder.rs b/crates/codegraph-mcp-autoagents/src/autoagents/agent_builder.rs index 3834139..c2adae9 100644 --- a/crates/codegraph-mcp-autoagents/src/autoagents/agent_builder.rs +++ b/crates/codegraph-mcp-autoagents/src/autoagents/agent_builder.rs @@ -1,4 +1,4 @@ -// ABOUTME: Factory for creating AutoAgents with CodeGraph-specific configuration +// ABOUTME: Factory for creating AutoAgents with CodeGraph-specific configuration // ABOUTME: Bridges codegraph_ai LLM providers to AutoAgents ChatProvider // ABOUTME: Builder for tier-aware CodeGraph agents with graph analysis tools @@ -6,7 +6,9 @@ use async_trait::async_trait; #[cfg(test)] use autoagents::llm::chat::ChatMessageBuilder; use autoagents::llm::chat::ChatProvider; -use autoagents::llm::chat::{ChatMessage, ChatResponse, ChatRole, MessageType, Tool}; +use autoagents::llm::chat::{ + ChatMessage, ChatResponse, ChatRole, MessageType, StructuredOutputFormat, Tool, +}; use autoagents::llm::completion::{CompletionProvider, CompletionRequest, CompletionResponse}; use autoagents::llm::embedding::EmbeddingProvider; use autoagents::llm::error::LLMError; @@ -51,6 +53,7 @@ pub(crate) fn read_memory_window_config() -> usize { } use crate::autoagents::progress_notifier::ProgressCallback; +use codegraph_mcp_core::context_aware_limits::ContextTier; /// Adapter that bridges codegraph_ai::LLMProvider to AutoAgents ChatProvider pub struct CodeGraphChatAdapter { @@ -156,20 +159,18 @@ impl CodeGraphChatAdapter { Some(tokens) } -} -#[async_trait] -impl ChatProvider for CodeGraphChatAdapter { - async fn chat( + /// Internal helper that does the actual chat call, with optional structured output + async fn chat_internal( &self, messages: &[ChatMessage], tools: Option<&[Tool]>, - json_schema: Option, + json_schema: Option, ) -> Result, LLMError> { // Log tool and message info let tool_count = tools.map_or(0, |t| t.len()); tracing::info!( - "📨 chat() called with {} messages, {} tools", + "📨 chat_internal() called with {} messages, {} tools", messages.len(), tool_count ); @@ -347,12 +348,33 @@ impl ChatProvider for CodeGraphChatAdapter { step_counter: Arc::new(AtomicU64::new(1)), })) } +} + +#[async_trait] +impl ChatProvider for CodeGraphChatAdapter { + async fn chat( + &self, + messages: &[ChatMessage], + json_schema: Option, + ) -> Result, LLMError> { + // Plain chat: no structured output schema + self.chat_internal(messages, None, json_schema).await + } + + async fn chat_with_tools( + &self, + messages: &[ChatMessage], + tools: Option<&[Tool]>, + json_schema: Option, + ) -> Result, LLMError> { + // Full-featured chat: tools + optional structured output + self.chat_internal(messages, tools, json_schema).await + } async fn chat_stream( &self, _messages: &[ChatMessage], - _tools: Option<&[Tool]>, - _json_schema: Option, + _json_schema: Option, ) -> Result< std::pin::Pin> + Send>>, LLMError, @@ -364,7 +386,7 @@ impl ChatProvider for CodeGraphChatAdapter { &self, _messages: &[ChatMessage], _tools: Option<&[Tool]>, - _json_schema: Option, + _json_schema: Option, ) -> Result< std::pin::Pin< Box< @@ -385,7 +407,7 @@ impl CompletionProvider for CodeGraphChatAdapter { async fn complete( &self, _req: &CompletionRequest, - _json_schema: Option, + _json_schema: Option, ) -> Result { Err(LLMError::Generic( "Completion not supported - use ChatProvider instead".to_string(), @@ -626,6 +648,12 @@ impl ChatResponse for CodeGraphChatResponse { // Tier-Aware ReAct Agent Wrapper // ============================================================================ +use autoagents::core::agent::prebuilt::executor::ReActAgent; +use autoagents::core::agent::{ + AgentDeriveT, AgentExecutor, AgentHooks, Context, DirectAgentHandle, ExecutorConfig, +}; +use autoagents::core::tool::{shared_tools_to_boxes, ToolT}; + /// Wrapper around ReActAgent that overrides max_turns configuration /// This allows tier-aware max_turns without forking AutoAgents #[derive(Debug)] @@ -649,11 +677,11 @@ impl TierAwareReActAgent { impl AgentDeriveT for TierAwareReActAgent { type Output = T::Output; - fn description(&self) -> &'static str { + fn description(&self) -> &str { self.inner_derive.description() } - fn name(&self) -> &'static str { + fn name(&self) -> &str { self.inner_derive.name() } @@ -717,18 +745,12 @@ use crate::autoagents::tier_plugin::TierAwarePromptPlugin; use crate::autoagents::tools::graph_tools::*; use crate::autoagents::tools::tool_executor_adapter::GraphToolFactory; use codegraph_mcp_core::analysis::AnalysisType; -use codegraph_mcp_core::context_aware_limits::ContextTier; use codegraph_mcp_tools::GraphToolExecutor; use crate::autoagents::codegraph_agent::CodeGraphAgentOutput; use autoagents::core::agent::memory::SlidingWindowMemory; -use autoagents::core::agent::prebuilt::executor::ReActAgent; use autoagents::core::agent::AgentBuilder; -use autoagents::core::agent::{ - AgentDeriveT, AgentExecutor, AgentHooks, Context, DirectAgentHandle, ExecutorConfig, -}; use autoagents::core::error::Error as AutoAgentsError; -use autoagents::core::tool::{shared_tools_to_boxes, ToolT}; /// Agent implementation for CodeGraph with manual tool registration #[derive(Debug, Clone)] @@ -743,13 +765,11 @@ pub struct CodeGraphReActAgent { impl AgentDeriveT for CodeGraphReActAgent { type Output = CodeGraphAgentOutput; - fn description(&self) -> &'static str { - // Use Box::leak to convert runtime String to &'static str - // This is the standard AutoAgents pattern for dynamic descriptions - Box::leak(self.system_prompt.clone().into_boxed_str()) + fn description(&self) -> &str { + &self.system_prompt } - fn name(&self) -> &'static str { + fn name(&self) -> &str { "codegraph_agent" } @@ -842,7 +862,7 @@ impl CodeGraphAgentBuilder { // Get executor adapter for tool construction let executor_adapter = self.tool_factory.adapter(); - // Manually construct all 6 tools with the executor (Arc-wrapped for sharing) + // Manually construct all tools with the executor (Arc-wrapped for sharing) let tools: Vec> = vec![ Arc::new(SemanticCodeSearch::new(executor_adapter.clone())), Arc::new(GetTransitiveDependencies::new(executor_adapter.clone())), @@ -1110,7 +1130,7 @@ mod tests { let adapter = CodeGraphChatAdapter::new(mock_llm, ContextTier::Medium); let messages = vec![ChatMessage::user().content("Hello").build()]; - let response = adapter.chat(&messages, None, None).await.unwrap(); + let response = adapter.chat(&messages, None).await.unwrap(); assert_eq!(response.text(), Some("Echo: Hello".to_string())); } diff --git a/install-codegraph-wsl.sh b/install-codegraph-wsl.sh new file mode 100644 index 0000000..4f6761e --- /dev/null +++ b/install-codegraph-wsl.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# ABOUTME: Installs CodeGraph CLI with some features and SurrealDB enabled. +# ABOUTME: Checks WSL Ubuntu prerequisites and compiles codegraph-mcp with agentic tooling enabled. + +set -euo pipefail + +# Build with some features +FEATURE_FLAGS="--features autoagents-lats,ai-enhanced,codegraph-ai/openai-compatible,embeddings-ollama,embeddings-lmstudio,server-http" +SURR_URL="${CODEGRAPH_SURREALDB_URL:-ws://localhost:3004}" +SURR_NAMESPACE="${CODEGRAPH_SURREALDB_NAMESPACE:-ouroboros}" +SURR_DATABASE="${CODEGRAPH_SURREALDB_DATABASE:-codegraph}" +HTTP_PORT="${CODEGRAPH_HTTP_PORT:-3000}" +INSTALL_PATH="${CARGO_HOME:-$HOME/.cargo}/bin" + +info() { printf '[INFO] %s\n' "$1"; } +warn() { printf '[WARN] %s\n' "$1"; } +fail() { printf '[ERROR] %s\n' "$1"; exit 1; } + +info "Preparing to install CodeGraph" + +[[ "${WSL_DISTRO_NAME:-}" == Ubuntu* ]] || fail "This installer targets WSL Ubuntu Linux." +command -v apt >/dev/null 2>&1 || fail "apt is required" +command -v cargo >/dev/null 2>&1 || fail "cargo is required" +command -v rustup >/dev/null 2>&1 || fail "rustup is required" +command -v pkg-config >/dev/null 2>&1 || fail "pkg-config is required" +command -v c++ >/dev/null 2>&1 || fail "c++ is required (build-essential)" +command -v zstd >/dev/null 2>&1 || fail "zstd is required" + +# Check for SurrealDB +if ! command -v surreal >/dev/null 2>&1; then + warn "SurrealDB CLI not found; installing via script..." + curl -sSf https://install.surrealdb.com | sh + info "SurrealDB CLI installed" +else + info "SurrealDB CLI detected" +fi + +# Check for Ollama (optional but recommended) +if ! command -v ollama >/dev/null 2>&1; then + warn "Ollama not found; installing via script..." + curl -fsSL https://ollama.com/install.sh | sh + warn "Ollama installed" +else + info "Ollama detected" +fi + +surreal upgrade --version 2.2.8 +sudo apt install libssl-dev +mkdir -p ~/.codegraph + +info "Compiling CodeGraph with these features: ${FEATURE_FLAGS}" +info "" +info "This may take 5-10 minutes depending on your machine..." + +# Binary now lives in the server crate after the MCP split +cargo install --target x86_64-unknown-linux-gnu --path crates/codegraph-mcp-server --bin codegraph ${FEATURE_FLAGS} --force + +info "CodeGraph installed to ${INSTALL_PATH}" +cat <