Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@ Versioning: `0.0.x` for fixes and small steps, `0.x` for milestone releases
- New `RepositoryView` feature slice with its own Zustand store; all
backend access flows through the typed `lib/ipc` layer.

## [0.2.1] - 2026-07-05

### Added

- Code Intelligence backend (sub-step; no UI yet), no AI:
- Deterministic detectors in `devpilot-core::intel`: cyclic dependencies
(Tarjan SCC over the dependency graph), dead code (functions with no
detected callers, not exported or `main` — heuristic), duplication
(identical normalized line blocks), and code search (rank symbols and
paths by query overlap).
- `AnalyzeCodeIntelligence` and `SearchCode` use cases (parse the repo,
build the architecture graphs, run the detectors).
- Tauri commands via DI: `analyze_code_intelligence`, `search_code`; typed
`lib/ipc/intel.ts`.

## [0.2.0] - 2026-07-04

Milestone: you can now chat with your repository.
Expand Down
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "2"
members = ["apps/desktop/src-tauri", "crates/*"]

[workspace.package]
version = "0.2.0"
version = "0.2.1"
edition = "2021"
license = "MIT"
repository = "https://github.com/s1rry/devpilot"
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "devpilot-desktop",
"private": true,
"version": "0.2.0",
"version": "0.2.1",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
36 changes: 32 additions & 4 deletions apps/desktop/src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
use std::path::PathBuf;

use devpilot_core::entities::{
AiSettings, ArchitectureModel, ChatMessage, FileAst, ProjectMetadata, RecentProject,
RepositoryId, RepositorySource, ScanReport, SourceFile,
AiSettings, ArchitectureModel, ChatMessage, CodeIntelligenceReport, FileAst, ProjectMetadata,
RecentProject, RepositoryId, RepositorySource, ScanReport, SearchHit, SourceFile,
};
use devpilot_core::usecases::{
AnalyzeArchitecture, ChatWithRepository, ListRecentProjects, OpenProject, RemoveRecentProject,
ScanRepository,
AnalyzeArchitecture, AnalyzeCodeIntelligence, ChatWithRepository, ListRecentProjects,
OpenProject, RemoveRecentProject, ScanRepository, SearchCode,
};
use futures_util::StreamExt;
use tauri::ipc::Channel;
Expand Down Expand Up @@ -127,6 +127,34 @@ pub async fn export_architecture(
Ok(out_path)
}

/// Runs the deterministic code-intelligence detectors (cyclic dependencies,
/// dead code, duplication) over a project.
#[tauri::command]
pub async fn analyze_code_intelligence(
path: String,
state: State<'_, AppState>,
) -> Result<CodeIntelligenceReport, String> {
let use_case = AnalyzeCodeIntelligence::new(state.git.clone(), state.analyzer.clone());
use_case
.execute(RepositorySource::LocalPath(PathBuf::from(path)))
.await
.map_err(|error| error.to_string())
}

/// Searches a project's symbols and paths for a query.
#[tauri::command]
pub async fn search_code(
path: String,
query: String,
state: State<'_, AppState>,
) -> Result<Vec<SearchHit>, String> {
let use_case = SearchCode::new(state.git.clone(), state.analyzer.clone());
use_case
.execute(RepositorySource::LocalPath(PathBuf::from(path)), query)
.await
.map_err(|error| error.to_string())
}

/// Returns the current AI settings.
#[tauri::command]
pub async fn get_ai_settings(state: State<'_, AppState>) -> Result<AiSettings, String> {
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ fn main() {
commands::parse_file,
commands::analyze_architecture,
commands::export_architecture,
commands::analyze_code_intelligence,
commands::search_code,
commands::get_ai_settings,
commands::set_ai_settings,
commands::chat,
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "DevPilot",
"version": "0.2.0",
"version": "0.2.1",
"identifier": "dev.devpilot.app",
"build": {
"beforeDevCommand": "pnpm dev",
Expand Down
56 changes: 56 additions & 0 deletions apps/desktop/src/lib/ipc/intel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { invoke } from "@tauri-apps/api/core";

/**
* Typed wrappers and types for Code Intelligence, mirroring the core
* `CodeIntelligenceReport` and `SearchHit`.
*/

/** A dependency cycle. */
export interface Cycle {
nodes: string[];
}

/** A function with no detected callers (heuristic). */
export interface DeadSymbol {
name: string;
file: string;
line: number;
}

/** One location of a duplicated block. */
export interface DuplicationLocation {
file: string;
start_line: number;
end_line: number;
}

/** A group of duplicated code blocks. */
export interface DuplicationGroup {
line_count: number;
occurrences: DuplicationLocation[];
}

/** The deterministic code-intelligence report. */
export interface CodeIntelligenceReport {
cyclic_dependencies: Cycle[];
dead_code: DeadSymbol[];
duplication: DuplicationGroup[];
}

/** A code-search result. */
export interface SearchHit {
path: string;
symbol: string | null;
line: number;
score: number;
}

/** Runs the cyclic-dependency, dead-code and duplication detectors. */
export function analyzeCodeIntelligence(path: string): Promise<CodeIntelligenceReport> {
return invoke<CodeIntelligenceReport>("analyze_code_intelligence", { path });
}

/** Searches the project's symbols and paths for a query. */
export function searchCode(path: string, query: string): Promise<SearchHit[]> {
return invoke<SearchHit[]>("search_code", { path, query });
}
66 changes: 66 additions & 0 deletions crates/devpilot-core/src/entities/intel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use serde::{Deserialize, Serialize};

/// A dependency cycle: a set of nodes that mutually depend on each other.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Cycle {
/// Node ids forming the cycle, in a deterministic order.
pub nodes: Vec<String>,
}

/// A function that appears to be unused (best-effort, heuristic).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DeadSymbol {
/// Function name.
pub name: String,
/// File the function is defined in.
pub file: String,
/// 1-based line the function starts on.
pub line: usize,
}

/// One location of a duplicated block.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DuplicationLocation {
/// File containing the block.
pub file: String,
/// 1-based first line of the block.
pub start_line: usize,
/// 1-based last line of the block.
pub end_line: usize,
}

/// A group of identical code blocks found in two or more places.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DuplicationGroup {
/// Number of (normalized) lines in the block.
pub line_count: usize,
/// Where the block occurs.
pub occurrences: Vec<DuplicationLocation>,
}

/// A code-search result.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SearchHit {
/// File the hit is in.
pub path: String,
/// Matching symbol name, when the hit is a symbol rather than a path.
pub symbol: Option<String>,
/// 1-based line of the hit (the symbol's line, or 1 for a path hit).
pub line: usize,
/// Relevance score; higher is better.
pub score: usize,
}

/// The deterministic code-intelligence report for a repository.
///
/// All findings are computed from the AST and architecture graphs; the dead
/// code and duplication detectors are heuristic and may have false positives.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct CodeIntelligenceReport {
/// Dependency cycles between modules/files.
pub cyclic_dependencies: Vec<Cycle>,
/// Functions with no detected callers.
pub dead_code: Vec<DeadSymbol>,
/// Groups of duplicated code blocks.
pub duplication: Vec<DuplicationGroup>,
}
4 changes: 4 additions & 0 deletions crates/devpilot-core/src/entities/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod analysis;
mod ast;
mod graph;
mod history;
mod intel;
mod language;
mod llm;
mod metadata;
Expand All @@ -24,6 +25,9 @@ pub use analysis::{
pub use ast::{ClassDef, ExportDecl, ExportKind, FileAst, FunctionDef, ImportDecl, InterfaceDef};
pub use graph::{ArchitectureModel, EdgeKind, Graph, GraphEdge, GraphNode, NodeKind};
pub use history::{AuthorStats, CommitHash, CommitInfo, FileChurn};
pub use intel::{
CodeIntelligenceReport, Cycle, DeadSymbol, DuplicationGroup, DuplicationLocation, SearchHit,
};
pub use language::Language;
pub use llm::{ChatMessage, ChatRequest, ModelInfo, Role};
pub use metadata::{LanguageStat, ProjectMetadata};
Expand Down
Loading
Loading