mnemo-dev 0.4.0__tar.gz → 0.5.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.
- mnemo_dev-0.5.0/PKG-INFO +281 -0
- mnemo_dev-0.5.0/README.md +231 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/__init__.py +1 -1
- mnemo_dev-0.5.0/mnemo/api_discovery/__init__.py +133 -0
- mnemo_dev-0.5.0/mnemo/breaking/__init__.py +120 -0
- mnemo_dev-0.5.0/mnemo/chunking.py +36 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/cli.py +87 -18
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/config.py +3 -1
- mnemo_dev-0.5.0/mnemo/conventions/__init__.py +155 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/corrections/__init__.py +19 -0
- mnemo_dev-0.5.0/mnemo/dead_code/__init__.py +66 -0
- mnemo_dev-0.5.0/mnemo/doctor.py +94 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/drift/__init__.py +62 -78
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/embeddings/__init__.py +3 -1
- mnemo_dev-0.5.0/mnemo/embeddings/dense.py +86 -0
- mnemo_dev-0.5.0/mnemo/engine/__init__.py +1 -0
- mnemo_dev-0.5.0/mnemo/engine/cache.py +58 -0
- mnemo_dev-0.5.0/mnemo/engine/clustering.py +211 -0
- mnemo_dev-0.5.0/mnemo/engine/db.py +49 -0
- mnemo_dev-0.5.0/mnemo/engine/freshness.py +181 -0
- mnemo_dev-0.5.0/mnemo/engine/memory_graph.py +389 -0
- mnemo_dev-0.5.0/mnemo/engine/pipeline.py +554 -0
- mnemo_dev-0.5.0/mnemo/engine/schema.py +49 -0
- mnemo_dev-0.5.0/mnemo/engine/scope.py +191 -0
- mnemo_dev-0.5.0/mnemo/engine/workers.py +71 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/enrichment.py +46 -9
- mnemo_dev-0.5.0/mnemo/health/__init__.py +146 -0
- mnemo_dev-0.5.0/mnemo/hooks/__init__.py +686 -0
- mnemo_dev-0.5.0/mnemo/hooks/extractor.py +31 -0
- mnemo_dev-0.5.0/mnemo/init.py +235 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/mcp_server.py +11 -2
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/_shared.py +1 -1
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/hierarchy.py +1 -1
- mnemo_dev-0.5.0/mnemo/memory/indexing.py +28 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/lessons.py +2 -2
- mnemo_dev-0.5.0/mnemo/memory/linking.py +36 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/retention.py +60 -4
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/search.py +254 -140
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/services.py +36 -1
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/slots.py +29 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/store.py +30 -20
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/onboarding/__init__.py +3 -5
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/plan/__init__.py +39 -17
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/prompts/__init__.py +12 -18
- mnemo_dev-0.5.0/mnemo/repo_map/__init__.py +13 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/repo_map/identity.py +26 -34
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/repo_map/parsers.py +24 -3
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/repo_map/scanner.py +26 -3
- mnemo_dev-0.5.0/mnemo/retrieval.py +101 -0
- mnemo_dev-0.5.0/mnemo/security/__init__.py +119 -0
- mnemo_dev-0.5.0/mnemo/serve.py +435 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/team_graph/__init__.py +0 -1
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/test_intel/__init__.py +0 -1
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tool_registry.py +31 -12
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/__init__.py +1 -0
- mnemo_dev-0.5.0/mnemo/tools/code.py +142 -0
- mnemo_dev-0.5.0/mnemo/tools/engine.py +300 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/git.py +15 -0
- mnemo_dev-0.5.0/mnemo/tools/graph.py +66 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/memory.py +18 -3
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/meta.py +2 -2
- mnemo_dev-0.5.0/mnemo/tools/plan.py +123 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/safety.py +38 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/search.py +55 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/team.py +111 -63
- mnemo_dev-0.5.0/mnemo/types.py +49 -0
- mnemo_dev-0.5.0/mnemo/utils/__init__.py +39 -0
- mnemo_dev-0.5.0/mnemo/utils/observations.py +127 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/workspace/__init__.py +0 -1
- mnemo_dev-0.5.0/mnemo_dev.egg-info/PKG-INFO +281 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo_dev.egg-info/SOURCES.txt +24 -20
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo_dev.egg-info/requires.txt +4 -3
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/pyproject.toml +5 -4
- mnemo_dev-0.5.0/tests/test_code_quality_tools.py +101 -0
- mnemo_dev-0.5.0/tests/test_engine_db.py +62 -0
- mnemo_dev-0.5.0/tests/test_engine_pipeline.py +140 -0
- mnemo_dev-0.5.0/tests/test_enrichment.py +39 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_export.py +1 -1
- mnemo_dev-0.5.0/tests/test_full_cycle.py +78 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_init.py +2 -4
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_mcp_integration.py +1 -1
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_memory.py +1 -3
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_plan_features.py +1 -1
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_search_quality.py +3 -3
- mnemo_dev-0.5.0/tests/test_self_maintenance.py +135 -0
- mnemo_dev-0.5.0/tests/test_serve.py +88 -0
- mnemo_dev-0.5.0/tests/test_tool_routing.py +232 -0
- mnemo_dev-0.4.0/PKG-INFO +0 -606
- mnemo_dev-0.4.0/README.md +0 -558
- mnemo_dev-0.4.0/mnemo/api.py +0 -58
- mnemo_dev-0.4.0/mnemo/api_discovery/__init__.py +0 -248
- mnemo_dev-0.4.0/mnemo/breaking/__init__.py +0 -163
- mnemo_dev-0.4.0/mnemo/chunking.py +0 -158
- mnemo_dev-0.4.0/mnemo/conventions/__init__.py +0 -229
- mnemo_dev-0.4.0/mnemo/dead_code/__init__.py +0 -118
- mnemo_dev-0.4.0/mnemo/dependency_graph/__init__.py +0 -126
- mnemo_dev-0.4.0/mnemo/doctor.py +0 -122
- mnemo_dev-0.4.0/mnemo/graph/__init__.py +0 -46
- mnemo_dev-0.4.0/mnemo/graph/builder.py +0 -278
- mnemo_dev-0.4.0/mnemo/graph/local.py +0 -192
- mnemo_dev-0.4.0/mnemo/graph/query.py +0 -221
- mnemo_dev-0.4.0/mnemo/graph/relationships.py +0 -131
- mnemo_dev-0.4.0/mnemo/graph/workspace.py +0 -124
- mnemo_dev-0.4.0/mnemo/health/__init__.py +0 -209
- mnemo_dev-0.4.0/mnemo/hooks/__init__.py +0 -401
- mnemo_dev-0.4.0/mnemo/init.py +0 -131
- mnemo_dev-0.4.0/mnemo/intelligence/__init__.py +0 -401
- mnemo_dev-0.4.0/mnemo/memory/indexing.py +0 -36
- mnemo_dev-0.4.0/mnemo/memory/linking.py +0 -29
- mnemo_dev-0.4.0/mnemo/middleware.py +0 -42
- mnemo_dev-0.4.0/mnemo/repo_map/__init__.py +0 -42
- mnemo_dev-0.4.0/mnemo/repo_map/generator.py +0 -161
- mnemo_dev-0.4.0/mnemo/retrieval.py +0 -34
- mnemo_dev-0.4.0/mnemo/security/__init__.py +0 -180
- mnemo_dev-0.4.0/mnemo/sqlite_adapter.py +0 -204
- mnemo_dev-0.4.0/mnemo/tools/code.py +0 -56
- mnemo_dev-0.4.0/mnemo/tools/graph.py +0 -36
- mnemo_dev-0.4.0/mnemo/tools/plan.py +0 -24
- mnemo_dev-0.4.0/mnemo/ui/__init__.py +0 -306
- mnemo_dev-0.4.0/mnemo/utils/__init__.py +0 -26
- mnemo_dev-0.4.0/mnemo/utils/observations.py +0 -51
- mnemo_dev-0.4.0/mnemo/vector_index/__init__.py +0 -210
- mnemo_dev-0.4.0/mnemo_dev.egg-info/PKG-INFO +0 -606
- mnemo_dev-0.4.0/tests/test_chunking_semantic.py +0 -33
- mnemo_dev-0.4.0/tests/test_doctor.py +0 -44
- mnemo_dev-0.4.0/tests/test_intelligence_advanced.py +0 -31
- mnemo_dev-0.4.0/tests/test_mcp_semantic_tools.py +0 -19
- mnemo_dev-0.4.0/tests/test_repo_map_storage.py +0 -14
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/LICENSE +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/analyzers/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/clients.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/code_review/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/commit_gen/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/commit_gen/mining.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/errors/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/incidents/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/knowledge/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/episodes.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/memory/temporal.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/persistence/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/persistence/export.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/persistence/snapshot.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/pr_gen/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/regressions/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/sprint/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/storage.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/tools/observe.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/audit.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/circuit_breaker.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/dedup.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/logger.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/metrics.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/privacy.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/stemmer.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/utils/synonyms.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo/velocity/__init__.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo_dev.egg-info/dependency_links.txt +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo_dev.egg-info/entry_points.txt +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/mnemo_dev.egg-info/top_level.txt +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/setup.cfg +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_audit.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_circuit_breaker.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_clients.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_memory_lifecycle.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_metrics.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_privacy.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_secondary_collections.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_slots.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_snapshot.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_stemmer.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_storage.py +0 -0
- {mnemo_dev-0.4.0 → mnemo_dev-0.5.0}/tests/test_synonyms.py +0 -0
mnemo_dev-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mnemo-dev
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Persistent memory and repo map for AI coding assistants
|
|
5
|
+
Author: Mnemo Contributors
|
|
6
|
+
License: AGPL-3.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/Mnemo-mcp/Mnemo
|
|
8
|
+
Project-URL: Repository, https://github.com/Mnemo-mcp/Mnemo
|
|
9
|
+
Project-URL: Issues, https://github.com/Mnemo-mcp/Mnemo/issues
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: click>=8.1
|
|
21
|
+
Requires-Dist: tree-sitter>=0.21
|
|
22
|
+
Requires-Dist: tree-sitter-python>=0.21
|
|
23
|
+
Requires-Dist: tree-sitter-javascript>=0.21
|
|
24
|
+
Requires-Dist: tree-sitter-typescript>=0.21
|
|
25
|
+
Requires-Dist: tree-sitter-c-sharp>=0.21
|
|
26
|
+
Requires-Dist: tree-sitter-go>=0.21
|
|
27
|
+
Requires-Dist: tree-sitter-java>=0.21
|
|
28
|
+
Requires-Dist: tree-sitter-rust>=0.21
|
|
29
|
+
Requires-Dist: gitpython>=3.1
|
|
30
|
+
Requires-Dist: pyyaml>=6.0
|
|
31
|
+
Requires-Dist: networkx>=3.0
|
|
32
|
+
Requires-Dist: onnxruntime>=1.17
|
|
33
|
+
Requires-Dist: tokenizers>=0.15
|
|
34
|
+
Requires-Dist: numpy>=1.24
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
38
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
39
|
+
Provides-Extra: binary
|
|
40
|
+
Requires-Dist: pyinstaller>=6.0; extra == "binary"
|
|
41
|
+
Provides-Extra: all-languages
|
|
42
|
+
Requires-Dist: tree-sitter-ruby>=0.21; extra == "all-languages"
|
|
43
|
+
Requires-Dist: tree-sitter-php>=0.22; extra == "all-languages"
|
|
44
|
+
Requires-Dist: tree-sitter-c>=0.21; extra == "all-languages"
|
|
45
|
+
Requires-Dist: tree-sitter-cpp>=0.21; extra == "all-languages"
|
|
46
|
+
Requires-Dist: tree-sitter-kotlin>=0.21; extra == "all-languages"
|
|
47
|
+
Requires-Dist: tree-sitter-swift>=0.21; extra == "all-languages"
|
|
48
|
+
Requires-Dist: tree-sitter-scala>=0.21; extra == "all-languages"
|
|
49
|
+
Dynamic: license-file
|
|
50
|
+
|
|
51
|
+
# Mnemo
|
|
52
|
+
|
|
53
|
+
**Persistent engineering cognition for AI coding agents.**
|
|
54
|
+
|
|
55
|
+
[](https://pypi.org/project/mnemo-dev/)
|
|
56
|
+
[]()
|
|
57
|
+
[](LICENSE)
|
|
58
|
+
|
|
59
|
+
One command gives your AI agent accumulated engineering understanding across sessions — architecture intelligence, semantic search, code graph, and institutional memory.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install mnemo-dev
|
|
63
|
+
mnemo init
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Your agent now remembers decisions, understands code relationships, and never asks the same question twice.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Why Mnemo
|
|
71
|
+
|
|
72
|
+
| Without Mnemo | With Mnemo |
|
|
73
|
+
|---------------|-----------|
|
|
74
|
+
| Re-explain your stack every session | Agent already knows your architecture |
|
|
75
|
+
| Agent breaks call chains it can't see | Full dependency graph with impact analysis |
|
|
76
|
+
| "What caching do we use?" → agent greps | Semantic search finds "Redis for sessions" instantly |
|
|
77
|
+
| Decisions lost between sessions | Permanent decisions survive forever |
|
|
78
|
+
| Context window wasted on repetition | ~500 tokens of targeted recall per session |
|
|
79
|
+
|
|
80
|
+
## Benchmarks
|
|
81
|
+
|
|
82
|
+
| Metric | Mnemo | Built-in (CLAUDE.md) |
|
|
83
|
+
|--------|-------|---------------------|
|
|
84
|
+
| **Search R@5** | **100%** | N/A (grep) |
|
|
85
|
+
| **Search latency** | **2ms** | — |
|
|
86
|
+
| **RAM** | **265 MB** | 0 |
|
|
87
|
+
| **Store 1 memory** | **5ms** | manual edit |
|
|
88
|
+
| **Token cost/session** | ~500 | 22,000+ (full file) |
|
|
89
|
+
| **Cross-session persistence** | ✅ | ❌ (resets) |
|
|
90
|
+
|
|
91
|
+
> Search uses ONNX all-MiniLM-L6-v2 dense embeddings + BM25 keyword + knowledge graph traversal, fused with Reciprocal Rank Fusion.
|
|
92
|
+
|
|
93
|
+
## Quick Start
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Install
|
|
97
|
+
pip install mnemo-dev
|
|
98
|
+
|
|
99
|
+
# Initialize in your repo
|
|
100
|
+
cd your-project
|
|
101
|
+
mnemo init --client kiro # or: cursor, claude-code, amazonq, copilot, generic
|
|
102
|
+
|
|
103
|
+
# That's it. Your agent now has persistent memory.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### What `mnemo init` does:
|
|
107
|
+
1. Scans your codebase (tree-sitter + Roslyn for C#)
|
|
108
|
+
2. Builds a knowledge graph (classes, methods, calls, communities)
|
|
109
|
+
3. Installs lifecycle hooks (auto-capture learnings, inject context)
|
|
110
|
+
4. Configures MCP server for your AI client
|
|
111
|
+
5. Downloads embedding model (~86MB, one-time)
|
|
112
|
+
|
|
113
|
+
### Verify it works:
|
|
114
|
+
```bash
|
|
115
|
+
mnemo recall # See what the agent will know
|
|
116
|
+
mnemo serve # Open dashboard at localhost:3333
|
|
117
|
+
mnemo doctor # Diagnose any issues
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## How It Works
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Session Start (agent-spawn hook)
|
|
126
|
+
→ mnemo_recall injects: decisions + memories + active task + repo map
|
|
127
|
+
→ Agent starts with full context (~500 tokens)
|
|
128
|
+
|
|
129
|
+
User asks a question (user-prompt-submit hook)
|
|
130
|
+
→ Semantic search finds relevant memories
|
|
131
|
+
→ Injected as <mnemo-relevant-context>
|
|
132
|
+
|
|
133
|
+
Agent works (tools available via MCP)
|
|
134
|
+
→ mnemo_lookup: class details, methods, signatures
|
|
135
|
+
→ mnemo_graph: neighbors, communities, impact analysis
|
|
136
|
+
→ mnemo_search: find code by meaning
|
|
137
|
+
→ mnemo_remember: store important context
|
|
138
|
+
→ mnemo_decide: record permanent decisions
|
|
139
|
+
|
|
140
|
+
Session ends (stop hook)
|
|
141
|
+
→ Auto-captures learnings, decisions, session summary
|
|
142
|
+
→ Memories decay over time (hot → warm → cold → evicted)
|
|
143
|
+
→ Contradictions detected and superseded
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Features
|
|
147
|
+
|
|
148
|
+
### 🧠 Memory System
|
|
149
|
+
- **Categorized storage**: architecture, pattern, bug, preference, decision
|
|
150
|
+
- **Retention scoring**: access frequency × recency × importance
|
|
151
|
+
- **Branch-aware**: memories tagged with git branch, filtered on recall
|
|
152
|
+
- **Contradiction detection**: new facts supersede old conflicting ones
|
|
153
|
+
- **Token-budgeted recall**: never exceeds ~2000 tokens regardless of memory count
|
|
154
|
+
- **Memory slots**: pinned context (project_context, user_preferences, known_gotchas)
|
|
155
|
+
|
|
156
|
+
### 🔍 Triple-Stream Search
|
|
157
|
+
- **BM25**: stemmed keyword matching with synonym expansion
|
|
158
|
+
- **Vector**: ONNX all-MiniLM-L6-v2 dense embeddings (384-dim, cosine similarity)
|
|
159
|
+
- **Graph**: Dijkstra traversal from code symbols to linked memories
|
|
160
|
+
- **Fusion**: Reciprocal Rank Fusion (RRF) combines all three streams
|
|
161
|
+
|
|
162
|
+
### 🏗️ Code Intelligence (LadybugDB)
|
|
163
|
+
- **Knowledge graph**: files, classes, methods, functions, projects, communities
|
|
164
|
+
- **14 languages**: Python, JS, TS, C#, Go, Java, Rust + 7 optional
|
|
165
|
+
- **Roslyn enrichment**: C# method signatures, implements, full AST
|
|
166
|
+
- **Leiden clustering**: automatic community detection
|
|
167
|
+
- **Impact analysis**: upstream/downstream dependency tracing
|
|
168
|
+
- **Incremental freshness**: graph auto-updates within 30s of file changes
|
|
169
|
+
|
|
170
|
+
### 📋 Planning & Records
|
|
171
|
+
- **Task plans**: create, track progress, mark done
|
|
172
|
+
- **Error patterns**: store errors with causes and fixes
|
|
173
|
+
- **Incidents**: root cause analysis with affected services
|
|
174
|
+
- **Code reviews**: feedback history per file
|
|
175
|
+
- **Corrections**: wrong→right pairs the agent learns from
|
|
176
|
+
|
|
177
|
+
### 🛡️ Safety & Audit
|
|
178
|
+
- **Security scan**: hardcoded secrets, SQL injection, insecure HTTP
|
|
179
|
+
- **Dead code detection**: symbols with no incoming edges
|
|
180
|
+
- **Convention checking**: naming violations
|
|
181
|
+
- **Pre-tool-use hook**: blocks catastrophic shell commands
|
|
182
|
+
|
|
183
|
+
### 🌐 Dashboard UI
|
|
184
|
+
```bash
|
|
185
|
+
mnemo serve # http://localhost:3333
|
|
186
|
+
```
|
|
187
|
+
- Interactive knowledge graph (vis-network)
|
|
188
|
+
- Memory & decisions viewer
|
|
189
|
+
- Community explorer with zoom-to-cluster
|
|
190
|
+
- Code search with click-to-focus
|
|
191
|
+
- Health monitoring
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## MCP Tools (16 agent-facing)
|
|
196
|
+
|
|
197
|
+
| Tool | Purpose |
|
|
198
|
+
|------|---------|
|
|
199
|
+
| `mnemo_recall` | Load full project context (budgeted) |
|
|
200
|
+
| `mnemo_remember` | Store a memory with category |
|
|
201
|
+
| `mnemo_forget` | Delete a memory |
|
|
202
|
+
| `mnemo_decide` | Record permanent decision |
|
|
203
|
+
| `mnemo_search_memory` | Semantic search across memories |
|
|
204
|
+
| `mnemo_search` | Search code graph (classes/methods/files) |
|
|
205
|
+
| `mnemo_lookup` | Detailed symbol info (methods, signatures) |
|
|
206
|
+
| `mnemo_graph` | Query graph (stats/neighbors/find) |
|
|
207
|
+
| `mnemo_impact` | Upstream/downstream dependency analysis |
|
|
208
|
+
| `mnemo_plan` | Create and track task plans |
|
|
209
|
+
| `mnemo_audit` | Security, health, dead-code reports |
|
|
210
|
+
| `mnemo_record` | Store errors, incidents, reviews |
|
|
211
|
+
| `mnemo_generate` | Commit messages and PR descriptions |
|
|
212
|
+
| `mnemo_map` | Regenerate repo map |
|
|
213
|
+
| `mnemo_ask` | Combined graph + memory lookup |
|
|
214
|
+
| `mnemo_lesson` | Store/retrieve learned patterns |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Supported Clients
|
|
219
|
+
|
|
220
|
+
| Client | MCP | Hooks | Agent Config |
|
|
221
|
+
|--------|-----|-------|-------------|
|
|
222
|
+
| **Kiro** | ✅ | 5 hooks | ✅ agent + skill |
|
|
223
|
+
| **Amazon Q** | ✅ | — | ✅ rules |
|
|
224
|
+
| **Claude Code** | ✅ | — | ✅ CLAUDE.md |
|
|
225
|
+
| **Cursor** | ✅ | — | ✅ .cursorrules |
|
|
226
|
+
| **Copilot** | ✅ | — | ✅ instructions |
|
|
227
|
+
| **Generic MCP** | ✅ | — | ✅ MNEMO.md |
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Performance
|
|
232
|
+
|
|
233
|
+
| Operation | Time |
|
|
234
|
+
|-----------|------|
|
|
235
|
+
| `mnemo init` (55 files) | 3.5s |
|
|
236
|
+
| `mnemo init` (300 files) | 7s |
|
|
237
|
+
| Re-init (no changes) | 0.01s |
|
|
238
|
+
| Remember 1 memory | 5ms |
|
|
239
|
+
| Recall | 33ms |
|
|
240
|
+
| Semantic search | 2ms |
|
|
241
|
+
| Graph query | 0.2ms |
|
|
242
|
+
|
|
243
|
+
| Resource | Value |
|
|
244
|
+
|----------|-------|
|
|
245
|
+
| RAM | 265 MB |
|
|
246
|
+
| Disk (.mnemo/) | ~16 MB |
|
|
247
|
+
| Model (one-time download) | 86 MB |
|
|
248
|
+
| External databases | 0 |
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Architecture
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
.mnemo/
|
|
256
|
+
├── memory.json # Memories with retention scores
|
|
257
|
+
├── decisions.json # Permanent architectural decisions
|
|
258
|
+
├── plans.json # Task tracking
|
|
259
|
+
├── graph.lbug # LadybugDB knowledge graph
|
|
260
|
+
├── vectors_memory.npy # Dense embedding vectors
|
|
261
|
+
├── meta_memory.json # Vector metadata
|
|
262
|
+
├── engine-meta.json # File hashes for incremental updates
|
|
263
|
+
├── parse-cache.json # AST parse cache
|
|
264
|
+
├── tree.md # Compact repo map
|
|
265
|
+
└── context.json # Project context key-values
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Stack**: Python · LadybugDB (Kuzu) · ONNX Runtime · tree-sitter · Roslyn
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Links
|
|
273
|
+
|
|
274
|
+
- **Website**: [mnemo-mcp.github.io/Mnemo](https://mnemo-mcp.github.io/Mnemo/)
|
|
275
|
+
- **PyPI**: [pypi.org/project/mnemo-dev](https://pypi.org/project/mnemo-dev/)
|
|
276
|
+
- **GitHub**: [github.com/Mnemo-mcp/Mnemo](https://github.com/Mnemo-mcp/Mnemo)
|
|
277
|
+
- **VS Code Extension**: [Marketplace](https://marketplace.visualstudio.com/items?itemName=Nikhil1057.mnemo-vscode)
|
|
278
|
+
|
|
279
|
+
## License
|
|
280
|
+
|
|
281
|
+
[AGPL-3.0](LICENSE)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Mnemo
|
|
2
|
+
|
|
3
|
+
**Persistent engineering cognition for AI coding agents.**
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/mnemo-dev/)
|
|
6
|
+
[]()
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
One command gives your AI agent accumulated engineering understanding across sessions — architecture intelligence, semantic search, code graph, and institutional memory.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install mnemo-dev
|
|
13
|
+
mnemo init
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Your agent now remembers decisions, understands code relationships, and never asks the same question twice.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why Mnemo
|
|
21
|
+
|
|
22
|
+
| Without Mnemo | With Mnemo |
|
|
23
|
+
|---------------|-----------|
|
|
24
|
+
| Re-explain your stack every session | Agent already knows your architecture |
|
|
25
|
+
| Agent breaks call chains it can't see | Full dependency graph with impact analysis |
|
|
26
|
+
| "What caching do we use?" → agent greps | Semantic search finds "Redis for sessions" instantly |
|
|
27
|
+
| Decisions lost between sessions | Permanent decisions survive forever |
|
|
28
|
+
| Context window wasted on repetition | ~500 tokens of targeted recall per session |
|
|
29
|
+
|
|
30
|
+
## Benchmarks
|
|
31
|
+
|
|
32
|
+
| Metric | Mnemo | Built-in (CLAUDE.md) |
|
|
33
|
+
|--------|-------|---------------------|
|
|
34
|
+
| **Search R@5** | **100%** | N/A (grep) |
|
|
35
|
+
| **Search latency** | **2ms** | — |
|
|
36
|
+
| **RAM** | **265 MB** | 0 |
|
|
37
|
+
| **Store 1 memory** | **5ms** | manual edit |
|
|
38
|
+
| **Token cost/session** | ~500 | 22,000+ (full file) |
|
|
39
|
+
| **Cross-session persistence** | ✅ | ❌ (resets) |
|
|
40
|
+
|
|
41
|
+
> Search uses ONNX all-MiniLM-L6-v2 dense embeddings + BM25 keyword + knowledge graph traversal, fused with Reciprocal Rank Fusion.
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Install
|
|
47
|
+
pip install mnemo-dev
|
|
48
|
+
|
|
49
|
+
# Initialize in your repo
|
|
50
|
+
cd your-project
|
|
51
|
+
mnemo init --client kiro # or: cursor, claude-code, amazonq, copilot, generic
|
|
52
|
+
|
|
53
|
+
# That's it. Your agent now has persistent memory.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### What `mnemo init` does:
|
|
57
|
+
1. Scans your codebase (tree-sitter + Roslyn for C#)
|
|
58
|
+
2. Builds a knowledge graph (classes, methods, calls, communities)
|
|
59
|
+
3. Installs lifecycle hooks (auto-capture learnings, inject context)
|
|
60
|
+
4. Configures MCP server for your AI client
|
|
61
|
+
5. Downloads embedding model (~86MB, one-time)
|
|
62
|
+
|
|
63
|
+
### Verify it works:
|
|
64
|
+
```bash
|
|
65
|
+
mnemo recall # See what the agent will know
|
|
66
|
+
mnemo serve # Open dashboard at localhost:3333
|
|
67
|
+
mnemo doctor # Diagnose any issues
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## How It Works
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Session Start (agent-spawn hook)
|
|
76
|
+
→ mnemo_recall injects: decisions + memories + active task + repo map
|
|
77
|
+
→ Agent starts with full context (~500 tokens)
|
|
78
|
+
|
|
79
|
+
User asks a question (user-prompt-submit hook)
|
|
80
|
+
→ Semantic search finds relevant memories
|
|
81
|
+
→ Injected as <mnemo-relevant-context>
|
|
82
|
+
|
|
83
|
+
Agent works (tools available via MCP)
|
|
84
|
+
→ mnemo_lookup: class details, methods, signatures
|
|
85
|
+
→ mnemo_graph: neighbors, communities, impact analysis
|
|
86
|
+
→ mnemo_search: find code by meaning
|
|
87
|
+
→ mnemo_remember: store important context
|
|
88
|
+
→ mnemo_decide: record permanent decisions
|
|
89
|
+
|
|
90
|
+
Session ends (stop hook)
|
|
91
|
+
→ Auto-captures learnings, decisions, session summary
|
|
92
|
+
→ Memories decay over time (hot → warm → cold → evicted)
|
|
93
|
+
→ Contradictions detected and superseded
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Features
|
|
97
|
+
|
|
98
|
+
### 🧠 Memory System
|
|
99
|
+
- **Categorized storage**: architecture, pattern, bug, preference, decision
|
|
100
|
+
- **Retention scoring**: access frequency × recency × importance
|
|
101
|
+
- **Branch-aware**: memories tagged with git branch, filtered on recall
|
|
102
|
+
- **Contradiction detection**: new facts supersede old conflicting ones
|
|
103
|
+
- **Token-budgeted recall**: never exceeds ~2000 tokens regardless of memory count
|
|
104
|
+
- **Memory slots**: pinned context (project_context, user_preferences, known_gotchas)
|
|
105
|
+
|
|
106
|
+
### 🔍 Triple-Stream Search
|
|
107
|
+
- **BM25**: stemmed keyword matching with synonym expansion
|
|
108
|
+
- **Vector**: ONNX all-MiniLM-L6-v2 dense embeddings (384-dim, cosine similarity)
|
|
109
|
+
- **Graph**: Dijkstra traversal from code symbols to linked memories
|
|
110
|
+
- **Fusion**: Reciprocal Rank Fusion (RRF) combines all three streams
|
|
111
|
+
|
|
112
|
+
### 🏗️ Code Intelligence (LadybugDB)
|
|
113
|
+
- **Knowledge graph**: files, classes, methods, functions, projects, communities
|
|
114
|
+
- **14 languages**: Python, JS, TS, C#, Go, Java, Rust + 7 optional
|
|
115
|
+
- **Roslyn enrichment**: C# method signatures, implements, full AST
|
|
116
|
+
- **Leiden clustering**: automatic community detection
|
|
117
|
+
- **Impact analysis**: upstream/downstream dependency tracing
|
|
118
|
+
- **Incremental freshness**: graph auto-updates within 30s of file changes
|
|
119
|
+
|
|
120
|
+
### 📋 Planning & Records
|
|
121
|
+
- **Task plans**: create, track progress, mark done
|
|
122
|
+
- **Error patterns**: store errors with causes and fixes
|
|
123
|
+
- **Incidents**: root cause analysis with affected services
|
|
124
|
+
- **Code reviews**: feedback history per file
|
|
125
|
+
- **Corrections**: wrong→right pairs the agent learns from
|
|
126
|
+
|
|
127
|
+
### 🛡️ Safety & Audit
|
|
128
|
+
- **Security scan**: hardcoded secrets, SQL injection, insecure HTTP
|
|
129
|
+
- **Dead code detection**: symbols with no incoming edges
|
|
130
|
+
- **Convention checking**: naming violations
|
|
131
|
+
- **Pre-tool-use hook**: blocks catastrophic shell commands
|
|
132
|
+
|
|
133
|
+
### 🌐 Dashboard UI
|
|
134
|
+
```bash
|
|
135
|
+
mnemo serve # http://localhost:3333
|
|
136
|
+
```
|
|
137
|
+
- Interactive knowledge graph (vis-network)
|
|
138
|
+
- Memory & decisions viewer
|
|
139
|
+
- Community explorer with zoom-to-cluster
|
|
140
|
+
- Code search with click-to-focus
|
|
141
|
+
- Health monitoring
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## MCP Tools (16 agent-facing)
|
|
146
|
+
|
|
147
|
+
| Tool | Purpose |
|
|
148
|
+
|------|---------|
|
|
149
|
+
| `mnemo_recall` | Load full project context (budgeted) |
|
|
150
|
+
| `mnemo_remember` | Store a memory with category |
|
|
151
|
+
| `mnemo_forget` | Delete a memory |
|
|
152
|
+
| `mnemo_decide` | Record permanent decision |
|
|
153
|
+
| `mnemo_search_memory` | Semantic search across memories |
|
|
154
|
+
| `mnemo_search` | Search code graph (classes/methods/files) |
|
|
155
|
+
| `mnemo_lookup` | Detailed symbol info (methods, signatures) |
|
|
156
|
+
| `mnemo_graph` | Query graph (stats/neighbors/find) |
|
|
157
|
+
| `mnemo_impact` | Upstream/downstream dependency analysis |
|
|
158
|
+
| `mnemo_plan` | Create and track task plans |
|
|
159
|
+
| `mnemo_audit` | Security, health, dead-code reports |
|
|
160
|
+
| `mnemo_record` | Store errors, incidents, reviews |
|
|
161
|
+
| `mnemo_generate` | Commit messages and PR descriptions |
|
|
162
|
+
| `mnemo_map` | Regenerate repo map |
|
|
163
|
+
| `mnemo_ask` | Combined graph + memory lookup |
|
|
164
|
+
| `mnemo_lesson` | Store/retrieve learned patterns |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Supported Clients
|
|
169
|
+
|
|
170
|
+
| Client | MCP | Hooks | Agent Config |
|
|
171
|
+
|--------|-----|-------|-------------|
|
|
172
|
+
| **Kiro** | ✅ | 5 hooks | ✅ agent + skill |
|
|
173
|
+
| **Amazon Q** | ✅ | — | ✅ rules |
|
|
174
|
+
| **Claude Code** | ✅ | — | ✅ CLAUDE.md |
|
|
175
|
+
| **Cursor** | ✅ | — | ✅ .cursorrules |
|
|
176
|
+
| **Copilot** | ✅ | — | ✅ instructions |
|
|
177
|
+
| **Generic MCP** | ✅ | — | ✅ MNEMO.md |
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Performance
|
|
182
|
+
|
|
183
|
+
| Operation | Time |
|
|
184
|
+
|-----------|------|
|
|
185
|
+
| `mnemo init` (55 files) | 3.5s |
|
|
186
|
+
| `mnemo init` (300 files) | 7s |
|
|
187
|
+
| Re-init (no changes) | 0.01s |
|
|
188
|
+
| Remember 1 memory | 5ms |
|
|
189
|
+
| Recall | 33ms |
|
|
190
|
+
| Semantic search | 2ms |
|
|
191
|
+
| Graph query | 0.2ms |
|
|
192
|
+
|
|
193
|
+
| Resource | Value |
|
|
194
|
+
|----------|-------|
|
|
195
|
+
| RAM | 265 MB |
|
|
196
|
+
| Disk (.mnemo/) | ~16 MB |
|
|
197
|
+
| Model (one-time download) | 86 MB |
|
|
198
|
+
| External databases | 0 |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Architecture
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
.mnemo/
|
|
206
|
+
├── memory.json # Memories with retention scores
|
|
207
|
+
├── decisions.json # Permanent architectural decisions
|
|
208
|
+
├── plans.json # Task tracking
|
|
209
|
+
├── graph.lbug # LadybugDB knowledge graph
|
|
210
|
+
├── vectors_memory.npy # Dense embedding vectors
|
|
211
|
+
├── meta_memory.json # Vector metadata
|
|
212
|
+
├── engine-meta.json # File hashes for incremental updates
|
|
213
|
+
├── parse-cache.json # AST parse cache
|
|
214
|
+
├── tree.md # Compact repo map
|
|
215
|
+
└── context.json # Project context key-values
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Stack**: Python · LadybugDB (Kuzu) · ONNX Runtime · tree-sitter · Roslyn
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Links
|
|
223
|
+
|
|
224
|
+
- **Website**: [mnemo-mcp.github.io/Mnemo](https://mnemo-mcp.github.io/Mnemo/)
|
|
225
|
+
- **PyPI**: [pypi.org/project/mnemo-dev](https://pypi.org/project/mnemo-dev/)
|
|
226
|
+
- **GitHub**: [github.com/Mnemo-mcp/Mnemo](https://github.com/Mnemo-mcp/Mnemo)
|
|
227
|
+
- **VS Code Extension**: [Marketplace](https://marketplace.visualstudio.com/items?itemName=Nikhil1057.mnemo-vscode)
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
[AGPL-3.0](LICENSE)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""API Discovery — uses engine/ graph + OpenAPI spec parsing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from ..config import IGNORE_DIRS
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _should_ignore(path: Path) -> bool:
|
|
14
|
+
return any(part in IGNORE_DIRS for part in path.parts)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _find_openapi_specs(repo_root: Path) -> list[Path]:
|
|
18
|
+
"""Find OpenAPI/Swagger spec files."""
|
|
19
|
+
specs = []
|
|
20
|
+
for pattern in ("swagger.json", "openapi.json", "swagger.yaml", "openapi.yaml"):
|
|
21
|
+
for f in repo_root.rglob(pattern):
|
|
22
|
+
if not _should_ignore(f):
|
|
23
|
+
specs.append(f)
|
|
24
|
+
return specs
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _parse_openapi(spec_path: Path) -> dict[str, Any] | None:
|
|
28
|
+
"""Parse an OpenAPI spec into a compact summary."""
|
|
29
|
+
try:
|
|
30
|
+
content = spec_path.read_text()
|
|
31
|
+
if spec_path.suffix in (".yaml", ".yml"):
|
|
32
|
+
import yaml
|
|
33
|
+
data = yaml.safe_load(content)
|
|
34
|
+
else:
|
|
35
|
+
data = json.loads(content)
|
|
36
|
+
except Exception:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
if not data or not isinstance(data, dict):
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
info = data.get("info", {})
|
|
43
|
+
paths = data.get("paths", {})
|
|
44
|
+
endpoints = []
|
|
45
|
+
for path, methods in paths.items():
|
|
46
|
+
for method, details in methods.items():
|
|
47
|
+
if method in ("get", "post", "put", "delete", "patch"):
|
|
48
|
+
endpoints.append({"method": method.upper(), "path": path, "summary": details.get("summary", "")})
|
|
49
|
+
return {"title": info.get("title", spec_path.stem), "version": info.get("version", ""), "endpoints": endpoints}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _detect_endpoints_from_graph(repo_root: Path) -> list[dict[str, Any]]:
|
|
53
|
+
"""Detect API endpoints from controller files indexed in graph."""
|
|
54
|
+
from ..engine.db import open_db, get_db_path
|
|
55
|
+
|
|
56
|
+
if not get_db_path(repo_root).exists():
|
|
57
|
+
return []
|
|
58
|
+
|
|
59
|
+
_, conn = open_db(repo_root)
|
|
60
|
+
endpoints = []
|
|
61
|
+
|
|
62
|
+
# Find controller files and their functions
|
|
63
|
+
result = conn.execute("""
|
|
64
|
+
MATCH (f:File)-[:FILE_DEFINES_CLASS]->(c:Class)
|
|
65
|
+
WHERE f.path CONTAINS 'Controller'
|
|
66
|
+
AND NOT f.path CONTAINS 'test'
|
|
67
|
+
RETURN f.path, c.name
|
|
68
|
+
""")
|
|
69
|
+
controller_files: list[tuple[str, str]] = []
|
|
70
|
+
while result.has_next():
|
|
71
|
+
row = result.get_next()
|
|
72
|
+
controller_files.append((row[0], row[1]))
|
|
73
|
+
|
|
74
|
+
# For each controller, read source to extract route attributes
|
|
75
|
+
for file_path, class_name in controller_files:
|
|
76
|
+
fp = repo_root / file_path
|
|
77
|
+
if not fp.exists():
|
|
78
|
+
continue
|
|
79
|
+
try:
|
|
80
|
+
content = fp.read_text(errors="replace")
|
|
81
|
+
except OSError:
|
|
82
|
+
continue
|
|
83
|
+
|
|
84
|
+
service = file_path.split("/")[0]
|
|
85
|
+
class_route = ""
|
|
86
|
+
route_match = re.search(r'\[Route\("([^"]+)"\)\]', content)
|
|
87
|
+
if route_match:
|
|
88
|
+
class_route = route_match.group(1)
|
|
89
|
+
|
|
90
|
+
for match in re.finditer(
|
|
91
|
+
r'\[(Http(Get|Post|Put|Delete|Patch))(?:\("([^"]*)"\))?\]\s*(?:\[.*?\]\s*)*public\s+(?:async\s+)?\S+\s+(\w+)',
|
|
92
|
+
content, re.DOTALL
|
|
93
|
+
):
|
|
94
|
+
method = match.group(2).upper()
|
|
95
|
+
route = match.group(3) or ""
|
|
96
|
+
func_name = match.group(4)
|
|
97
|
+
full_path = f"/{class_route}/{route}".replace("//", "/").rstrip("/")
|
|
98
|
+
full_path = re.sub(r'\[controller\]', class_name.replace('Controller', '').lower(), full_path)
|
|
99
|
+
endpoints.append({"service": service, "method": method, "path": full_path, "handler": func_name})
|
|
100
|
+
|
|
101
|
+
return endpoints
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def discover_apis(repo_root: Path) -> str:
|
|
105
|
+
"""Discover all APIs in the repo."""
|
|
106
|
+
lines = ["# API Discovery\n"]
|
|
107
|
+
|
|
108
|
+
specs = _find_openapi_specs(repo_root)
|
|
109
|
+
if specs:
|
|
110
|
+
lines.append("## OpenAPI Specifications\n")
|
|
111
|
+
for spec_path in specs:
|
|
112
|
+
parsed = _parse_openapi(spec_path)
|
|
113
|
+
if parsed:
|
|
114
|
+
lines.append(f"### {parsed['title']} (v{parsed['version']})")
|
|
115
|
+
for ep in parsed["endpoints"]:
|
|
116
|
+
lines.append(f"- `{ep['method']} {ep['path']}` {ep['summary']}")
|
|
117
|
+
lines.append("")
|
|
118
|
+
|
|
119
|
+
controller_endpoints = _detect_endpoints_from_graph(repo_root)
|
|
120
|
+
if controller_endpoints:
|
|
121
|
+
lines.append("## Controller Endpoints\n")
|
|
122
|
+
by_service: dict[str, list] = {}
|
|
123
|
+
for ep in controller_endpoints:
|
|
124
|
+
by_service.setdefault(ep["service"], []).append(ep)
|
|
125
|
+
for svc in sorted(by_service):
|
|
126
|
+
lines.append(f"### {svc}")
|
|
127
|
+
for ep in by_service[svc]:
|
|
128
|
+
lines.append(f"- `{ep['method']} {ep['path']}` → {ep['handler']}()")
|
|
129
|
+
lines.append("")
|
|
130
|
+
|
|
131
|
+
if len(lines) <= 2:
|
|
132
|
+
return "No APIs discovered."
|
|
133
|
+
return "\n".join(lines)
|