synap-git 0.2.0__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 (43) hide show
  1. synap_git/__init__.py +5 -0
  2. synap_git/api/__init__.py +5 -0
  3. synap_git/api/app.py +111 -0
  4. synap_git/api/static/index.html +615 -0
  5. synap_git/cli/__init__.py +3 -0
  6. synap_git/cli/__main__.py +4 -0
  7. synap_git/cli/main.py +1174 -0
  8. synap_git/config.py +169 -0
  9. synap_git/diagnostics/__init__.py +0 -0
  10. synap_git/diagnostics/logger.py +82 -0
  11. synap_git/diagnostics/tracing.py +71 -0
  12. synap_git/embeddings/__init__.py +0 -0
  13. synap_git/git/__init__.py +11 -0
  14. synap_git/git/state.py +139 -0
  15. synap_git/indexer/__init__.py +0 -0
  16. synap_git/indexer/daemon.py +143 -0
  17. synap_git/indexer/engine.py +327 -0
  18. synap_git/indexer/scanner.py +463 -0
  19. synap_git/indexer/wiki.py +78 -0
  20. synap_git/mcp/__init__.py +5 -0
  21. synap_git/mcp/server.py +232 -0
  22. synap_git/parser/__init__.py +0 -0
  23. synap_git/parser/registry.py +209 -0
  24. synap_git/provider/anthropic.py +86 -0
  25. synap_git/provider/base.py +44 -0
  26. synap_git/provider/factory.py +101 -0
  27. synap_git/provider/gemini.py +98 -0
  28. synap_git/provider/mock.py +66 -0
  29. synap_git/provider/ollama.py +98 -0
  30. synap_git/provider/openai.py +90 -0
  31. synap_git/py.typed +1 -0
  32. synap_git/retrieval/__init__.py +0 -0
  33. synap_git/retrieval/engine.py +258 -0
  34. synap_git/retrieval/memory.py +123 -0
  35. synap_git/storage/__init__.py +3 -0
  36. synap_git/storage/sqlite.py +575 -0
  37. synap_git/utils/__init__.py +0 -0
  38. synap_git/utils/serialization.py +68 -0
  39. synap_git-0.2.0.dist-info/METADATA +251 -0
  40. synap_git-0.2.0.dist-info/RECORD +43 -0
  41. synap_git-0.2.0.dist-info/WHEEL +4 -0
  42. synap_git-0.2.0.dist-info/entry_points.txt +2 -0
  43. synap_git-0.2.0.dist-info/licenses/LICENSE.md +201 -0
synap_git/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ """Synap: persistent structural context infrastructure for AI coding agents."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.2.0"
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ from synap_git.api.app import create_app
4
+
5
+ __all__ = ["create_app"]
synap_git/api/app.py ADDED
@@ -0,0 +1,111 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import json
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ from fastapi import FastAPI, HTTPException
9
+ from fastapi.middleware.cors import CORSMiddleware
10
+ from fastapi.responses import HTMLResponse, StreamingResponse
11
+ from fastapi.staticfiles import StaticFiles
12
+
13
+ from synap_git.indexer.engine import SynapRuntime
14
+
15
+
16
+ def create_app(runtime: SynapRuntime) -> FastAPI:
17
+ app = FastAPI(
18
+ title="Synap Context Diagnostics",
19
+ description="Deterministic structural context infrastructure for AI coding agents.",
20
+ version="0.2.0",
21
+ )
22
+
23
+ app.add_middleware(
24
+ CORSMiddleware,
25
+ allow_origins=["*"],
26
+ allow_credentials=True,
27
+ allow_methods=["*"],
28
+ allow_headers=["*"],
29
+ )
30
+
31
+ # Serve static UI files
32
+ static_dir = Path(__file__).parent / "static"
33
+ static_dir.mkdir(parents=True, exist_ok=True)
34
+ app.mount("/static", StaticFiles(directory=static_dir), name="static")
35
+
36
+ @app.get("/", response_class=HTMLResponse)
37
+ async def get_index() -> str:
38
+ index_file = static_dir / "index.html"
39
+ if index_file.exists():
40
+ return index_file.read_text(encoding="utf-8")
41
+ return "<h1>Synap Diagnostic UI is ready.</h1>"
42
+
43
+ @app.get("/api/v1/status")
44
+ async def get_status() -> dict[str, Any]:
45
+ try:
46
+ status = runtime.status()
47
+ from synap_git.cli.main import _read_daemon_heartbeat
48
+
49
+ daemon_info = _read_daemon_heartbeat(Path(status.repository_path))
50
+ return {
51
+ "repository_path": status.repository_path,
52
+ "branch": status.branch,
53
+ "git_commit": status.git_commit,
54
+ "active_commit": status.active_commit,
55
+ "symbols": status.symbols,
56
+ "files": status.files,
57
+ "mode": status.mode,
58
+ "daemon": daemon_info,
59
+ }
60
+ except Exception as exc:
61
+ raise HTTPException(status_code=500, detail=str(exc))
62
+
63
+ @app.get("/api/v1/trace/latest")
64
+ async def get_latest_trace() -> dict[str, Any]:
65
+ try:
66
+ return runtime.trace_store.get_latest()
67
+ except Exception as exc:
68
+ raise HTTPException(status_code=500, detail=str(exc))
69
+
70
+ @app.get("/api/v1/events")
71
+ async def get_events() -> StreamingResponse:
72
+ from collections.abc import AsyncGenerator
73
+
74
+ async def event_generator() -> AsyncGenerator[str, None]:
75
+ while True:
76
+ status = runtime.status()
77
+ yield f"data: {json.dumps(status.__dict__)}\n\n"
78
+ await asyncio.sleep(2)
79
+
80
+ return StreamingResponse(event_generator(), media_type="text/event-stream")
81
+
82
+ @app.get("/wiki/{filepath:path}")
83
+ async def get_wiki_page(filepath: str) -> dict[str, Any]:
84
+ wiki_path = runtime.wiki.wiki_dir / f"{filepath}.md"
85
+ if wiki_path.exists():
86
+ return {"status": "ok", "content": wiki_path.read_text(encoding="utf-8")}
87
+ return {"status": "error", "message": "Wiki not found"}
88
+
89
+ @app.get("/api/v1/memory")
90
+ async def get_memory_page() -> dict[str, Any]:
91
+ approved = runtime.store.get_lessons("approved")
92
+ pending = runtime.store.get_lessons("pending")
93
+ return {"status": "ok", "approved": approved, "pending": pending}
94
+
95
+ @app.get("/api/v1/cost")
96
+ async def get_cost_page() -> dict[str, Any]:
97
+ with runtime.store.connect() as conn:
98
+ rows = conn.execute("SELECT * FROM llm_calls ORDER BY created_at DESC").fetchall()
99
+ calls = [dict(r) for r in rows]
100
+ return {"status": "ok", "calls": calls}
101
+
102
+ @app.get("/api/v1/checkpoints")
103
+ async def get_checkpoints_page() -> dict[str, Any]:
104
+ with runtime.store.connect() as conn:
105
+ rows = conn.execute(
106
+ "SELECT * FROM checkpoints ORDER BY created_at DESC LIMIT 20"
107
+ ).fetchall()
108
+ cps = [dict(r) for r in rows]
109
+ return {"status": "ok", "checkpoints": cps}
110
+
111
+ return app