From 80ce631c9ccf34ab328564b753d81c6db7e99f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bystr=C3=B6m?= Date: Tue, 3 Mar 2026 11:53:09 +0100 Subject: [PATCH 1/2] Add support for running in WSL --- .gitignore | 1 + crates/codegraph-core/Cargo.toml | 11 ++- install-codegraph-wsl.sh | 128 +++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 install-codegraph-wsl.sh diff --git a/.gitignore b/.gitignore index 2d3fa541..7b9a99c1 100644 --- a/.gitignore +++ b/.gitignore @@ -186,3 +186,4 @@ idd-state.graphson todo.md *.spec.md journal.md +.aider* diff --git a/crates/codegraph-core/Cargo.toml b/crates/codegraph-core/Cargo.toml index 4a0e9391..037117f8 100644 --- a/crates/codegraph-core/Cargo.toml +++ b/crates/codegraph-core/Cargo.toml @@ -36,7 +36,6 @@ clap = { workspace = true } colored = { workspace = true } indicatif = { workspace = true } once_cell = { workspace = true } -tikv-jemallocator = { workspace = true } hashbrown = { workspace = true } rustc-hash = { workspace = true } sha2 = { workspace = true } @@ -52,6 +51,9 @@ bytes = { workspace = true } bumpalo = "3.15" rkyv = { workspace = true } +[target.'cfg(macos)'.dependencies] +tikv-jemallocator = { workspace = true } + [target.'cfg(unix)'.dependencies] libc = "0.2" @@ -71,6 +73,9 @@ name = "core_micro" harness = false [features] -# Enable jemalloc as the global allocator and expose jemalloc controls -default = ["jemalloc"] +default = [] jemalloc = [] + +[target.'cfg(macos)'.features] +# Enable jemalloc as the global allocator +default = ["jemalloc"] diff --git a/install-codegraph-wsl.sh b/install-codegraph-wsl.sh new file mode 100644 index 00000000..15fbf986 --- /dev/null +++ b/install-codegraph-wsl.sh @@ -0,0 +1,128 @@ +#!/bin/bash +# ABOUTME: Installs CodeGraph CLI with autoagent-lates features and SurrealDB enabled. +# ABOUTME: Checks WSL Ubuntu prerequisites and compiles codegraph-mcp with agentic tooling enabled. + +set -euo pipefail + +# Build with LATS +FEATURE_FLAGS="--features autoagents-lats" +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 (autoagent-lats)" + +[[ "${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)" + +# 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 - local LLM/embedding support will be limited" + warn "Install from: https://ollama.com/download" +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 < Date: Wed, 4 Mar 2026 10:52:12 +0100 Subject: [PATCH 2/2] Port to WSL Replaced jemalloc with mimalloc for compatibility with non-MacOS. Also got agent_builders.rs compiling again. Three codegraph-core watch tests won't pass in WSL since network mounted file systems won't emit any events (so notify 0.8.2 won't see them). --- Cargo.lock | 41 +++++----- Cargo.toml | 3 +- crates/codegraph-core/Cargo.toml | 16 ++-- crates/codegraph-core/src/lib.rs | 6 +- .../src/autoagents/agent_builder.rs | 74 ++++++++++++------- install-codegraph-wsl.sh | 18 +++-- 6 files changed, 86 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e48268f5..8f8ce98a 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 99bb639e..19567d1c 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 037117f8..c11df3d1 100644 --- a/crates/codegraph-core/Cargo.toml +++ b/crates/codegraph-core/Cargo.toml @@ -36,6 +36,7 @@ clap = { workspace = true } colored = { workspace = true } indicatif = { workspace = true } once_cell = { workspace = true } +mimalloc = { workspace = true } hashbrown = { workspace = true } rustc-hash = { workspace = true } sha2 = { workspace = true } @@ -51,13 +52,10 @@ bytes = { workspace = true } bumpalo = "3.15" rkyv = { workspace = true } -[target.'cfg(macos)'.dependencies] -tikv-jemallocator = { 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" @@ -73,9 +71,5 @@ name = "core_micro" harness = false [features] -default = [] -jemalloc = [] - -[target.'cfg(macos)'.features] -# Enable jemalloc as the global allocator -default = ["jemalloc"] +default = ["mimalloc"] +mimalloc = [] diff --git a/crates/codegraph-core/src/lib.rs b/crates/codegraph-core/src/lib.rs index ca416a47..93c2e535 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 3834139c..c2adae9e 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 index 15fbf986..4f6761e0 100644 --- a/install-codegraph-wsl.sh +++ b/install-codegraph-wsl.sh @@ -1,11 +1,11 @@ #!/bin/bash -# ABOUTME: Installs CodeGraph CLI with autoagent-lates features and SurrealDB enabled. +# 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 LATS -FEATURE_FLAGS="--features autoagents-lats" +# 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}" @@ -16,7 +16,7 @@ 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 (autoagent-lats)" +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" @@ -24,6 +24,7 @@ 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 @@ -36,8 +37,9 @@ fi # Check for Ollama (optional but recommended) if ! command -v ollama >/dev/null 2>&1; then - warn "Ollama not found - local LLM/embedding support will be limited" - warn "Install from: https://ollama.com/download" + warn "Ollama not found; installing via script..." + curl -fsSL https://ollama.com/install.sh | sh + warn "Ollama installed" else info "Ollama detected" fi @@ -56,8 +58,8 @@ cargo install --target x86_64-unknown-linux-gnu --path crates/codegraph-mcp-serv info "CodeGraph installed to ${INSTALL_PATH}" cat <