codemesh 0.1.1__py3-none-any.whl

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.
Files changed (52) hide show
  1. codemesh/__init__.py +5 -0
  2. codemesh/__main__.py +8 -0
  3. codemesh/cli/__init__.py +3 -0
  4. codemesh/cli/init.py +208 -0
  5. codemesh/cli/install_cmd.py +208 -0
  6. codemesh/cli/main.py +469 -0
  7. codemesh/context/__init__.py +3 -0
  8. codemesh/context/builder.py +388 -0
  9. codemesh/db/__init__.py +3 -0
  10. codemesh/db/connection.py +66 -0
  11. codemesh/db/queries.py +696 -0
  12. codemesh/db/schema.py +125 -0
  13. codemesh/embedding/__init__.py +3 -0
  14. codemesh/extraction/__init__.py +7 -0
  15. codemesh/extraction/languages/__init__.py +95 -0
  16. codemesh/extraction/languages/c_family.py +614 -0
  17. codemesh/extraction/languages/go.py +397 -0
  18. codemesh/extraction/languages/java.py +603 -0
  19. codemesh/extraction/languages/python.py +718 -0
  20. codemesh/extraction/languages/rust.py +435 -0
  21. codemesh/extraction/languages/swift.py +464 -0
  22. codemesh/extraction/languages/typescript.py +1222 -0
  23. codemesh/extraction/orchestrator.py +218 -0
  24. codemesh/graph/__init__.py +8 -0
  25. codemesh/graph/query_manager.py +117 -0
  26. codemesh/graph/traverser.py +107 -0
  27. codemesh/indexer.py +240 -0
  28. codemesh/mcp/__init__.py +3 -0
  29. codemesh/mcp/server.py +60 -0
  30. codemesh/mcp/tools.py +605 -0
  31. codemesh/querier.py +269 -0
  32. codemesh/resolution/__init__.py +7 -0
  33. codemesh/resolution/frameworks/__init__.py +15 -0
  34. codemesh/resolution/frameworks/django.py +30 -0
  35. codemesh/resolution/frameworks/fastapi.py +23 -0
  36. codemesh/resolution/import_resolver.py +69 -0
  37. codemesh/resolution/name_matcher.py +30 -0
  38. codemesh/resolution/resolver.py +268 -0
  39. codemesh/retrieval/__init__.py +7 -0
  40. codemesh/search/__init__.py +3 -0
  41. codemesh/sync/__init__.py +3 -0
  42. codemesh/sync/watcher.py +135 -0
  43. codemesh/types.py +148 -0
  44. codemesh/viz/__init__.py +0 -0
  45. codemesh/viz/graph_builder.py +162 -0
  46. codemesh/viz/server.py +122 -0
  47. codemesh/viz/templates/index.html +359 -0
  48. codemesh-0.1.1.dist-info/METADATA +337 -0
  49. codemesh-0.1.1.dist-info/RECORD +52 -0
  50. codemesh-0.1.1.dist-info/WHEEL +4 -0
  51. codemesh-0.1.1.dist-info/entry_points.txt +2 -0
  52. codemesh-0.1.1.dist-info/licenses/LICENSE +21 -0
codemesh/db/schema.py ADDED
@@ -0,0 +1,125 @@
1
+ """Database schema definitions and migration support."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from codemesh.db.connection import get_connection
8
+
9
+ SCHEMA_SQL = """
10
+ -- Nodes table: code symbols
11
+ CREATE TABLE IF NOT EXISTS nodes (
12
+ id TEXT PRIMARY KEY,
13
+ kind TEXT NOT NULL,
14
+ name TEXT NOT NULL,
15
+ qualified_name TEXT NOT NULL,
16
+ file_path TEXT NOT NULL,
17
+ language TEXT NOT NULL,
18
+ start_line INTEGER NOT NULL,
19
+ end_line INTEGER NOT NULL,
20
+ start_column INTEGER DEFAULT 0,
21
+ end_column INTEGER DEFAULT 0,
22
+ docstring TEXT DEFAULT '',
23
+ signature TEXT DEFAULT '',
24
+ visibility TEXT DEFAULT 'public',
25
+ parent_id TEXT,
26
+ metadata TEXT DEFAULT '{}',
27
+ is_exported INTEGER DEFAULT 0,
28
+ is_async INTEGER DEFAULT 0,
29
+ is_static INTEGER DEFAULT 0,
30
+ is_abstract INTEGER DEFAULT 0,
31
+ content_hash TEXT DEFAULT '',
32
+ created_at INTEGER DEFAULT (unixepoch())
33
+ );
34
+
35
+ -- Edges table: relationships between symbols
36
+ CREATE TABLE IF NOT EXISTS edges (
37
+ id TEXT PRIMARY KEY,
38
+ source_id TEXT NOT NULL,
39
+ target_id TEXT NOT NULL,
40
+ kind TEXT NOT NULL,
41
+ confidence REAL DEFAULT 1.0,
42
+ weight_source TEXT DEFAULT 'ast',
43
+ line INTEGER DEFAULT 0,
44
+ column INTEGER DEFAULT 0,
45
+ metadata TEXT DEFAULT '{}',
46
+ resolved_target TEXT DEFAULT '',
47
+ type_context TEXT DEFAULT '',
48
+ created_at INTEGER DEFAULT (unixepoch())
49
+ );
50
+
51
+ -- File-to-node dependency mapping for delta indexing
52
+ CREATE TABLE IF NOT EXISTS file_node_deps (
53
+ file_path TEXT NOT NULL,
54
+ node_id TEXT NOT NULL,
55
+ PRIMARY KEY (file_path, node_id)
56
+ );
57
+
58
+ -- Full-text search virtual table (BM25 via FTS5)
59
+ -- Column weights: id=0, name=20, qualified_name=5, docstring=1, signature=2
60
+ -- Heavy name weight ensures exact/prefix name matches rank above incidental
61
+ -- mentions in long docstrings or qualified names of nested symbols.
62
+ CREATE VIRTUAL TABLE IF NOT EXISTS nodes_fts USING fts5(
63
+ id,
64
+ name,
65
+ qualified_name,
66
+ docstring,
67
+ signature,
68
+ content='nodes',
69
+ content_rowid='rowid'
70
+ );
71
+
72
+ -- Query log for analytics
73
+ CREATE TABLE IF NOT EXISTS query_log (
74
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
75
+ query_text TEXT NOT NULL,
76
+ retrieved_nodes TEXT NOT NULL,
77
+ created_at INTEGER NOT NULL DEFAULT (unixepoch())
78
+ );
79
+
80
+ -- Indexes
81
+ CREATE INDEX IF NOT EXISTS idx_nodes_kind ON nodes(kind);
82
+ CREATE INDEX IF NOT EXISTS idx_nodes_file ON nodes(file_path);
83
+ CREATE INDEX IF NOT EXISTS idx_nodes_language ON nodes(language);
84
+ CREATE INDEX IF NOT EXISTS idx_nodes_qualified ON nodes(qualified_name);
85
+ CREATE INDEX IF NOT EXISTS idx_nodes_lower_name ON nodes(lower(name));
86
+ CREATE INDEX IF NOT EXISTS idx_edges_source ON edges(source_id);
87
+ CREATE INDEX IF NOT EXISTS idx_edges_target ON edges(target_id);
88
+ CREATE INDEX IF NOT EXISTS idx_edges_kind ON edges(kind);
89
+ CREATE INDEX IF NOT EXISTS idx_edges_confidence ON edges(confidence);
90
+ CREATE INDEX IF NOT EXISTS idx_edges_dataflow ON edges(kind, source_id) WHERE kind IN ('data_flow', 'reads', 'writes');
91
+ CREATE INDEX IF NOT EXISTS idx_edges_resolved ON edges(resolved_target) WHERE resolved_target != '';
92
+ CREATE INDEX IF NOT EXISTS idx_nodes_content_hash ON nodes(content_hash) WHERE content_hash != '';
93
+ CREATE INDEX IF NOT EXISTS idx_fnd_node ON file_node_deps(node_id);
94
+
95
+ -- FTS5 triggers to keep index in sync
96
+ CREATE TRIGGER IF NOT EXISTS nodes_ai AFTER INSERT ON nodes BEGIN
97
+ INSERT INTO nodes_fts(rowid, id, name, qualified_name, docstring, signature)
98
+ VALUES (NEW.rowid, NEW.id, NEW.name, NEW.qualified_name, NEW.docstring, NEW.signature);
99
+ END;
100
+
101
+ CREATE TRIGGER IF NOT EXISTS nodes_ad AFTER DELETE ON nodes BEGIN
102
+ INSERT INTO nodes_fts(nodes_fts, rowid, id, name, qualified_name, docstring, signature)
103
+ VALUES ('delete', OLD.rowid, OLD.id, OLD.name, OLD.qualified_name, OLD.docstring, OLD.signature);
104
+ END;
105
+
106
+ CREATE TRIGGER IF NOT EXISTS nodes_au AFTER UPDATE ON nodes BEGIN
107
+ INSERT INTO nodes_fts(nodes_fts, rowid, id, name, qualified_name, docstring, signature)
108
+ VALUES ('delete', OLD.rowid, OLD.id, OLD.name, OLD.qualified_name, OLD.docstring, OLD.signature);
109
+ INSERT INTO nodes_fts(rowid, id, name, qualified_name, docstring, signature)
110
+ VALUES (NEW.rowid, NEW.id, NEW.name, NEW.qualified_name, NEW.docstring, NEW.signature);
111
+ END;
112
+ """
113
+
114
+
115
+ def init_db(db_path: Path | None = None) -> None:
116
+ """Initialize the database schema."""
117
+ if db_path is None:
118
+ db_path = Path.cwd() / ".codemesh" / "index.db"
119
+ with get_connection(db_path) as conn:
120
+ conn.executescript(SCHEMA_SQL)
121
+
122
+
123
+ def migrate_db(db_path: Path | None = None) -> None:
124
+ """Run any pending migrations."""
125
+ init_db(db_path)
@@ -0,0 +1,3 @@
1
+ """Code embedding generation."""
2
+
3
+ from __future__ import annotations
@@ -0,0 +1,7 @@
1
+ """Code extraction layer: tree-sitter AST parsing into knowledge graph."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from codemesh.extraction.orchestrator import ExtractionOrchestrator
6
+
7
+ __all__ = ["ExtractionOrchestrator"]
@@ -0,0 +1,95 @@
1
+ """Language-specific tree-sitter extractors."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path # noqa: TC003
6
+ from typing import Protocol
7
+
8
+ from codemesh.types import Edge, Language, Node
9
+
10
+
11
+ class LanguageExtractor(Protocol):
12
+ """Protocol for language-specific extractors."""
13
+
14
+ def extract(
15
+ self,
16
+ file_path: Path,
17
+ source: bytes,
18
+ root_node: object,
19
+ language: Language,
20
+ ) -> tuple[list[Node], list[Edge]]: ...
21
+
22
+
23
+ _EXTRACTORS: dict[Language, LanguageExtractor] = {}
24
+
25
+
26
+ def register_extractor(language: Language, extractor: LanguageExtractor) -> None:
27
+ """Register a language extractor."""
28
+ _EXTRACTORS[language] = extractor
29
+
30
+
31
+ def get_extractor(language: Language) -> LanguageExtractor | None:
32
+ """Get the extractor for a language."""
33
+ return _EXTRACTORS.get(language)
34
+
35
+
36
+ # Import and register all extractors
37
+ def _register_all() -> None:
38
+ """Register all available extractors."""
39
+ try:
40
+ from codemesh.extraction.languages.python import PythonExtractor
41
+
42
+ register_extractor(Language.PYTHON, PythonExtractor())
43
+ except ImportError:
44
+ pass
45
+
46
+ try:
47
+ from codemesh.extraction.languages.typescript import TypeScriptExtractor
48
+
49
+ ts_extractor = TypeScriptExtractor()
50
+ register_extractor(Language.TYPESCRIPT, ts_extractor)
51
+ register_extractor(Language.JAVASCRIPT, ts_extractor)
52
+ except ImportError:
53
+ pass
54
+
55
+ try:
56
+ from codemesh.extraction.languages.rust import RustExtractor
57
+
58
+ register_extractor(Language.RUST, RustExtractor())
59
+ except ImportError:
60
+ pass
61
+
62
+ try:
63
+ from codemesh.extraction.languages.swift import SwiftExtractor
64
+
65
+ register_extractor(Language.SWIFT, SwiftExtractor())
66
+ except ImportError:
67
+ pass
68
+
69
+ try:
70
+ from codemesh.extraction.languages.go import GoExtractor
71
+
72
+ register_extractor(Language.GO, GoExtractor())
73
+ except ImportError:
74
+ pass
75
+
76
+ try:
77
+ from codemesh.extraction.languages.java import JavaExtractor
78
+
79
+ java_extractor = JavaExtractor()
80
+ register_extractor(Language.JAVA, java_extractor)
81
+ register_extractor(Language.KOTLIN, java_extractor)
82
+ except ImportError:
83
+ pass
84
+
85
+ try:
86
+ from codemesh.extraction.languages.c_family import CFamilyExtractor
87
+
88
+ c_family_extractor = CFamilyExtractor()
89
+ register_extractor(Language.C, c_family_extractor)
90
+ register_extractor(Language.CPP, c_family_extractor)
91
+ except ImportError:
92
+ pass
93
+
94
+
95
+ _register_all()