codegraph-engine 2.1.8__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/PKG-INFO +10 -10
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/README.md +9 -9
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/pyproject.toml +1 -1
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/__init__.py +1 -1
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/cli.py +60 -14
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/context.py +3 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/database/interrogation.py +30 -7
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/freshness.py +59 -21
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/indexer.py +4 -1
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/interrogation.py +19 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/mcp/server.py +8 -1
- codegraph_engine-2.2.0/src/codegraph/runtime/runner.py +204 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph_engine.egg-info/PKG-INFO +10 -10
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph_engine.egg-info/SOURCES.txt +2 -0
- codegraph_engine-2.2.0/tests/test_v22_enterprise_concurrency_and_runtime.py +200 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/LICENSE +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/setup.cfg +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/agent.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/agent_brain.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/agent_capabilities.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/agent_rules.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/architecture.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/audit.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/binding_resolver.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/cache.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/cli_output.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/config.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/constraints.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/database/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/database/extractor.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/database/models.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/epistemic.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/errors.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/evidence/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/evidence/citations.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/evidence_contract.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/frameworks.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/git.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/graph/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/graph/models.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/graph/traversal.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/classifier.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/models.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/parser.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/scanner.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/telemetry.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/indexing/test_framework.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/installer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/llm/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/llm/base.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/llm/context.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/mcp/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/mcp_diagnostics.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/memory/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/memory/store.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/models.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/monorepo.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/observability.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/optimizer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/planner.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/process_lifecycle.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/py.typed +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/query_expansion.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/ranking.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resolver.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resources/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resources/cache.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resources/coalescer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resources/debouncer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resources/governor.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resources/monitor.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/resources/policy.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/retrieval_policy.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/route_composer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/runtime/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/runtime/ingestor.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/runtime/models.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/runtime/reconciliation.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/search/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/search/hybrid.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/search/semantic.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/security/__init__.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/security/paths.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/security/redaction.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/semantic_decorators.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/target_resolver.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/task.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph/tool_selection_eval.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph_engine.egg-info/dependency_links.txt +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph_engine.egg-info/entry_points.txt +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph_engine.egg-info/requires.txt +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/src/codegraph_engine.egg-info/top_level.txt +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_active_coding_protection.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_adaptive_planning.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_adversarial_edge_cases.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_agent_ux_hardening.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_agent_ux_text_search_file_inspection.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_artifact_classification.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_artifact_retrieval_policy.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_benchmark_infra.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_bounded_caches.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_change_impact.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_cli_doctor_privacy.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_conservative_binding.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_context_budget.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_context_cache.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_context_compiler_v2.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_core.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_database_integrity.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_database_runtime_intelligence_and_security.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_debouncer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_dependency_injection.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_determinism_and_soak.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_developer_audit.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_epistemic_relationships.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_evaluation_framework.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_framework_analyzers.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_framework_routes_persistence.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_git_intelligence.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_hardening.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_interrogation_contracts.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_latency_modes_and_parallel.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_mcp_integration.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_monorepo_packages.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_package_boundaries.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_phase10_context_optimization.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_phase11_agent_integration.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_phase12_hardening.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_phase13_agent_brain_and_rc.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_phase2.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_platform_resources.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_ranking_engine.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_reference_resolution.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_registries_and_dispatch.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_request_coalescer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_resource_governor.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_retrieval_planner.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_route_composition.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_scanner_security.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_semantic_decorators.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_single_pass_parser.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_symbol_identity.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_task_ambiguity.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_task_mcp_tools.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_task_normalization.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_task_spec.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_test_intelligence.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v211_factory_resolution.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v211_features.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v211_imports_dependents_cli.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v211_recursive_frameworks.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v215_external_feedback.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v216_installer.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v217_large_repo_indexing.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v21_diagnostics.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v21_hard_exclusions.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v21_query_expansion.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v21_retrieval_policy.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_v21_target_resolver.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_verify_evidence.py +0 -0
- {codegraph_engine-2.1.8 → codegraph_engine-2.2.0}/tests/test_windows_and_process_lifecycle.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codegraph-engine
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Deep deterministic repository intelligence for AI coding agents (code, dependencies, databases, and runtime observations)
|
|
5
5
|
Author: CodeGraph contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -35,24 +35,24 @@ Dynamic: license-file
|
|
|
35
35
|
<img src="docs/assets/codegraph_logo.jpg" alt="CodeGraph MCP — Deep Deterministic Repository Intelligence for AI Coding Agents" width="500" />
|
|
36
36
|
</p>
|
|
37
37
|
|
|
38
|
-
<h1 align="center">CodeGraph Engine (v2.
|
|
38
|
+
<h1 align="center">CodeGraph-MCP Engine (v2.2.0)</h1>
|
|
39
39
|
|
|
40
40
|
<p align="center">
|
|
41
41
|
<strong>Deep deterministic repository intelligence for AI coding agents.</strong>
|
|
42
42
|
</p>
|
|
43
43
|
|
|
44
44
|
<p align="center">
|
|
45
|
-
<a href="https://pypi.org/project/codegraph-engine/2.
|
|
45
|
+
<a href="https://pypi.org/project/codegraph-engine/2.2.0/"><img src="https://img.shields.io/badge/pypi-codegraph--engine%20v2.2.0-blue.svg" alt="PyPI: codegraph-engine v2.2.0" /></a>
|
|
46
46
|
<a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.12%20%7C%203.13-3776AB.svg" alt="Python 3.12 | 3.13" /></a>
|
|
47
47
|
<a href="src/codegraph/mcp/server.py"><img src="https://img.shields.io/badge/MCP-14%20default%20%7C%2056%20full%20tools-2ea043.svg" alt="MCP Tools: 14 default | 56 full" /></a>
|
|
48
|
-
<a href="tests/"><img src="https://img.shields.io/badge/pytest-
|
|
48
|
+
<a href="tests/"><img src="https://img.shields.io/badge/pytest-861%20passed-brightgreen.svg" alt="Tests: 861 passed" /></a>
|
|
49
49
|
<a href="pyproject.toml"><img src="https://img.shields.io/badge/ruff-0%20errors-success.svg" alt="Ruff: 0 errors" /></a>
|
|
50
|
-
<a href="src/codegraph/"><img src="https://img.shields.io/badge/mypy-0%20issues%20(
|
|
50
|
+
<a href="src/codegraph/"><img src="https://img.shields.io/badge/mypy-0%20issues%20(80%20files)-blue.svg" alt="Mypy: strict" /></a>
|
|
51
51
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
52
52
|
</p>
|
|
53
53
|
|
|
54
54
|
<p align="center">
|
|
55
|
-
<a href="https://pypi.org/project/codegraph-engine/2.
|
|
55
|
+
<a href="https://pypi.org/project/codegraph-engine/2.2.0/"><strong>PyPI (v2.2.0)</strong></a> •
|
|
56
56
|
<a href="#2-quickstart-30-second-setup"><strong>Quickstart</strong></a> •
|
|
57
57
|
<a href="#1-built-for-aiml-and-backend-heavy-repositories"><strong>Built For</strong></a> •
|
|
58
58
|
<a href="#5-database-intelligence"><strong>Database Intelligence</strong></a> •
|
|
@@ -126,7 +126,7 @@ pip install "codegraph-engine[mcp]"
|
|
|
126
126
|
|
|
127
127
|
### Step 2: Configure Your AI Coding Agents (`codegraph install`)
|
|
128
128
|
|
|
129
|
-
CodeGraph includes an interactive, idempotent onboarding installer ([`src/codegraph/installer.py`](src/codegraph/installer.py)) that detects installed AI coding agents (**Claude Code**, **Cursor**, **Antigravity**, **Codex CLI**, **Gemini CLI**, and **Cline**), configures `mcpServers.codegraph`, installs marker-bounded routing instructions (`<!-- CODEGRAPH:START -->` … `<!-- CODEGRAPH:END -->`), and verifies MCP server startup:
|
|
129
|
+
CodeGraph-MCP includes an interactive, idempotent onboarding installer ([`src/codegraph/installer.py`](src/codegraph/installer.py)) that detects installed AI coding agents (**Claude Code**, **Cursor**, **Antigravity**, **Codex CLI**, **Gemini CLI**, and **Cline**), configures `mcpServers.codegraph`, installs marker-bounded routing instructions (`<!-- CODEGRAPH:START -->` … `<!-- CODEGRAPH:END -->`), and verifies MCP server startup:
|
|
130
130
|
|
|
131
131
|
```bash
|
|
132
132
|
# Interactive setup (detects installed agents, previews planned changes, asks confirmation)
|
|
@@ -232,7 +232,7 @@ InferenceService.run_inference
|
|
|
232
232
|
db:table:postgresql.public.prediction_logs
|
|
233
233
|
```
|
|
234
234
|
|
|
235
|
-
**What CodeGraph structurally proves**:
|
|
235
|
+
**What CodeGraph-MCP structurally proves**:
|
|
236
236
|
- `find_routes(path="/v1/predict")` resolves composed router prefixes (`MOUNTS`) to `predict_endpoint`.
|
|
237
237
|
- `trace_path(from_symbol="predict_endpoint", to_symbol="log_prediction")` proves the multi-hop execution chain across DI injection, preprocessing, model execution, and persistence.
|
|
238
238
|
- `get_db_impact(symbol="InferenceService.run_inference")` identifies downstream writes to `prediction_logs`.
|
|
@@ -250,7 +250,7 @@ TrainingPipeline.run
|
|
|
250
250
|
└──►CALLS (AST_VERIFIED) ──► Evaluator.compute_metrics
|
|
251
251
|
```
|
|
252
252
|
|
|
253
|
-
**What CodeGraph structurally proves**:
|
|
253
|
+
**What CodeGraph-MCP structurally proves**:
|
|
254
254
|
- `find_callees(symbol="TrainingPipeline.run")` enumerates every stage of the pipeline with exact file and line ranges.
|
|
255
255
|
- `find_tests(symbol="Evaluator.compute_metrics")` locates the unit and regression tests covering metric calculation.
|
|
256
256
|
- When a transform or model class is dynamically instantiated from a YAML string (`getattr(models, cfg.arch)`), CodeGraph explicitly records `POSSIBLE_CALLS` (`POSSIBLE`) or `UNRESOLVED_REFERENCE` (`UNKNOWN`) rather than fabricating a false static call edge.
|
|
@@ -269,7 +269,7 @@ AgentRunner.execute_step
|
|
|
269
269
|
└──►CALLS (AST_VERIFIED) ──► ModelProviderClient.generate
|
|
270
270
|
```
|
|
271
271
|
|
|
272
|
-
**What CodeGraph structurally proves**:
|
|
272
|
+
**What CodeGraph-MCP structurally proves**:
|
|
273
273
|
- Tracks decorator and call-based registrations (`@tool_registry.register("search_orders")`) via `REGISTERS` and `REGISTERED_HANDLER` edges.
|
|
274
274
|
- Tracks environment variable dependencies (`os.getenv("OPENAI_API_KEY")`) as `READS_ENV` edges with the variable name only—never indexing or exposing secret values.
|
|
275
275
|
|
|
@@ -2,24 +2,24 @@
|
|
|
2
2
|
<img src="docs/assets/codegraph_logo.jpg" alt="CodeGraph MCP — Deep Deterministic Repository Intelligence for AI Coding Agents" width="500" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<h1 align="center">CodeGraph Engine (v2.
|
|
5
|
+
<h1 align="center">CodeGraph-MCP Engine (v2.2.0)</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<strong>Deep deterministic repository intelligence for AI coding agents.</strong>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<a href="https://pypi.org/project/codegraph-engine/2.
|
|
12
|
+
<a href="https://pypi.org/project/codegraph-engine/2.2.0/"><img src="https://img.shields.io/badge/pypi-codegraph--engine%20v2.2.0-blue.svg" alt="PyPI: codegraph-engine v2.2.0" /></a>
|
|
13
13
|
<a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.12%20%7C%203.13-3776AB.svg" alt="Python 3.12 | 3.13" /></a>
|
|
14
14
|
<a href="src/codegraph/mcp/server.py"><img src="https://img.shields.io/badge/MCP-14%20default%20%7C%2056%20full%20tools-2ea043.svg" alt="MCP Tools: 14 default | 56 full" /></a>
|
|
15
|
-
<a href="tests/"><img src="https://img.shields.io/badge/pytest-
|
|
15
|
+
<a href="tests/"><img src="https://img.shields.io/badge/pytest-861%20passed-brightgreen.svg" alt="Tests: 861 passed" /></a>
|
|
16
16
|
<a href="pyproject.toml"><img src="https://img.shields.io/badge/ruff-0%20errors-success.svg" alt="Ruff: 0 errors" /></a>
|
|
17
|
-
<a href="src/codegraph/"><img src="https://img.shields.io/badge/mypy-0%20issues%20(
|
|
17
|
+
<a href="src/codegraph/"><img src="https://img.shields.io/badge/mypy-0%20issues%20(80%20files)-blue.svg" alt="Mypy: strict" /></a>
|
|
18
18
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
19
19
|
</p>
|
|
20
20
|
|
|
21
21
|
<p align="center">
|
|
22
|
-
<a href="https://pypi.org/project/codegraph-engine/2.
|
|
22
|
+
<a href="https://pypi.org/project/codegraph-engine/2.2.0/"><strong>PyPI (v2.2.0)</strong></a> •
|
|
23
23
|
<a href="#2-quickstart-30-second-setup"><strong>Quickstart</strong></a> •
|
|
24
24
|
<a href="#1-built-for-aiml-and-backend-heavy-repositories"><strong>Built For</strong></a> •
|
|
25
25
|
<a href="#5-database-intelligence"><strong>Database Intelligence</strong></a> •
|
|
@@ -93,7 +93,7 @@ pip install "codegraph-engine[mcp]"
|
|
|
93
93
|
|
|
94
94
|
### Step 2: Configure Your AI Coding Agents (`codegraph install`)
|
|
95
95
|
|
|
96
|
-
CodeGraph includes an interactive, idempotent onboarding installer ([`src/codegraph/installer.py`](src/codegraph/installer.py)) that detects installed AI coding agents (**Claude Code**, **Cursor**, **Antigravity**, **Codex CLI**, **Gemini CLI**, and **Cline**), configures `mcpServers.codegraph`, installs marker-bounded routing instructions (`<!-- CODEGRAPH:START -->` … `<!-- CODEGRAPH:END -->`), and verifies MCP server startup:
|
|
96
|
+
CodeGraph-MCP includes an interactive, idempotent onboarding installer ([`src/codegraph/installer.py`](src/codegraph/installer.py)) that detects installed AI coding agents (**Claude Code**, **Cursor**, **Antigravity**, **Codex CLI**, **Gemini CLI**, and **Cline**), configures `mcpServers.codegraph`, installs marker-bounded routing instructions (`<!-- CODEGRAPH:START -->` … `<!-- CODEGRAPH:END -->`), and verifies MCP server startup:
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
# Interactive setup (detects installed agents, previews planned changes, asks confirmation)
|
|
@@ -199,7 +199,7 @@ InferenceService.run_inference
|
|
|
199
199
|
db:table:postgresql.public.prediction_logs
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
**What CodeGraph structurally proves**:
|
|
202
|
+
**What CodeGraph-MCP structurally proves**:
|
|
203
203
|
- `find_routes(path="/v1/predict")` resolves composed router prefixes (`MOUNTS`) to `predict_endpoint`.
|
|
204
204
|
- `trace_path(from_symbol="predict_endpoint", to_symbol="log_prediction")` proves the multi-hop execution chain across DI injection, preprocessing, model execution, and persistence.
|
|
205
205
|
- `get_db_impact(symbol="InferenceService.run_inference")` identifies downstream writes to `prediction_logs`.
|
|
@@ -217,7 +217,7 @@ TrainingPipeline.run
|
|
|
217
217
|
└──►CALLS (AST_VERIFIED) ──► Evaluator.compute_metrics
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
**What CodeGraph structurally proves**:
|
|
220
|
+
**What CodeGraph-MCP structurally proves**:
|
|
221
221
|
- `find_callees(symbol="TrainingPipeline.run")` enumerates every stage of the pipeline with exact file and line ranges.
|
|
222
222
|
- `find_tests(symbol="Evaluator.compute_metrics")` locates the unit and regression tests covering metric calculation.
|
|
223
223
|
- When a transform or model class is dynamically instantiated from a YAML string (`getattr(models, cfg.arch)`), CodeGraph explicitly records `POSSIBLE_CALLS` (`POSSIBLE`) or `UNRESOLVED_REFERENCE` (`UNKNOWN`) rather than fabricating a false static call edge.
|
|
@@ -236,7 +236,7 @@ AgentRunner.execute_step
|
|
|
236
236
|
└──►CALLS (AST_VERIFIED) ──► ModelProviderClient.generate
|
|
237
237
|
```
|
|
238
238
|
|
|
239
|
-
**What CodeGraph structurally proves**:
|
|
239
|
+
**What CodeGraph-MCP structurally proves**:
|
|
240
240
|
- Tracks decorator and call-based registrations (`@tool_registry.register("search_orders")`) via `REGISTERS` and `REGISTERED_HANDLER` edges.
|
|
241
241
|
- Tracks environment variable dependencies (`os.getenv("OPENAI_API_KEY")`) as `READS_ENV` edges with the variable name only—never indexing or exposing secret values.
|
|
242
242
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codegraph-engine"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
description = "Deep deterministic repository intelligence for AI coding agents (code, dependencies, databases, and runtime observations)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -434,6 +434,8 @@ def routes(
|
|
|
434
434
|
framework: Annotated[str | None, typer.Option("--framework", "-f", help="Filter by framework (e.g. flask, fastapi)")] = None,
|
|
435
435
|
method: Annotated[str | None, typer.Option("--method", "-m", help="Filter by HTTP method (e.g. GET, POST)")] = None,
|
|
436
436
|
route_path: Annotated[str | None, typer.Option("--path", "-p", help="Filter by route path substring")] = None,
|
|
437
|
+
limit: Annotated[int | None, typer.Option("--limit", "-l", help="Maximum number of routes to return")] = None,
|
|
438
|
+
offset: Annotated[int, typer.Option("--offset", help="Number of routes to skip")] = 0,
|
|
437
439
|
json_output: Annotated[bool, typer.Option("--json", help="Output raw JSON array")] = False,
|
|
438
440
|
) -> None:
|
|
439
441
|
"""List and inspect indexed framework routes."""
|
|
@@ -479,6 +481,11 @@ def routes(
|
|
|
479
481
|
for r in rows
|
|
480
482
|
]
|
|
481
483
|
|
|
484
|
+
if limit is not None:
|
|
485
|
+
safe_offset = max(0, offset)
|
|
486
|
+
safe_limit = max(0, limit)
|
|
487
|
+
route_list = route_list[safe_offset : safe_offset + safe_limit]
|
|
488
|
+
|
|
482
489
|
if json_output:
|
|
483
490
|
typer.echo(json.dumps(route_list, indent=2))
|
|
484
491
|
else:
|
|
@@ -597,19 +604,60 @@ def debug(
|
|
|
597
604
|
)
|
|
598
605
|
|
|
599
606
|
|
|
600
|
-
@app.command(
|
|
601
|
-
|
|
602
|
-
|
|
607
|
+
@app.command(
|
|
608
|
+
"run",
|
|
609
|
+
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
|
610
|
+
)
|
|
611
|
+
def run_cmd(
|
|
612
|
+
ctx: typer.Context,
|
|
613
|
+
command: Annotated[list[str] | None, typer.Argument(help="Development command and arguments to execute")] = None,
|
|
603
614
|
repository: Annotated[Path | None, typer.Option("--repository", "-r", "--repo", help="Repository path")] = None,
|
|
604
|
-
|
|
615
|
+
sample_rate: Annotated[float, typer.Option("--sample-rate", help="Sampling rate for trace capture (0.0..1.0)")] = 1.0,
|
|
616
|
+
) -> None:
|
|
617
|
+
"""Execute a development command or server with transparent runtime trace capture."""
|
|
618
|
+
full_cmd = (command or []) + ctx.args
|
|
619
|
+
if not full_cmd:
|
|
620
|
+
cli_echo("Error: Command cannot be empty. Usage: codegraph run <command> [args...]")
|
|
621
|
+
raise typer.Exit(code=1)
|
|
622
|
+
|
|
623
|
+
repo = _resolve_repo(None, repository)
|
|
624
|
+
from codegraph.runtime.runner import run_with_telemetry
|
|
625
|
+
|
|
626
|
+
exit_code = run_with_telemetry(full_cmd, repository=repo, sample_rate=sample_rate)
|
|
627
|
+
raise typer.Exit(code=exit_code)
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
def _run_server(
|
|
631
|
+
path: Path | None,
|
|
632
|
+
repository: Path | None,
|
|
633
|
+
profile: str,
|
|
634
|
+
transport: str = "stdio",
|
|
635
|
+
host: str = "127.0.0.1",
|
|
636
|
+
port: int = 8765,
|
|
605
637
|
) -> None:
|
|
606
|
-
"""Run the stdio MCP server (requires the optional mcp extra)."""
|
|
607
638
|
repo = _resolve_repo(path, repository)
|
|
608
639
|
from codegraph.mcp import create_server
|
|
609
640
|
from codegraph.process_lifecycle import run_mcp_stdio_server
|
|
610
641
|
|
|
611
|
-
|
|
612
|
-
|
|
642
|
+
if transport.lower() == "sse":
|
|
643
|
+
server = create_server(repo, profile=profile, host=host, port=port)
|
|
644
|
+
server.run(transport="sse")
|
|
645
|
+
else:
|
|
646
|
+
server = create_server(repo, profile=profile)
|
|
647
|
+
run_mcp_stdio_server(server, repo, profile=profile)
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
@app.command()
|
|
651
|
+
def serve(
|
|
652
|
+
path: Annotated[Path | None, typer.Argument(help="Repository path (default: current directory)")] = None,
|
|
653
|
+
repository: Annotated[Path | None, typer.Option("--repository", "-r", "--repo", help="Repository path")] = None,
|
|
654
|
+
profile: Annotated[str, typer.Option("--profile", help="Tool profile: core | minimal | developer | full")] = "full",
|
|
655
|
+
transport: Annotated[str, typer.Option("--transport", "-t", help="MCP transport: stdio | sse")] = "stdio",
|
|
656
|
+
host: Annotated[str, typer.Option("--host", help="Host for SSE server")] = "127.0.0.1",
|
|
657
|
+
port: Annotated[int, typer.Option("--port", "-p", help="Port for SSE server")] = 8765,
|
|
658
|
+
) -> None:
|
|
659
|
+
"""Run the CodeGraph MCP server via stdio or SSE transport."""
|
|
660
|
+
_run_server(path, repository, profile, transport=transport, host=host, port=port)
|
|
613
661
|
|
|
614
662
|
|
|
615
663
|
mcp_app = typer.Typer(help="MCP server commands.")
|
|
@@ -621,14 +669,12 @@ def mcp_serve(
|
|
|
621
669
|
path: Annotated[Path | None, typer.Argument(help="Repository path (default: current directory)")] = None,
|
|
622
670
|
repository: Annotated[Path | None, typer.Option("--repository", "-r", "--repo", help="Repository path")] = None,
|
|
623
671
|
profile: Annotated[str, typer.Option("--profile", help="Tool profile: core | graph | minimal | developer | full")] = "full",
|
|
672
|
+
transport: Annotated[str, typer.Option("--transport", "-t", help="MCP transport: stdio | sse")] = "stdio",
|
|
673
|
+
host: Annotated[str, typer.Option("--host", help="Host for SSE server")] = "127.0.0.1",
|
|
674
|
+
port: Annotated[int, typer.Option("--port", "-p", help="Port for SSE server")] = 8765,
|
|
624
675
|
) -> None:
|
|
625
|
-
"""Run the
|
|
626
|
-
|
|
627
|
-
from codegraph.mcp import create_server
|
|
628
|
-
from codegraph.process_lifecycle import run_mcp_stdio_server
|
|
629
|
-
|
|
630
|
-
server = create_server(repo, profile=profile)
|
|
631
|
-
run_mcp_stdio_server(server, repo, profile=profile)
|
|
676
|
+
"""Run the CodeGraph MCP server via stdio or SSE transport."""
|
|
677
|
+
_run_server(path, repository, profile, transport=transport, host=host, port=port)
|
|
632
678
|
|
|
633
679
|
|
|
634
680
|
def _execute_stop(
|
|
@@ -594,6 +594,7 @@ def _get_context_impl(
|
|
|
594
594
|
if path:
|
|
595
595
|
c = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
|
|
596
596
|
c.row_factory = sqlite3.Row
|
|
597
|
+
c.execute("PRAGMA busy_timeout = 15000")
|
|
597
598
|
try:
|
|
598
599
|
for query in queries:
|
|
599
600
|
for item in search(
|
|
@@ -629,6 +630,7 @@ def _get_context_impl(
|
|
|
629
630
|
if path:
|
|
630
631
|
c = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
|
|
631
632
|
c.row_factory = sqlite3.Row
|
|
633
|
+
c.execute("PRAGMA busy_timeout = 15000")
|
|
632
634
|
try:
|
|
633
635
|
return c.execute(
|
|
634
636
|
"SELECT route_path, http_method, handler_name, file_path, line, endpoint_id FROM framework_routes"
|
|
@@ -665,6 +667,7 @@ def _get_context_impl(
|
|
|
665
667
|
if path:
|
|
666
668
|
c = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
|
|
667
669
|
c.row_factory = sqlite3.Row
|
|
670
|
+
c.execute("PRAGMA busy_timeout = 15000")
|
|
668
671
|
try:
|
|
669
672
|
archs.append(get_architecture(c, repo))
|
|
670
673
|
finally:
|
|
@@ -748,6 +748,8 @@ def get_db_schema(
|
|
|
748
748
|
schema: str | None = None,
|
|
749
749
|
*,
|
|
750
750
|
dialect: str | None = None,
|
|
751
|
+
limit: int | None = None,
|
|
752
|
+
offset: int = 0,
|
|
751
753
|
) -> dict[str, Any]:
|
|
752
754
|
"""Return the complete repository database schema overview with safe credential redaction."""
|
|
753
755
|
if isinstance(repo_or_dialect, str) and not dialect:
|
|
@@ -800,21 +802,42 @@ def get_db_schema(
|
|
|
800
802
|
|
|
801
803
|
dialects = sorted({t["dialect"] for t in tables if t.get("dialect")}) or ["UNKNOWN"]
|
|
802
804
|
|
|
803
|
-
|
|
805
|
+
safe_tables = tables
|
|
806
|
+
safe_models = models
|
|
807
|
+
safe_migrations = migrations
|
|
808
|
+
safe_cols = columns
|
|
809
|
+
safe_rels = rels
|
|
810
|
+
|
|
811
|
+
if limit is not None:
|
|
812
|
+
safe_offset = max(0, offset)
|
|
813
|
+
safe_limit = max(0, limit)
|
|
814
|
+
safe_tables = tables[safe_offset : safe_offset + safe_limit]
|
|
815
|
+
safe_models = models[safe_offset : safe_offset + safe_limit]
|
|
816
|
+
safe_migrations = migrations[safe_offset : safe_offset + safe_limit]
|
|
817
|
+
safe_cols = columns[: max(safe_limit * 5, 20)]
|
|
818
|
+
safe_rels = rels[: max(safe_limit * 5, 20)]
|
|
819
|
+
|
|
820
|
+
result_dict: dict[str, Any] = {
|
|
804
821
|
"status": "ok",
|
|
805
822
|
"dialects": dialects,
|
|
806
823
|
"table_count": len(tables),
|
|
807
824
|
"column_count": len(columns),
|
|
808
825
|
"model_count": len(models),
|
|
809
826
|
"migration_count": len(migrations),
|
|
810
|
-
"tables":
|
|
811
|
-
"columns":
|
|
812
|
-
"models":
|
|
813
|
-
"relationships":
|
|
814
|
-
"migrations":
|
|
827
|
+
"tables": safe_tables,
|
|
828
|
+
"columns": safe_cols,
|
|
829
|
+
"models": safe_models,
|
|
830
|
+
"relationships": safe_rels,
|
|
831
|
+
"migrations": safe_migrations,
|
|
815
832
|
"env_variables": env_vars,
|
|
816
833
|
"database_credentials": "REDACTED",
|
|
817
|
-
}
|
|
834
|
+
}
|
|
835
|
+
if limit is not None:
|
|
836
|
+
result_dict["limit"] = safe_limit
|
|
837
|
+
result_dict["offset"] = safe_offset
|
|
838
|
+
result_dict["has_more"] = (safe_offset + len(safe_tables)) < len(tables)
|
|
839
|
+
|
|
840
|
+
return redact_payload(result_dict)
|
|
818
841
|
|
|
819
842
|
|
|
820
843
|
def get_db_impact(
|
|
@@ -235,30 +235,68 @@ def check_freshness(
|
|
|
235
235
|
deleted: list[str] = []
|
|
236
236
|
parse_failed: list[str] = []
|
|
237
237
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
238
|
+
# Fast path 1: Git commit diff (branch switch or commit advance)
|
|
239
|
+
git_diff_handled = False
|
|
240
|
+
if cur_commit and idx_commit and cur_commit != idx_commit:
|
|
241
|
+
diff_out = _run_git(repository, "diff", "--name-status", idx_commit, cur_commit)
|
|
242
|
+
if diff_out is not None:
|
|
243
|
+
git_diff_handled = True
|
|
244
|
+
for line in diff_out.splitlines():
|
|
245
|
+
parts = line.strip().split(maxsplit=1)
|
|
246
|
+
if len(parts) == 2:
|
|
247
|
+
action, fpath = parts[0], parts[1]
|
|
248
|
+
if action.startswith("D"):
|
|
249
|
+
deleted.append(fpath)
|
|
250
|
+
else:
|
|
251
|
+
modified.append(fpath)
|
|
252
|
+
|
|
253
|
+
# Fast path 2: Git status when HEAD commit is unchanged
|
|
254
|
+
if not git_diff_handled and cur_commit and idx_commit and cur_commit == idx_commit:
|
|
255
|
+
status_out = _run_git(repository, "status", "--porcelain", "--untracked-files=no")
|
|
256
|
+
if status_out is not None and not status_out.strip():
|
|
257
|
+
# Working tree has zero tracked changes against HEAD
|
|
258
|
+
git_diff_handled = True
|
|
253
259
|
try:
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
+
pf_rows = con.execute("SELECT path FROM files WHERE status='parse_failed'").fetchall()
|
|
261
|
+
for r in pf_rows:
|
|
262
|
+
parse_failed.append(str(r[0]))
|
|
263
|
+
modified.append(str(r[0]))
|
|
264
|
+
except sqlite3.OperationalError:
|
|
265
|
+
pass
|
|
266
|
+
|
|
267
|
+
if not git_diff_handled:
|
|
268
|
+
try:
|
|
269
|
+
rows = con.execute("SELECT path, hash, status, indexed_at FROM files").fetchall()
|
|
270
|
+
except sqlite3.OperationalError:
|
|
271
|
+
try:
|
|
272
|
+
rows = con.execute("SELECT path, hash, status, 0 AS indexed_at FROM files").fetchall()
|
|
273
|
+
except sqlite3.OperationalError:
|
|
274
|
+
rows = con.execute("SELECT path, hash, 'ok' AS status, 0 AS indexed_at FROM files").fetchall()
|
|
275
|
+
|
|
276
|
+
for row in rows:
|
|
277
|
+
rel = str(row["path"])
|
|
278
|
+
if row["status"] == "parse_failed":
|
|
279
|
+
parse_failed.append(rel)
|
|
260
280
|
if rel not in modified:
|
|
261
281
|
modified.append(rel)
|
|
282
|
+
abs_path = repository / rel
|
|
283
|
+
if not abs_path.exists():
|
|
284
|
+
deleted.append(rel)
|
|
285
|
+
else:
|
|
286
|
+
try:
|
|
287
|
+
st = abs_path.stat()
|
|
288
|
+
# Mtime check: skip reading & hashing files strictly older than indexing time
|
|
289
|
+
idx_at = int(row["indexed_at"] or 0)
|
|
290
|
+
if idx_at > 0 and int(st.st_mtime) < idx_at and row["status"] != "parse_failed":
|
|
291
|
+
continue
|
|
292
|
+
digest = hashlib.sha256(
|
|
293
|
+
abs_path.read_text(encoding="utf-8", errors="replace").encode()
|
|
294
|
+
).hexdigest()
|
|
295
|
+
if digest != row["hash"] and rel not in modified:
|
|
296
|
+
modified.append(rel)
|
|
297
|
+
except OSError:
|
|
298
|
+
if rel not in modified:
|
|
299
|
+
modified.append(rel)
|
|
262
300
|
|
|
263
301
|
changed = len(modified) + len(deleted)
|
|
264
302
|
if changed == 0 and not parse_failed and (idx_commit == cur_commit or cur_commit is None):
|
|
@@ -493,8 +493,11 @@ class Indexer:
|
|
|
493
493
|
con = sqlite3.connect(self.db_path)
|
|
494
494
|
con.row_factory = make_compat_row
|
|
495
495
|
con.execute("PRAGMA journal_mode = WAL")
|
|
496
|
+
con.execute("PRAGMA synchronous = NORMAL")
|
|
496
497
|
con.execute("PRAGMA foreign_keys = ON")
|
|
497
|
-
con.execute("PRAGMA busy_timeout =
|
|
498
|
+
con.execute("PRAGMA busy_timeout = 15000")
|
|
499
|
+
con.execute("PRAGMA cache_size = -64000")
|
|
500
|
+
con.execute("PRAGMA temp_store = MEMORY")
|
|
498
501
|
self._ensure_schema(con)
|
|
499
502
|
return con
|
|
500
503
|
|
|
@@ -1979,6 +1979,8 @@ def list_routes(
|
|
|
1979
1979
|
framework: str | None = None,
|
|
1980
1980
|
method: str | None = None,
|
|
1981
1981
|
path: str | None = None,
|
|
1982
|
+
limit: int | None = None,
|
|
1983
|
+
offset: int = 0,
|
|
1982
1984
|
) -> dict[str, Any]:
|
|
1983
1985
|
"""Expose application routes discovered from the repository."""
|
|
1984
1986
|
unindexed = check_index_available(con, repository)
|
|
@@ -2028,10 +2030,27 @@ def list_routes(
|
|
|
2028
2030
|
for r in rows
|
|
2029
2031
|
]
|
|
2030
2032
|
|
|
2033
|
+
total_count = len(routes)
|
|
2034
|
+
if limit is not None:
|
|
2035
|
+
safe_offset = max(0, offset)
|
|
2036
|
+
safe_limit = max(0, limit)
|
|
2037
|
+
paginated_routes = routes[safe_offset : safe_offset + safe_limit]
|
|
2038
|
+
return {
|
|
2039
|
+
"status": "ok",
|
|
2040
|
+
**meta,
|
|
2041
|
+
"count": len(paginated_routes),
|
|
2042
|
+
"total_count": total_count,
|
|
2043
|
+
"limit": safe_limit,
|
|
2044
|
+
"offset": safe_offset,
|
|
2045
|
+
"has_more": (safe_offset + len(paginated_routes)) < total_count,
|
|
2046
|
+
"routes": paginated_routes,
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2031
2049
|
return {
|
|
2032
2050
|
"status": "ok",
|
|
2033
2051
|
**meta,
|
|
2034
2052
|
"count": len(routes),
|
|
2053
|
+
"total_count": total_count,
|
|
2035
2054
|
"routes": routes,
|
|
2036
2055
|
}
|
|
2037
2056
|
|
|
@@ -173,6 +173,8 @@ def create_server(
|
|
|
173
173
|
repository: Path,
|
|
174
174
|
settings: Settings | None = None,
|
|
175
175
|
profile: str = "full",
|
|
176
|
+
host: str = "127.0.0.1",
|
|
177
|
+
port: int = 8765,
|
|
176
178
|
) -> Any:
|
|
177
179
|
"""Build an MCP FastMCP server lazily so normal CLI use needs no MCP dependency."""
|
|
178
180
|
try:
|
|
@@ -184,7 +186,12 @@ def create_server(
|
|
|
184
186
|
|
|
185
187
|
indexer = Indexer(repository, settings)
|
|
186
188
|
memory = MemoryStore(indexer.db_path)
|
|
187
|
-
app = FastMCP(
|
|
189
|
+
app = FastMCP(
|
|
190
|
+
"CodeGraph MCP",
|
|
191
|
+
instructions=render_agent_rules("antigravity"),
|
|
192
|
+
host=host,
|
|
193
|
+
port=port,
|
|
194
|
+
)
|
|
188
195
|
max_read_bytes = indexer.settings.max_read_bytes
|
|
189
196
|
|
|
190
197
|
# -----------------------------------------------------------------------
|