feat: Code Graph Memory System — full-stack implementation#580
Open
TheDarkSkyXD wants to merge 99 commits intospacedriveapp:mainfrom
Open
feat: Code Graph Memory System — full-stack implementation#580TheDarkSkyXD wants to merge 99 commits intospacedriveapp:mainfrom
TheDarkSkyXD wants to merge 99 commits intospacedriveapp:mainfrom
Conversation
…tection Add the ability for users to authenticate with their Anthropic Claude Pro/Max subscription via OAuth instead of requiring a separate API key. The feature detects existing Claude Code CLI installations and surfaces that status in the UI for a streamlined sign-in experience. Backend: - Add GET /api/providers/anthropic/oauth/cli-status endpoint that detects Claude Code CLI installation, version, and auth status by inspecting ~/.claude/ and running `claude auth status` - Add POST /api/providers/anthropic/oauth/start endpoint to initiate the PKCE authorization flow and return the browser authorize URL - Add POST /api/providers/anthropic/oauth/exchange endpoint to exchange the authorization code for access/refresh tokens - Add anthropic_oauth field to ProviderStatus for tracking OAuth state - Add set/clear_anthropic_oauth_credentials methods to LlmManager - Handle DELETE /api/providers/anthropic-oauth for credential removal Frontend: - Add AnthropicOAuthProviderCard below the Anthropic API key card with CLI detection status indicator and sign-in/remove actions - Add AnthropicOAuthDialog with model selector (user picks their model), PKCE flow steps, and authorization code input - Add ClaudeCliStatusResponse, AnthropicOAuthStartResponse, and AnthropicOAuthExchangeResponse types to the API client - Add claudeCliStatus(), startAnthropicOAuth(), and exchangeAnthropicOAuth() API functions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace window.open() with openExternal() helper that uses the Tauri shell plugin to open OAuth URLs in the system browser. window.open() in Tauri opens a webview instead of the default browser, breaking the OAuth flow in the desktop app. This also fixes the same latent bug in the existing OpenAI OAuth flow. - Prefix unused `state` parameter in start_anthropic_oauth with underscore to suppress compiler warning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… missing providers Upgrade ModelSelect to a proper searchable dropdown with chevron indicator, keyboard navigation (arrow keys + enter), selected model info badge, and loading/error states. Fix configured_providers in models.rs to detect Anthropic OAuth, Ollama, Nvidia, and GitHub Copilot so the /models endpoint returns models for all connected providers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rs, improve ModelSelect - Add nvidia and ollama/ollama-cloud to direct_provider_mapping() so models.dev catalog entries get correct provider IDs matching configured_providers() - Add GitHub Copilot models to extra_models() since they are not in models.dev (accessed via token exchange) - Mirror Anthropic OAuth credentials check in /providers endpoint so Settings UI correctly shows Anthropic as configured for OAuth users - Stop committing search draft on every keystroke in ModelSelect; only commit on explicit selection or Enter - Add PROVIDER_LABELS matching to ModelSelect filter so searching by display names like "Google Gemini" works Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous commit used anthropic_oauth_configured but never defined it. Add the definition using crate::auth::credentials_path() to match the same check used in configured_providers() in models.rs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ndle script Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, compaction)
Three fixes for tool call errors observed during worker execution:
1. Enable browser_evaluate by default (config/types.rs)
Workers using browser_evaluate were always hitting "JavaScript evaluation
is disabled in browser config". Changed the default from false to true so
workers can extract page content without requiring explicit config changes.
2. Handle browser_close gracefully on dead connections (tools/browser.rs)
When the browser's WebSocket connection is already gone (e.g. process
killed, connection timeout), browser.close() fails with "oneshot canceled".
This is not a real error — the browser is effectively closed. Now logs a
warning and returns success instead of propagating the error to the worker.
3. Fix history compaction orphaning tool_result blocks (agent/worker.rs,
agent/compactor.rs)
When compaction removes messages by draining from the front of history,
the drain boundary could fall between an assistant message (with tool_use
blocks) and the following user message (with tool_result blocks). This
left orphaned tool_results referencing removed tool_use_ids, causing the
Anthropic API to reject requests with:
"unexpected tool_use_id found in tool_result blocks"
Fixed in all three compaction paths (worker compact_history, channel
emergency_truncate, channel run_compaction) by advancing the removal
boundary past any User messages containing ToolResult blocks.
All fixes are platform-independent (Windows, macOS, Linux/Docker).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, compaction)
Three fixes for tool call errors observed during worker execution:
1. Enable browser_evaluate by default (config/types.rs)
Workers using browser_evaluate were always hitting "JavaScript evaluation
is disabled in browser config". Changed the default from false to true so
workers can extract page content without requiring explicit config changes.
2. Handle browser_close gracefully on dead connections (tools/browser.rs)
When the browser's WebSocket connection is already gone (e.g. process
killed, connection timeout), browser.close() fails with "oneshot canceled".
This is not a real error — the browser is effectively closed. Now logs a
warning and returns success instead of propagating the error to the worker.
3. Fix history compaction orphaning tool_result blocks (agent/worker.rs,
agent/compactor.rs)
When compaction removes messages by draining from the front of history,
the drain boundary could fall between an assistant message (with tool_use
blocks) and the following user message (with tool_result blocks). This
left orphaned tool_results referencing removed tool_use_ids, causing the
Anthropic API to reject requests with:
"unexpected tool_use_id found in tool_result blocks"
Fixed in all three compaction paths (worker compact_history, channel
emergency_truncate, channel run_compaction) by advancing the removal
boundary past any User messages containing ToolResult blocks.
All fixes are platform-independent (Windows, macOS, Linux/Docker).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a "Browse" button next to the Root Path input so users can select a project directory without manually copying/pasting the path. - Tauri desktop: opens native OS folder picker via tauri-plugin-dialog - Web/Docker: inline directory browser backed by new GET /api/fs/list-dir endpoint Works on Windows, macOS, Linux, and Docker. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Workers spawning large LLM requests (e.g. writing a full PRD) were getting stuck for 30+ minutes because: 1. The global reqwest client timeout of 120s was too short for large Anthropic completions with extended thinking — requests timed out before the API could finish generating. 2. The retry cascade (3 model-level retries × 5 worker-level retries) meant each timeout failure took ~30 minutes before the worker finally gave up, only to be respawned with the same result. Changes: - Add 10-minute per-request timeout on Anthropic API calls, overriding the 120s global client timeout. Matches the scale of the streaming path (30min). - Reduce MAX_TRANSIENT_RETRIES from 5 to 3 (still 9 total attempts with model-level retries) to fail faster on sustained API issues. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert WebChatPanel and CortexChatPanel text inputs from controlled (useState) to uncontrolled (ref-based) textareas so keystrokes bypass React's render cycle entirely. Wrap input components and message lists in React.memo to prevent expensive re-renders of long chat histories on every SSE event. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, catalog-backed GitHub Copilot - Add onBlur handler to ModelSelect so typed custom model IDs are committed when the input loses focus (e.g. clicking Save/Test without pressing Enter). Escape suppresses the commit via ref. - Add github-copilot to direct_provider_mapping() so /models pulls from the live models.dev catalog (25 models) instead of the hardcoded 5-model snapshot that drifts over time. - Remove hardcoded GitHub Copilot entries from extra_models() to avoid duplicates with catalog results. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Set suppressBlurCommitRef before blur in Enter and chevron-close handlers to prevent handleBlur from firing a second onChange() after handleSelect already committed the value. - Add "ollama" arm to defaults_for_provider() and provider_to_prefix() in routing.rs so ollama models are fully routable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…shot - Add minimax-cn and moonshotai-cn to direct_provider_mapping() so their models come from the live models.dev catalog. - Remove extra_models() entirely — all providers now use the catalog. No more hardcoded model lists that drift over time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # desktop/src-tauri/src/main.rs # src/api/server.rs
# Conflicts: # interface/src/api/client.ts # src/api/providers.rs # src/api/server.rs
…draws The overview page was polling the heavy /agents/instance endpoint every 10s (runs 5+ SQL queries per agent) and the topology graph was rebuilding all nodes on every refetch due to reference-equality checks that always failed because of changing timestamps. - Increase overview refetchInterval from 10s to 60s - Increase topology refetchInterval from 10s to 30s - Replace reference-equality sync with content-based fingerprint so the graph only redraws when visual data actually changes - Add Windows platform support for daemon IPC, filesystem stats, and SSH - Fix IS_TAURI import path in Settings, add routing import in server.rs - Populate agent configs before HTTP server starts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
useSetTopBar was calling store.setContent() synchronously during render, which triggered a setState on TopBar while Overview was still rendering. Wrap in useEffect so the update happens after render completes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ls in debug Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove eager avatar URL from topology graph nodes — agents without
custom avatars were triggering 404 console errors on every render.
The gradient fallback avatars display correctly without the URL.
- Add debounce={1} to ResponsiveContainer in AgentDetail charts to
prevent the "width(-1) and height(-1)" warnings on initial mount.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add scripts/rebuild.ps1 and scripts/rebuild.sh to rebuild backend, frontend, sidecar, and Tauri desktop app in one command - In debug builds, Spacebot.exe now spawns the backend server and pipes its logs to the console window so developers can see server activity - Increase stack size to 16 MB on Windows MSVC to prevent stack overflow in unoptimized debug builds Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rontend The Tauri debug build defaults to loading from devUrl (localhost:19840), but the rebuild scripts produce static files via `bun run build`. Adding `--features tauri/custom-protocol` makes the app use frontendDist instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Spacebot-native rebuild of GitNexus as a Layer 2 memory layer. When a project is added, a 10-phase AST parsing and graph construction pipeline fires automatically, capturing every function, class, import, call relationship, and execution flow in LadybugDB. Backend (Rust): - New src/codegraph/ module (15 files): types, db, schema, events, manager, pipeline (10 phases), languages (3 providers), search, watcher, eviction - CodeGraphManager singleton shared across all agents via ApiState - 3 tree-sitter language providers (TypeScript/JS, Python, Rust) with full AST walking behind the 'codegraph' feature flag - 10 REST API endpoints for project CRUD, graph queries, search - 3 agent tools: codegraph_query, codegraph_list_projects, codegraph_get_files_for_task - File watcher with notify crate and 500ms debounce - 15 optional tree-sitter crate deps behind 'codegraph' feature Frontend (React/TypeScript): - New global Projects sidebar tab with Folder icon - /projects route: project card grid with status badges, filters, create - /projects/$projectId route: detail page with 4 sub-tabs - Overview: project info, index stats, re-index action - Code Graph: 4 views (Communities, Entry Points, Search, Index Log) - Project Memory: filterable memory list with relevance scores - Settings: per-project config overrides (placeholder) - Remove Project dialog with cascade delete confirmation - 15 new TypeScript types + 10 API client methods Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rupt data The server process died when reindexing projects because CodeGraphDb::open silently swallowed file-deletion errors on Windows, then called Database::new on corrupt state causing a native code segfault. - Handle single-file DB format (lbug creates files, not directories) - Add retry_remove_db helper with escalating delays for Windows file locks - Always clean up .wal sibling alongside the main database file - Skip schema version check on freshly cleaned databases (avoids pointless nuke that fights Windows file handles on a just-created DB) - Drop FTS indexes before schema nuke to release Kuzu internal references - Bail with clear error instead of silently proceeding on deletion failure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use is_ok_and instead of map_or(false, ...) in db.rs - Collapse nested if statements with let-chains in c_sharp, java, manager, processes, and search - Extract AggregateResult type alias for complex return type in communities - Remove no-op .skip(0) in routes - Derive Default on NodeLabel enum instead of manual impl Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align filter-panel icons with GitNexus's lucide semantics (Braces/List/ FileCode/etc.) using their Hugeicons equivalents, and add a right-aligned count badge on Explorer folder rows showing direct child count. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… DBs Re-indexing a project with an existing LadybugDB could SIGSEGV inside `lbug::Database::new` if the on-disk data was stale or partially corrupt — spawn_blocking can't catch native segfaults, so the whole server process died. The previous fix hardened the open path for cases where the sidecar version file was present; it couldn't protect the first open on pre-existing installs, or cases where the data was corrupt in a way the sidecar check can't detect. - Add `reset_project_db` helper that drops the on-disk `lbug/` directory and version sidecar with Windows file-lock retries - Call it from `run_indexing_pipeline` after removing the in-memory handle, so `ensure_db` always runs against an empty directory during re-index - Add sidecar-version infrastructure: pre-open check that nukes a mismatched DB before `Database::new` can segfault; post-open write so subsequent opens can short-circuit the native _SchemaVersion query path entirely Delete already avoided lazy-open (remove_project comment, step 2), so it was always crash-safe. With this change, re-index is too. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oups Rewrites the mermaid layout mode as an interactive, relationship-clustered file graph built on React Flow + dagre. Files union-find into groups by shared IMPORTS/CALLS/EXTENDS/IMPLEMENTS edges, each group lays out as a top-down dagre hierarchy inside a container with an editable title, color swatch, and collapse toggle. Cross-group edges collapse into one thick bundled bezier per group pair, labelled with the count, which cuts SVG path count from thousands to dozens on large projects. Per-file card color overrides reuse the existing NodeColorPicker (extracted to its own module for sharing). All user overrides — titles, colors, collapsed state — persist per-project in localStorage. First-paint on large graphs (>100 files) starts with every group collapsed so only compact summary tiles plus cross-group bundles paint up front; the Sigma/graphology graph is also skipped while in mermaid mode. An auto-expand kicks in when a file is selected from the right rail so the target is never hidden behind a tile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tabs Replace the 16-swatch grid + native color input with a One UI-inspired picker: Swatches tab shows a 10x12 tint/shade grid, Spectrum tab offers a pointer- drag HSV area plus a brightness slider, and the footer carries hex/RGB readouts, a two-tone preview, recently used colors (localStorage-backed), an EyeDropper trigger, and explicit Cancel/Done actions so swatch clicks are previewed instead of applied immediately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nore - .cargo/config.toml: add /FORCE:MULTIPLE so zstd from lbug and zstd-sys (via lance) can coexist at link time on Windows MSVC. - Cargo.toml: pull in streaming-iterator (used by tree-sitter query cursor). - .gitignore: ignore .gitnexus local scratch dir. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
In debug builds the GUI subsystem hides stdout, so the backend sidecar's piped logs were being dropped. Call AllocConsole on startup so they land in a visible terminal window next to the app. Also silence unused-variable warnings by renaming the on_window_event bindings to _window/_event when the macOS branch is compiled out. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds langmap.rs (binary-search lookup of extension/basename to canonical language display name) regenerated from github-linguist/languages.yml filtered to entries present in ozh/github-colors. Used by the language breakdown feature to match GitHub's repo bar semantics. - src/codegraph/langmap.rs: generated lookup tables + lookup_extension / lookup_basename / language_for_path helpers (binary-search, sorted). - scripts/gen_langmap.mjs: regeneration script, with popularity ranking for extensions shared by multiple languages. - interface/src/lib/githubLanguageColors.json: color map input (also consumed by the frontend language breakdown component). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- html.rs / prisma.rs: tree-sitter providers so form-action URLs and Prisma model declarations produce edges to backend routes / queries. - jcl.rs: JCL job-control parser emitting JclJob/JclStep nodes; files route through the COBOL provider for structural walk survival. - cobol_exec.rs / cobol_preprocessor.rs: COBOL COPY/EXEC expansion so SQL/CICS/DLI calls embedded in copybooks become graph nodes. - languages.rs / language_detection.rs: add Jcl/Html/Prisma variants, register extensions (.jcl/.job/.proc, .html/.htm, .prisma), and widen COBOL's extension set with .copybook. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…se order - lang/queries/: one .rs per language (c, cpp, csharp, dart, go, java, javascript, kotlin, php, python, ruby, rust, swift, typescript) holding the .scm query text as a const &str, re-exported via mod.rs. Individual language providers now reference these instead of carrying their own query strings inline. - lang/ast_cache.rs: per-language LRU of parsed tree-sitter trees so incremental reindex doesn't reparse untouched files. - lang/parse_order.rs: topological ordering so files whose symbols are referenced elsewhere parse first, improving call-graph resolution. - pipeline/parsing.rs: wire the cache + parse order in; enrich symbol records with return type / visibility / annotations / parameter counts so downstream phases can emit richer metadata. - per-language providers (c_cpp, c_sharp, dart, go, java, kotlin, php, provider, python, ruby, rust_lang, swift, typescript, cobol): use the shared queries module, fill new Symbol fields via struct update syntax, and rely on Default for backwards-compat. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- codegraph/config/: parses Cargo.toml, tsconfig.json, go.mod, composer.json, pom.xml/build.gradle, csproj, Package.swift, pubspec.yaml into a shared ConfigContext the imports phase uses to resolve path aliases and module prefixes across languages. - codegraph/semantic/: framework-aware extractors (route_extractors/ for aspnet, django, fastapi, flask, laravel, symfony; named_bindings/ for DI containers in csharp/java_kotlin/php/python/rust/typescript) plus shared resolver, member_rules, response_shapes, symbol_table, type_env, and markdown link resolution. - pipeline/structure.rs: load the config context early so later phases can consult it. - pipeline/imports.rs: resolve aliased imports via ConfigContext and walk the semantic resolver for cross-module references. - pipeline/routes.rs: new phase that invokes route_extractors to emit HANDLES_ROUTE edges for web frameworks. - pipeline/enriching.rs: hook in markdown_links + response_shapes so docstrings and API response shapes become first-class graph nodes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the monolithic pipeline runner with a Phase trait: each stage (walker, parsing, structure, imports, calls, heritage, routes, named_bindings, communities, processes, enriching, overrides, embeddings, fts, incremental, complete) implements run/name/order, and pipeline/mod.rs just composes them with shared timing, progress reporting, and cancellation checks. - pipeline/phase.rs: Phase trait + shared context (PhaseCtx) carrying the db handle, progress sender, cancellation flag, and config. - pipeline/complete.rs: terminal phase that marks the project Ready and flushes derived caches. - pipeline/named_bindings.rs: new phase driving the per-language DI extractors added in codegraph/semantic/named_bindings. - Phase trait impls in walker/calls/heritage/communities/processes/ overrides/incremental. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- pipeline/embeddings.rs: replace the no-op stub with fastembed generating 384-dim all-MiniLM-L6-v2 vectors per symbol and writing them into a LadybugDB HNSW-indexed table for cosine-similarity search. Respects the skip_embeddings config flag so tests and bare-metal indexes stay fast. - pipeline/fts.rs: drop the external SQLite FTS5 sidecar and use LadybugDB's native full-text extension with per-table indexes on name / qualified_name / source_file. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- codegraph/schema.rs: bump schema to v12; add node labels Middleware, SqlQuery, CicsCall, DliCall, JclJob, JclStep, CodeEmbedding plus Community.cohesion / keywords / entry_point_score and Process.terminal_id. - codegraph/types.rs: add LanguageCount, PipelinePhase variants for routes/named_bindings/complete, and the NodeLabel additions. - codegraph/graph_queries.rs: corresponding queries for the new node types plus a language-bucket rollup used by the Projects page. - codegraph/search_augmentation.rs: BM25 FTS fast-path for IDE / palette completions (<500 ms), falls back to full hybrid search when the FTS index isn't ready. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…down - codegraph/manager.rs: detect_languages now walks files via the langmap lookup and sums byte counts (matches GitHub's repo bar). Also threads ConfigContext from structure phase into imports and wires the new routes / named_bindings / embeddings / fts phases plus an index-cancellation flag. - codegraph/watcher.rs: skip dotfiles, dotdirs, and target/build artifacts so fs events don't re-queue work on every cache write. - codegraph/db.rs: minor iterator simplification. - codegraph/tools.rs / tools/codegraph.rs: surface the new search augmentation + language breakdown to the agent tool layer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ndpoint - api/schema_alias.rs: optional ?schema=gitnexus query param that translates node labels and edge types at the API boundary, so clients speaking GitNexus vocabulary can consume the graph without an internal schema change. - api/codegraph.rs: wire the alias translation into the bulk fetch + add get_graph_stream, an NDJSON endpoint that streams nodes and edges without the previous pagination truncation limits. - api/server.rs: route the new streaming endpoint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…otstrap - tests/bulletin.rs, tests/context_dump.rs: add codegraph_manager: None + pass the new optional arg through worker_tool_server ctors so tests build after the manager plumbing. - messaging/email.rs: box ImapSession::Tls (the TLS variant is ~368 B vs ~120 B plaintext) so the enum stays compact. - tools/browser.rs: collapse nested if-let into the new let-chain. - agent/compactor.rs, agent/cortex.rs: drop stale "Phase N" history markers from comments. - secrets/keystore.rs: allow dead_code on SERVICE_NAME for non-keyring builds. - api/providers.rs: fn-pointer/spawn_blocking tidying in claude_cli_status. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- routes/GlobalProjects.tsx: render the GitHub-style language bar for each project card using the new backend language_breakdown field, add a one-click re-index button, and wire up an optimistic remove action backed by the new API. - routes/ProjectDetail.tsx: show schema-upgrade banner when the stored graph is older than the current code version, display the language breakdown, and drop the Memory / Settings tab toggle (functionality absorbed into other routes). - components/projects/LanguageBreakdown.tsx (new): reusable stacked bar + legend. Uses GitHub-linguist colors. - lib/languageColors.ts: resolves a language name to its GitHub color via the already-present githubLanguageColors.json. - Deleted ProjectMemoryTab.tsx / ProjectSettingsTab.tsx — dead code after the detail route was restructured. - api/client.ts: expose language_breakdown / CodeGraphLanguageCount on the CodeGraphProject type. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…g layout - api/ndjson.ts (new): async generator that reads an NDJSON stream line by line with AbortSignal support. - api/client.ts: codegraphGraphStream pulls nodes and edges over the new streaming endpoint with throttled onProgress callbacks. - api/schema.d.ts: drop the now-obsolete truncated / total_available fields from BulkNodesResponse; streaming has no cap. - CodeGraphSearchBar / CodeGraphStatusBar: remove the truncation display props/UI since streaming eliminates the cap. - GraphCanvas.tsx: cache the first-push state so subsequent SSE refetches don't retrigger the intro camera animation. - codegraph/constants.ts: widen the taxonomy to the ~40 raw backend labels with CANONICAL_LABEL mapping so filters hide every variant, add WRAPS edge + edge-color resolver. - codegraph/graphAdapter.ts: switch the solar layout to ring + satellite clustering (core → folders → types → files → functions) for better readability on medium-sized graphs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Runs the codegraph pipeline against self-contained fixture projects (go_basic, rust_basic, python_basic, typescript_basic, markdown_docs) and diffs the resulting graph against a committed expected.json. - tests/parity.rs: harness, including SPACEBOT_PARITY_REGEN=1 to regenerate the expected output when an intentional change lands. - tests/parity_fixtures/: source trees + expected.json baselines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a transparency slider with checkered backdrop below both Swatches and Spectrum tabs, and stores HSV in component state so dragging brightness to 0 (or saturation to 0) preserves the picked hue when sliding back up. Output stays `#rrggbb` while opaque and widens to `#rrggbbaa` only when alpha drops below 1. Slider track is sized to contain the thumb and the thumb is inset so it remains fully visible at both extremes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Recompute language_breakdown after incremental updates and full re-index fallbacks so file add/delete is reflected in the bar and legend; folds sub-0.05% slices into "Other" to avoid rendering visually-empty rows; GlobalProjects subscribes to SSE so the list refreshes instantly instead of on the 10s idle poll. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A native segfault inside `Database::new()` — typically WAL recovery on an inconsistent `.wal` left by a prior ungraceful shutdown — aborts the sidecar process and cannot be caught by `spawn_blocking`. Without state on disk, every subsequent launch hits the same crash and users have to manually delete the DB directory. Write an `<db>.opening` marker before calling `Database::new()` and remove it after `open()` fully succeeds. On the next open, a lingering marker is treated as evidence of a prior mid-open crash: the DB files are nuked before any native code runs, so the process re-indexes from scratch instead of dying the same way twice. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… bugs The Tauri sidecar binds its HTTP listener before LadybugDB, ONNX, and FTS subsystems finish warming up, so the SPA used to race the backend and surface a wall of ERR_CONNECTION_REFUSED + a spurious "disconnected from server" banner on fresh launch. Three lifecycle bugs also made it worse under real disconnects. - `api/fetchRetry.ts`: bounded exponential-backoff retry for connect- level fetch failures. Applied via `fetchJson` (client.ts) and at the front of `fetchNdjson` (ndjson.ts). Retries only the connect — once a stream body starts reading, mid-stream failures still propagate. - `hooks/useServer.tsx`: health check requires two consecutive failures before flipping to "disconnected". A single transient during lazy per-project LadybugDB schema init used to cascade into disabling SSE and showing the banner. - `hooks/useEventSource.ts`: cancel any pending backoff timer when SSE is disabled (otherwise a queued reconnect fires later and opens a stray EventSource) and reset backoff on re-enable so the first reconnect attempt isn't pushed 30s out by a previous run's delay. - `routes/ProjectDetail.tsx`: cancel the outgoing project's codegraph queries on `projectId` change and drop idle polling (`refetchInterval = false` in indexed/idle state) so navigating between projects doesn't leave orphaned in-flight requests hammering the backend. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…adcrumb nodes Replace the ad-hoc componentGrouper/GroupContainer approach with a folder-based "layer" taxonomy: every file is bucketed by the first segment of its source_file path, and cross-layer file-to-file edges are aggregated into a single bundle per (source, target) pair. The overview now renders tens of bundles instead of thousands of raw edges. - `layerBuilder.ts`: bucketing + cross-layer edge aggregation. - `LayerClusterNode.tsx`: overview card per layer with drill-in. - `PortalNode.tsx`: represents cross-layer connections when drilled in. - `Breadcrumb.tsx`: layer drill-in/out navigation. - `FileNodeCardCompact.tsx`: denser file card for zoomed-out views. - `OrphanDrawer.tsx`: side panel for files with no layer association. - `nodeDescription.ts`: shared node-label/description formatting. - `MermaidView.tsx`: rewritten around the layer + portal graph. - Remove `GroupContainer.tsx` and `componentGrouper.ts` (superseded). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
React Flow's default handle is interactive: hovering the dot shows a
`+` cursor and drags produce new edges. Spacebot renders these cards
in a read-only graph, so the affordance is confusing and the drag
targets nothing.
Set `isConnectable={false}` on every handle across FileNodeCard,
FileNodeCardCompact, LayerClusterNode, and PortalNode. React Flow
routes edges through the handle as an attachment point but turns off
pointer events and the connect cursor on it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Overhaul the codegraph search and filter surfaces so they behave
correctly across layout modes. Prior state: the Filters tab was
always shown even when it did nothing (mermaid ignores label/edge/
depth filters); the top search bar didn't react to filter toggles
on graph layouts; selecting a symbol from search while on mermaid
did nothing because only files have cards on that canvas.
CodeGraphSidebar
- New `showFilters` prop hides the Filters tab button in both the
collapsed rail and the expanded header.
- Auto-switches activeTab back to "files" if the prop flips false
while Filters is open, so the panel never renders an empty shell.
CodeGraphTab
- Derives effective filter values (`effectiveVisibleLabels`,
`effectiveVisibleEdgeTypes`, `effectiveDepthFilter`). On mermaid
these are the fully permissive sets; elsewhere they mirror the
user's toggles. Saved prefs in state/localStorage are untouched,
so switching layouts preserves them.
- Passes `showFilters={!isMermaid}` to the sidebar and the effective
values to sidebar / GraphCanvas / SearchBar.
CodeGraphSearchBar
- Accepts `visibleLabels` and, on non-mermaid layouts, skips
results whose label isn't in the set — so toggling "File" off in
the sidebar now also hides File results from the dropdown.
- Pre-builds a lowercase index of nodes (`useMemo([nodes])`), so
per-keystroke work is scoring only — the 15k-node `.toLowerCase()`
pass happens once per graph load.
- `useDeferredValue(query)` keeps typing responsive; React shows
the previous result set while the new scan runs on the low-
priority track.
- Scoring: exact > prefix > substring, with Folder/File matches
getting a large additive boost so `playlist.tsx` is never buried
under a flood of symbol nodes named exactly "playlist".
- Fuzzy subsequence fallback: when the query has no substring hit
anywhere, each node is still scored by an in-order character
walk, normalized into (0, 1) so fuzzy hits always rank below
real substring hits. Lets `plyist` still find `playlist.tsx`.
- In mermaid mode the dropdown is restricted to Folder and File
labels (symbols have no card to navigate to on that canvas).
- MAX_RESULTS 12 → 30 and a visible `.scrollbar-app` on the
dropdown so the extra slots are actually browsable.
MermaidView
- Replaces the ad-hoc `selectedFileId` derivation with a single
`selectionTarget` that resolves any selection source into
`{ fileId, layerId }`: Folder → layer only, File → both, Symbol
→ parent file + its layer via `source_file`. The auto drill-in
effect now reads `selectionTarget.layerId`, so Folder selections
from the search actually navigate.
- Auto-opens the Other-files drawer when the selected file is an
orphan, so a search-bar pick on an edgeless file surfaces its
card without a manual toggle.
layerBuilder
- Export `firstSegment` so MermaidView can derive a layer id from
a folder's source_file using the same rule the graph builder
uses (no drift between the two).
style.scss
- New `.scrollbar-app` utility driven by the existing
`--color-app-explorer-scrollbar` theme variable, matching the
rest of the app across light/dark/high-contrast themes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Toggling an edge-type in the Filters tab previously did nothing visible: the filter just updated a ref read by the Sigma edge reducer and called `sigma.refresh()`, but Sigma caches reducer output per scene and the reducer doesn't re-run without a scene change, so stale edges stayed on screen. Node filtering worked because it writes `hidden` directly on the graphology graph — edges should do the same. Add `filterGraphByEdgeTypes` mirroring `filterGraphByLabels`: iterate every edge and set its `hidden` attribute based on three rules evaluated in order: - In-taxonomy edge (CONTAINS / DEFINES / IMPORTS / CALLS / EXTENDS / IMPLEMENTS): hidden iff its type isn't in the user's visible set. - Off-taxonomy edge (HAS_METHOD, HAS_PROPERTY, HAS_PARAMETER, DECORATES, MEMBER_OF, STEP_IN_PROCESS, OVERRIDES, TESTED_BY, HANDLES_TOOL, WRAPS, QUERIES, USES, ACCESSES): always hidden. The backend emits these ancillary relationships but they carry no user-facing toggle in this view and rendered as unexplainable gray lines between symbol nodes. - Either endpoint is hidden: always hidden. Prevents dangling lines when a label is toggled off in the Filters tab — e.g. hiding the Type / Function / Method / Variable nodes no longer leaves their incident edges drawing to now-invisible endpoints. GraphCanvas's re-filter `useEffect` now calls `filterGraphByEdgeTypes` after `filterGraphByDepth` (so node `hidden` is already current when the edge pass reads it) and adds `visibleEdgeTypes` to the deps, so edge-type toggles actually trigger a refilter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
Important Review skippedToo many files! This PR contains 204 files, which is 54 over the limit of 150. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (65)
📒 Files selected for processing (204)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Code Graph Memory System — a Spacebot-native code indexer and graph explorer that gives every project its own queryable AST graph. Per-project LadybugDB storage (schema v12) is populated by a 16-phase pipeline over 18 languages, and the graph is exposed to both the UI (interactive canvas + Mermaid views) and agents (11 graph-aware tools). The new Projects tab in the sidebar is the entry point; it lists indexed projects, shows live indexing progress over SSE, and drills into a per-project detail view with a full graph canvas.
Codegraph-specific changes: 194 files changed, ~49.5k insertions / ~1.1k deletions. Most is new surface area (
src/codegraph/,interface/src/components/projects/, parity fixtures); incidental changes to existing files are limited to wiring the manager intoApiState/AgentDepsand addingProcessEvent::CodeGraph*variants.What's included
Backend —
src/codegraph/(~35k LOC, 101 new files)CONTAINS,CALLS,IMPORTS,EXTENDS,IMPLEMENTS,OVERRIDES,HAS_METHOD,ACCESSES,USES,HAS_PARAMETER,DECORATES,TESTED_BY,ENTRY_POINT_OF,HANDLES_ROUTE,FETCHES,QUERIES,HANDLES_TOOL,WRAPS, …).lbug 0.15.2), schema v12 with auto-migration of stale schemas, crash recovery on corrupt opens, and a missing-schema sentinel that marks the DB stale.pipeline/): 16 ordered phases — walker → parsing → structure → calls → imports → heritage → overrides → named_bindings → enriching → communities → processes → routes → embeddings → fts → incremental → complete. Emits progress events per phase.lang/queries/with an AST cache and deterministic parse order. Language map (langmap.rs) is auto-generated from GitHub Linguist viascripts/gen_langmap.mjs.semantic/): cross-file type environment, symbol table, MRO-aware call resolution, response-shape inference, markdown link extraction, framework route extractors for Django, FastAPI, Flask, Laravel, Symfony, and ASP.NET, plus language-specific named-binding resolvers.config/): parsers forCargo.tomlworkspaces,composer.json,csproj,go.mod, Maven/Gradle,Package.swift,pubspec.yaml, andtsconfig.jsonfor accurate module/package graphs.src/api/codegraph.rs, 16 endpoints): project CRUD, reindex, communities, processes, search, index log, remove-info, node list/get, node edges, graph stats, bulk nodes/edges, plus an NDJSON streaming endpoint for large graphs. Aschema_aliaslayer also exposes responses under alternate field names for external-tool compatibility.src/main.rs):CodeGraphEvent→ApiEvent::CodeGraphStale/CodeGraphChanged/CodeGraphIndexedso the frontend can reactively update without polling.src/tools/codegraph.rs, 11 tools):codegraph_query,codegraph_list_projects,codegraph_get_files_for_task,codegraph_context,codegraph_impact,codegraph_detect_changes,codegraph_cypher,codegraph_rename,codegraph_route_map,codegraph_tool_map,codegraph_api_impact. Registered automatically on workers and the cortex chat server whenever the manager is present.codegraphCargo feature;default = ["codegraph"]. Builds without the feature skip the module entirely.src/api/fs.rs):/fs/read_fileendpoint with project-root sandboxing, 2 MB cap, and optional 1-indexed line ranges — powers the inspector panel without exposing arbitrary host paths.Frontend —
interface/(~10k LOC, 43 files)/projects(GlobalProjects.tsx): card grid with status badges, live language breakdown, re-index and remove actions, create-project dialog with directory browser, polling-free updates via SSE./projects/$projectId(ProjectDetail.tsx): two sub-tabs — Overview (language breakdown, graph stats, index log) and Code Graph (interactive canvas). Cascade-delete dialog shows exact node/edge counts before removal.components/projects/codegraph/): 4-zone interactive layout built on React Flow + Sigma.js. Features:MermaidView.tsx) with zoom/pan and a right-panel inspector.interface/src/api/client.ts+ndjson.ts+fetchRetry.ts): typed wrappers for all 16 codegraph endpoints plus the streaming reader.Tests —
tests/parity.rs+tests/parity_fixtures/Parity harness with per-language fixtures (Rust, Python, TypeScript, Go, Markdown) that exercise the pipeline end-to-end and assert expected node/edge counts per fixture.
codegraph_manageris threaded through the test bootstrap sotests/context_dump.rsandtests/bulletin.rscan run alongside.Supporting infrastructure
scripts/gen_langmap.mjs— regenerateslangmap.rsfrom GitHub Linguist data..cargo/config.toml— Windows-specific zstd linker fix needed for the tree-sitter dependency set.Test plan
cargo checkpasses.cargo check --features codegraphpasses (default feature set).cargo check --no-default-featurespasses (codegraph-free build still compiles).cargo clippyclean on the codegraph module.cargo test -p spacebot --test paritypasses for every fixture language.bun run buildininterface/)./projectsrenders the empty state with an Add Project button and a working directory browser.indexed./projects/$projectId→ Overview shows non-zero language breakdown, graph stats, and an index log./projects/$projectId→ Code Graph renders the interactive canvas with folder clustering, opens the inspector panel on node click, and the Mermaid view toggles cleanly.code_graph_changedon SSE and the canvas updates without a full reload.codegraph_list_projects,codegraph_query, andcodegraph_impactreturn sane results against an indexed project.🤖 Generated with Claude Code