jsat 0.1.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.
Files changed (70) hide show
  1. jsat-0.1.0/.github/workflows/ci.yml +55 -0
  2. jsat-0.1.0/.github/workflows/publish.yml +38 -0
  3. jsat-0.1.0/.gitignore +38 -0
  4. jsat-0.1.0/CHANGELOG.md +59 -0
  5. jsat-0.1.0/PKG-INFO +209 -0
  6. jsat-0.1.0/README.md +119 -0
  7. jsat-0.1.0/jsat/__init__.py +38 -0
  8. jsat-0.1.0/jsat/_ai/__init__.py +90 -0
  9. jsat-0.1.0/jsat/_ai/anthropic.py +80 -0
  10. jsat-0.1.0/jsat/_ai/claude_cli.py +278 -0
  11. jsat-0.1.0/jsat/_ai/none.py +60 -0
  12. jsat-0.1.0/jsat/_ai/ollama.py +97 -0
  13. jsat-0.1.0/jsat/_ai/openai.py +81 -0
  14. jsat-0.1.0/jsat/_ai/openai_compat.py +107 -0
  15. jsat-0.1.0/jsat/_cache/__init__.py +17 -0
  16. jsat-0.1.0/jsat/_cache/disk.py +93 -0
  17. jsat-0.1.0/jsat/_cache/memory.py +84 -0
  18. jsat-0.1.0/jsat/_cache/redis.py +139 -0
  19. jsat-0.1.0/jsat/_config.py +469 -0
  20. jsat-0.1.0/jsat/_core.py +416 -0
  21. jsat-0.1.0/jsat/_embed/__init__.py +37 -0
  22. jsat-0.1.0/jsat/_embed/local.py +53 -0
  23. jsat-0.1.0/jsat/_embed/none.py +42 -0
  24. jsat-0.1.0/jsat/_embed/openai.py +61 -0
  25. jsat-0.1.0/jsat/_exceptions.py +253 -0
  26. jsat-0.1.0/jsat/_graph/__init__.py +87 -0
  27. jsat-0.1.0/jsat/_graph/lightgraph.py +140 -0
  28. jsat-0.1.0/jsat/_graph/neo4j.py +141 -0
  29. jsat-0.1.0/jsat/_graph/sqlite.py +170 -0
  30. jsat-0.1.0/jsat/_models.py +233 -0
  31. jsat-0.1.0/jsat/_parsers/__init__.py +46 -0
  32. jsat-0.1.0/jsat/_parsers/go.py +135 -0
  33. jsat-0.1.0/jsat/_parsers/javascript.py +135 -0
  34. jsat-0.1.0/jsat/_parsers/python.py +149 -0
  35. jsat-0.1.0/jsat/cli.py +1273 -0
  36. jsat-0.1.0/jsat/mcp/__init__.py +1 -0
  37. jsat-0.1.0/jsat/mcp/server.py +194 -0
  38. jsat-0.1.0/jsat/mcp/tools.py +162 -0
  39. jsat-0.1.0/jsat/skills/__init__.py +1 -0
  40. jsat-0.1.0/jsat/skills/clusters.py +44 -0
  41. jsat-0.1.0/jsat/skills/manifest.py +82 -0
  42. jsat-0.1.0/jsat/skills/registry.py +81 -0
  43. jsat-0.1.0/jsat/tools/__init__.py +18 -0
  44. jsat-0.1.0/jsat/tools/blast_radius.py +127 -0
  45. jsat-0.1.0/jsat/tools/contract.py +106 -0
  46. jsat-0.1.0/jsat/tools/export.py +131 -0
  47. jsat-0.1.0/jsat/tools/feature.py +85 -0
  48. jsat-0.1.0/jsat/tools/incident.py +136 -0
  49. jsat-0.1.0/jsat/tools/indexer.py +130 -0
  50. jsat-0.1.0/jsat/tools/ithinking.py +126 -0
  51. jsat-0.1.0/jsat/tools/knowledge.py +100 -0
  52. jsat-0.1.0/jsat/tools/migration.py +128 -0
  53. jsat-0.1.0/jsat/tools/orchestrator.py +101 -0
  54. jsat-0.1.0/jsat/tools/query.py +88 -0
  55. jsat-0.1.0/jsat/tools/review.py +116 -0
  56. jsat-0.1.0/jsat/tools/security.py +97 -0
  57. jsat-0.1.0/jsat/tools/shell.py +720 -0
  58. jsat-0.1.0/jsat/tools/test_helper.py +81 -0
  59. jsat-0.1.0/pyproject.toml +121 -0
  60. jsat-0.1.0/tests/__init__.py +0 -0
  61. jsat-0.1.0/tests/test_blast_radius.py +92 -0
  62. jsat-0.1.0/tests/test_cache.py +99 -0
  63. jsat-0.1.0/tests/test_exceptions.py +92 -0
  64. jsat-0.1.0/tests/test_graph_sqlite.py +118 -0
  65. jsat-0.1.0/tests/test_incident.py +86 -0
  66. jsat-0.1.0/tests/test_migration.py +116 -0
  67. jsat-0.1.0/tests/test_models.py +70 -0
  68. jsat-0.1.0/tests/test_parsers.py +138 -0
  69. jsat-0.1.0/tests/test_security.py +82 -0
  70. jsat-0.1.0/tests/test_skills.py +114 -0
@@ -0,0 +1,55 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install uv
25
+ run: pip install uv
26
+
27
+ - name: Install jsat (core + standard, no AI backends)
28
+ run: uv pip install --system -e ".[standard]"
29
+
30
+ - name: Run CI-safe tests
31
+ run: pytest -m ci --tb=short -q
32
+ env:
33
+ CI: "true"
34
+
35
+ - name: Coverage report (Python 3.11 only)
36
+ if: matrix.python-version == '3.11'
37
+ run: |
38
+ uv pip install --system coverage
39
+ coverage run -m pytest -m ci -q
40
+ coverage report --fail-under=55
41
+
42
+ lint:
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+
47
+ - uses: actions/setup-python@v5
48
+ with:
49
+ python-version: "3.11"
50
+
51
+ - name: Install ruff
52
+ run: pip install ruff
53
+
54
+ - name: Lint
55
+ run: ruff check jsat/ --select E,F,I --ignore E501,E402
@@ -0,0 +1,38 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*" # triggers on: git tag v0.1.0 && git push --tags
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ environment:
12
+ name: pypi
13
+ url: https://pypi.org/project/jsat/
14
+
15
+ permissions:
16
+ id-token: write # required for trusted publishing (no token needed!)
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: "3.11"
24
+
25
+ - name: Install build tools
26
+ run: pip install build
27
+
28
+ - name: Build
29
+ run: python -m build
30
+
31
+ - name: Publish to PyPI
32
+ uses: pypa/gh-action-pypi-publish@release/v1
33
+ with:
34
+ password: ${{ secrets.PYPI_API_TOKEN }}
35
+ # To set the secret:
36
+ # 1. pypi.org → Account Settings → API tokens → Add token (Entire account)
37
+ # 2. GitHub repo → Settings → Secrets and variables → Actions → New secret
38
+ # Name: PYPI_API_TOKEN Value: pypi-AgEI...
jsat-0.1.0/.gitignore ADDED
@@ -0,0 +1,38 @@
1
+ # Planning docs (local only — not tracked)
2
+ plan.md
3
+ prompt.md
4
+
5
+ # JSAT — everything lives under .jsat/
6
+ # Exclude runtime artifacts; keep config.yaml committable for team sharing
7
+ .jsat/graph/
8
+ .jsat/vectors/
9
+ .jsat/cache/
10
+ .jsat/system-profile.json
11
+ .jsat/audit.log
12
+ # Legacy root-level config (no longer created)
13
+ .jsat.yaml
14
+
15
+ # Python
16
+ __pycache__/
17
+ *.py[cod]
18
+ *.egg-info/
19
+ dist/
20
+ build/
21
+ .venv/
22
+ venv/
23
+ .env
24
+ *venv/
25
+
26
+ # Node
27
+ node_modules/
28
+
29
+ # Editors
30
+ .DS_Store
31
+ .idea/
32
+ .vscode/
33
+ *.swp
34
+
35
+ # Secrets (never commit)
36
+ *.pem
37
+ *.key
38
+ .env.local
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ All notable changes to JSAT.
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [0.1.0] — 2026-07-25
8
+
9
+ ### Added
10
+
11
+ **Core infrastructure**
12
+ - 27-class exception hierarchy (`JSATError` → `ConfigError`, `IndexError`, `AIError`, `GraphError`, `ProfileError`, `ExportError`, `SkillError`) — all with structured context kwargs
13
+ - All Pydantic v2 models: `JSATConfig`, `SystemProfile`, `IndexResult`, `BlastRadiusReport`, `SecurityReport`, `IncidentReport`, `QueryResult`, `ExportManifest`, and supporting sub-models
14
+ - Config loader with 5-path search order + `CI=true` auto-overrides
15
+ - System auto-detection: RAM, CPU arch (arm64/x86_64), GPU (CUDA/Metal/none), service reachability (Ollama, Neo4j, Qdrant, Redis)
16
+ - Profile presets: `solo`, `team`, `ci`, `raspberry-pi`
17
+
18
+ **JSAT class and CLI**
19
+ - `JSAT` class with fully lazy backend wiring — heavy imports only on first call
20
+ - Typer CLI: `jsat index`, `jsat shell`, `jsat doctor`, `jsat init`, `jsat export`, `jsat import`, `jsat skills list/run`, `jsat version`
21
+
22
+ **Tools (0–14)**
23
+ - Tool 0 — JSAT Shell: interactive REPL with 14 commands, tab completion, session history, Rich output
24
+ - Tool 1 — Directory Indexer: tree-sitter AST parsing (Python, JS/TS, Go), BFS graph population, `INDEX.md` output
25
+ - Tool 2 — Test Intelligence Helper: source-to-test file matching, over-mock detection, behavioral coverage estimate
26
+ - Tool 3 — Feature Helper: graph-context-aware implementation plan generation
27
+ - Tool 4 — Blast Radius Analyzer: BFS traversal with severity classification (breaking/degraded/warning/safe) and Mermaid diagram output
28
+ - Tool 5 — API Contract Validator: OpenAPI/AsyncAPI diff between git branches with compatibility score
29
+ - Tool 6 — Security Review Agent: Semgrep integration (graceful fallback), Shannon entropy secret detection, OWASP severity filtering
30
+ - Tool 7 — Incident Investigation Helper: git history scoring with recency × blast-radius × pattern-match formula
31
+ - Tool 8 — Migration Safety Validator: SQL parsing, lock-type classification, zero-downtime guide generation
32
+ - Tool 9 — Multi-Model Code Review: parallel dispatch, embedding-based deduplication, confidence ranking
33
+ - Tool 10 — Knowledge Base Builder: graph-stored knowledge entries, AI synthesis, stale-flag decay
34
+ - Tool 11 — Multi-Agent Orchestrator: heuristic task decomposition, sequential agent execution, conflict detection
35
+ - Tool 12 — Export / Import System: atomic ZIP export with manifest, graph + artifact restore
36
+ - Tool 13 — Python SDK: `JSAT` class; full sync + async API for all tools
37
+ - Tool 14 — IThinking: 7-phase meta-cognitive wrapper (intent → plan → verify → execute → reflect)
38
+
39
+ **Backends**
40
+ - Graph: SQLite (core, always available), LightGraph (stdlib-only fallback), Neo4j (team extra)
41
+ - Embeddings: NoOp/zero-vector (CI), local Ollama nomic-embed-code, OpenAI text-embedding-3-*
42
+ - Cache: memory LRU, atomic disk JSON, Redis (team extra)
43
+ - AI: NoOp (CI), Ollama (local), Anthropic/Claude, OpenAI, any OpenAI-compatible endpoint
44
+
45
+ **MCP server**
46
+ - JSON-RPC 2.0 stdin/stdout server with 47-tool catalog (JSON Schema per tool)
47
+ - 12 tool categories: Index, Blast Radius, Tests, Security, API Contract, Knowledge, Incident, Migration, Review, Export, Meta, IThinking
48
+
49
+ **Skills system**
50
+ - `SkillsRegistry`: YAML manifest auto-discovery and dispatch
51
+ - `SkillManifest` Pydantic model with `from_yaml()` and `to_mcp_tool()` converters
52
+ - 7 built-in skill clusters: `start-session`, `new-feature`, `pre-merge`, `incident`, `security-release`, `db-schema-change`, `knowledge-maintenance`
53
+
54
+ **Tests**
55
+ - 43+ CI-safe tests (`@pytest.mark.ci`) covering: exceptions, models, caches, SQLite graph, parsers (Python/JS/Go), blast radius, incident scoring, migration analysis, security detection, skills registry
56
+
57
+ **Packaging**
58
+ - `pyproject.toml` with 6 pip extras: `core` (~80MB), `local`, `standard`, `team`, `ci`, `all`
59
+ - GitHub Actions CI: matrix (Python 3.10/3.11/3.12), ruff lint, coverage gate at 55%
jsat-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,209 @@
1
+ Metadata-Version: 2.4
2
+ Name: jsat
3
+ Version: 0.1.0
4
+ Summary: JaySoft AI Tools — open-source codebase intelligence shell and SDK
5
+ Project-URL: Homepage, https://github.com/jsat-project/jsat
6
+ Project-URL: Repository, https://github.com/jsat-project/jsat
7
+ Project-URL: Bug Tracker, https://github.com/jsat-project/jsat/issues
8
+ Author-email: JaySoft <iamjpsonkar@gmail.com>
9
+ License: MIT
10
+ Keywords: ai,cli,codebase,intelligence,sdk,static-analysis
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Topic :: Software Development :: Quality Assurance
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: click>=8
22
+ Requires-Dist: gitpython>=3.1
23
+ Requires-Dist: httpx>=0.27
24
+ Requires-Dist: psutil>=5.9
25
+ Requires-Dist: pydantic-settings>=2
26
+ Requires-Dist: pydantic>=2.5
27
+ Requires-Dist: pyyaml>=6
28
+ Requires-Dist: rich>=13
29
+ Requires-Dist: sqlean-py>=0.21.7
30
+ Requires-Dist: structlog>=24
31
+ Requires-Dist: tree-sitter-go>=0.21
32
+ Requires-Dist: tree-sitter-javascript>=0.21
33
+ Requires-Dist: tree-sitter-python>=0.21
34
+ Requires-Dist: tree-sitter>=0.21
35
+ Requires-Dist: typer[all]>=0.12
36
+ Provides-Extra: all
37
+ Requires-Dist: anthropic>=0.30; extra == 'all'
38
+ Requires-Dist: graphiti-core>=0.3; extra == 'all'
39
+ Requires-Dist: jsonschema>=4.20; extra == 'all'
40
+ Requires-Dist: neo4j>=5.15; extra == 'all'
41
+ Requires-Dist: ollama>=0.2; extra == 'all'
42
+ Requires-Dist: openai>=1.35; extra == 'all'
43
+ Requires-Dist: openapi-spec-validator>=0.7; extra == 'all'
44
+ Requires-Dist: prance>=23; extra == 'all'
45
+ Requires-Dist: pygithub>=2; extra == 'all'
46
+ Requires-Dist: qdrant-client>=1.7; extra == 'all'
47
+ Requires-Dist: redis>=5; extra == 'all'
48
+ Requires-Dist: sarif-tools>=0.3; extra == 'all'
49
+ Requires-Dist: semgrep>=1.50; extra == 'all'
50
+ Requires-Dist: tree-sitter-java>=0.21; extra == 'all'
51
+ Requires-Dist: tree-sitter-ruby>=0.21; extra == 'all'
52
+ Requires-Dist: tree-sitter-rust>=0.21; extra == 'all'
53
+ Provides-Extra: anthropic
54
+ Requires-Dist: anthropic>=0.30; extra == 'anthropic'
55
+ Provides-Extra: ci
56
+ Requires-Dist: jsonschema>=4.20; extra == 'ci'
57
+ Requires-Dist: openapi-spec-validator>=0.7; extra == 'ci'
58
+ Requires-Dist: prance>=23; extra == 'ci'
59
+ Requires-Dist: pygithub>=2; extra == 'ci'
60
+ Requires-Dist: sarif-tools>=0.3; extra == 'ci'
61
+ Requires-Dist: semgrep>=1.50; extra == 'ci'
62
+ Requires-Dist: tree-sitter-java>=0.21; extra == 'ci'
63
+ Requires-Dist: tree-sitter-ruby>=0.21; extra == 'ci'
64
+ Requires-Dist: tree-sitter-rust>=0.21; extra == 'ci'
65
+ Provides-Extra: local
66
+ Requires-Dist: ollama>=0.2; extra == 'local'
67
+ Provides-Extra: openai
68
+ Requires-Dist: openai>=1.35; extra == 'openai'
69
+ Provides-Extra: standard
70
+ Requires-Dist: jsonschema>=4.20; extra == 'standard'
71
+ Requires-Dist: openapi-spec-validator>=0.7; extra == 'standard'
72
+ Requires-Dist: prance>=23; extra == 'standard'
73
+ Requires-Dist: semgrep>=1.50; extra == 'standard'
74
+ Requires-Dist: tree-sitter-java>=0.21; extra == 'standard'
75
+ Requires-Dist: tree-sitter-ruby>=0.21; extra == 'standard'
76
+ Requires-Dist: tree-sitter-rust>=0.21; extra == 'standard'
77
+ Provides-Extra: team
78
+ Requires-Dist: graphiti-core>=0.3; extra == 'team'
79
+ Requires-Dist: jsonschema>=4.20; extra == 'team'
80
+ Requires-Dist: neo4j>=5.15; extra == 'team'
81
+ Requires-Dist: openapi-spec-validator>=0.7; extra == 'team'
82
+ Requires-Dist: prance>=23; extra == 'team'
83
+ Requires-Dist: qdrant-client>=1.7; extra == 'team'
84
+ Requires-Dist: redis>=5; extra == 'team'
85
+ Requires-Dist: semgrep>=1.50; extra == 'team'
86
+ Requires-Dist: tree-sitter-java>=0.21; extra == 'team'
87
+ Requires-Dist: tree-sitter-ruby>=0.21; extra == 'team'
88
+ Requires-Dist: tree-sitter-rust>=0.21; extra == 'team'
89
+ Description-Content-Type: text/markdown
90
+
91
+ # JSAT — JaySoft AI Tools
92
+
93
+ > Codebase intelligence shell and SDK. Lightweight by default.
94
+
95
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
96
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
97
+ [![Author](https://img.shields.io/badge/author-Jay%20Prakash%20Sonkar-green.svg)](https://github.com/iamjpsonkar)
98
+
99
+ ## What is JSAT?
100
+
101
+ JSAT gives any AI (Claude, Codex, Gemini, or local Ollama) deep, structured understanding of
102
+ your codebase — so you spend less time explaining context and more time shipping.
103
+
104
+ - **Interactive shell** like IPython, but for codebase intelligence
105
+ - **Python SDK** — `from jsat import JSAT`
106
+ - **Works offline** with local Ollama — no API keys required
107
+ - **Lightweight by default** — `pip install jsat` is ~80MB and starts in <800ms
108
+
109
+ ## Quick Start
110
+
111
+ ```bash
112
+ pip install jsat # core only
113
+ pip install jsat[local] # + Ollama for local AI (recommended)
114
+
115
+ cd your-project/
116
+ jsat init --profile solo # write .jsat.yaml
117
+ jsat index . # build the codebase graph
118
+ jsat # start the shell
119
+ ```
120
+
121
+ ```
122
+ JSAT Shell v0.1.0
123
+ > what does this project do?
124
+ > which services write to the orders table?
125
+ > blast-radius src/payment/refund.py
126
+ ```
127
+
128
+ ## Installation Profiles
129
+
130
+ | Profile | Command | Size | Use case |
131
+ |---------|---------|------|---------|
132
+ | Core | `pip install jsat` | ~80MB | Quick evaluation |
133
+ | Local AI | `pip install jsat[local]` | ~85MB | Solo dev with Ollama |
134
+ | Standard | `pip install jsat[standard]` | ~120MB | Individual engineers |
135
+ | Team | `pip install jsat[team]` | ~200MB | Engineering teams |
136
+ | CI | `pip install jsat[ci]` | ~90MB | CI pipelines (no AI cost) |
137
+ | Full | `pip install jsat[all]` | ~350MB | Power users |
138
+
139
+ ## System Auto-Detection
140
+
141
+ JSAT probes your machine on first run and selects the right backends:
142
+
143
+ ```bash
144
+ jsat doctor # see what's detected and what to install
145
+ ```
146
+
147
+ | Your setup | Graph | Embeddings | Cache |
148
+ |-----------|-------|-----------|-------|
149
+ | Laptop, Ollama running | SQLite | nomic-embed-code (local) | disk |
150
+ | Team server (Neo4j+Qdrant+Redis) | Neo4j | text-embedding-3-small | Redis |
151
+ | ARM (Apple M2, Pi) | SQLite | nomic-embed-code via Metal | disk |
152
+ | CI environment | SQLite | none (skipped) | memory |
153
+
154
+ ## Python SDK
155
+
156
+ ```python
157
+ from jsat import JSAT
158
+
159
+ js = JSAT(repo=".")
160
+ js.index()
161
+
162
+ # Natural language query
163
+ result = js.query("what calls the refund endpoint?")
164
+ print(result.answer)
165
+
166
+ # Blast radius — trace impact of a change
167
+ report = js.blast_radius("src/payment/refund.py")
168
+ for impact in report.impacts:
169
+ print(f"{impact.severity}: {impact.node_name}")
170
+
171
+ # Incident investigation
172
+ incident = js.investigate_incident("500 errors on checkout since 14:00")
173
+ for h in incident.hypotheses:
174
+ print(f"Score {h.score}: {h.commit_summary}")
175
+
176
+ # Export for sharing
177
+ js.export("backup.jsat.zip")
178
+ ```
179
+
180
+ ## CLI Reference
181
+
182
+ ```bash
183
+ jsat index [PATH] [--branch HEAD] [--force]
184
+ jsat shell
185
+ jsat doctor [--refresh] [--json]
186
+ jsat init --profile solo|team|ci|raspberry-pi
187
+ jsat export OUTPUT
188
+ jsat import ARCHIVE
189
+ jsat skills list
190
+ jsat version
191
+ ```
192
+
193
+ ## Architecture
194
+
195
+ JSAT is built around a **graph-native architecture**:
196
+
197
+ - **tree-sitter** for multi-language AST parsing
198
+ - **SQLite** (local) or **Neo4j** (team) for the codebase graph
199
+ - **Ollama** (local) or any cloud LLM for AI features
200
+ - **Lazy loading** — nothing heavy loads until you use it
201
+
202
+ All backends implement ABCs — tools never call backends directly.
203
+
204
+ ## Project
205
+
206
+ - **Author:** Jay Prakash Sonkar ([@iamjpsonkar](https://github.com/iamjpsonkar))
207
+ - **Email:** iamjpsonkar@gmail.com
208
+ - **License:** MIT
209
+ - **Specification:** [`plan.md`](plan.md) | **Implementation guide:** [`prompt.md`](prompt.md)
jsat-0.1.0/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # JSAT — JaySoft AI Tools
2
+
3
+ > Codebase intelligence shell and SDK. Lightweight by default.
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
7
+ [![Author](https://img.shields.io/badge/author-Jay%20Prakash%20Sonkar-green.svg)](https://github.com/iamjpsonkar)
8
+
9
+ ## What is JSAT?
10
+
11
+ JSAT gives any AI (Claude, Codex, Gemini, or local Ollama) deep, structured understanding of
12
+ your codebase — so you spend less time explaining context and more time shipping.
13
+
14
+ - **Interactive shell** like IPython, but for codebase intelligence
15
+ - **Python SDK** — `from jsat import JSAT`
16
+ - **Works offline** with local Ollama — no API keys required
17
+ - **Lightweight by default** — `pip install jsat` is ~80MB and starts in <800ms
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ pip install jsat # core only
23
+ pip install jsat[local] # + Ollama for local AI (recommended)
24
+
25
+ cd your-project/
26
+ jsat init --profile solo # write .jsat.yaml
27
+ jsat index . # build the codebase graph
28
+ jsat # start the shell
29
+ ```
30
+
31
+ ```
32
+ JSAT Shell v0.1.0
33
+ > what does this project do?
34
+ > which services write to the orders table?
35
+ > blast-radius src/payment/refund.py
36
+ ```
37
+
38
+ ## Installation Profiles
39
+
40
+ | Profile | Command | Size | Use case |
41
+ |---------|---------|------|---------|
42
+ | Core | `pip install jsat` | ~80MB | Quick evaluation |
43
+ | Local AI | `pip install jsat[local]` | ~85MB | Solo dev with Ollama |
44
+ | Standard | `pip install jsat[standard]` | ~120MB | Individual engineers |
45
+ | Team | `pip install jsat[team]` | ~200MB | Engineering teams |
46
+ | CI | `pip install jsat[ci]` | ~90MB | CI pipelines (no AI cost) |
47
+ | Full | `pip install jsat[all]` | ~350MB | Power users |
48
+
49
+ ## System Auto-Detection
50
+
51
+ JSAT probes your machine on first run and selects the right backends:
52
+
53
+ ```bash
54
+ jsat doctor # see what's detected and what to install
55
+ ```
56
+
57
+ | Your setup | Graph | Embeddings | Cache |
58
+ |-----------|-------|-----------|-------|
59
+ | Laptop, Ollama running | SQLite | nomic-embed-code (local) | disk |
60
+ | Team server (Neo4j+Qdrant+Redis) | Neo4j | text-embedding-3-small | Redis |
61
+ | ARM (Apple M2, Pi) | SQLite | nomic-embed-code via Metal | disk |
62
+ | CI environment | SQLite | none (skipped) | memory |
63
+
64
+ ## Python SDK
65
+
66
+ ```python
67
+ from jsat import JSAT
68
+
69
+ js = JSAT(repo=".")
70
+ js.index()
71
+
72
+ # Natural language query
73
+ result = js.query("what calls the refund endpoint?")
74
+ print(result.answer)
75
+
76
+ # Blast radius — trace impact of a change
77
+ report = js.blast_radius("src/payment/refund.py")
78
+ for impact in report.impacts:
79
+ print(f"{impact.severity}: {impact.node_name}")
80
+
81
+ # Incident investigation
82
+ incident = js.investigate_incident("500 errors on checkout since 14:00")
83
+ for h in incident.hypotheses:
84
+ print(f"Score {h.score}: {h.commit_summary}")
85
+
86
+ # Export for sharing
87
+ js.export("backup.jsat.zip")
88
+ ```
89
+
90
+ ## CLI Reference
91
+
92
+ ```bash
93
+ jsat index [PATH] [--branch HEAD] [--force]
94
+ jsat shell
95
+ jsat doctor [--refresh] [--json]
96
+ jsat init --profile solo|team|ci|raspberry-pi
97
+ jsat export OUTPUT
98
+ jsat import ARCHIVE
99
+ jsat skills list
100
+ jsat version
101
+ ```
102
+
103
+ ## Architecture
104
+
105
+ JSAT is built around a **graph-native architecture**:
106
+
107
+ - **tree-sitter** for multi-language AST parsing
108
+ - **SQLite** (local) or **Neo4j** (team) for the codebase graph
109
+ - **Ollama** (local) or any cloud LLM for AI features
110
+ - **Lazy loading** — nothing heavy loads until you use it
111
+
112
+ All backends implement ABCs — tools never call backends directly.
113
+
114
+ ## Project
115
+
116
+ - **Author:** Jay Prakash Sonkar ([@iamjpsonkar](https://github.com/iamjpsonkar))
117
+ - **Email:** iamjpsonkar@gmail.com
118
+ - **License:** MIT
119
+ - **Specification:** [`plan.md`](plan.md) | **Implementation guide:** [`prompt.md`](prompt.md)
@@ -0,0 +1,38 @@
1
+ """
2
+ JSAT — JaySoft AI Tools
3
+ Codebase intelligence shell and SDK. Lightweight by default.
4
+
5
+ pip install jsat # core only (~80MB)
6
+ pip install jsat[local] # + Ollama
7
+ pip install jsat[standard] # + analysis tools
8
+ pip install jsat[team] # + Neo4j, Qdrant, Redis
9
+ pip install jsat[all] # everything
10
+ """
11
+ from __future__ import annotations
12
+
13
+ from jsat._core import JSAT
14
+ from jsat._config import load_config
15
+ from jsat._exceptions import (
16
+ JSATError, ConfigError, ConfigFileNotFound, ConfigSchemaError,
17
+ MissingRequiredConfig, IndexError, IndexNotFound, IndexCorrupted,
18
+ IndexOutOfDate, UnsupportedLanguage, AIError, AIProviderError,
19
+ AIRateLimitError, AITimeoutError, AIContextLengthError, AIAuthError,
20
+ GraphError, GraphConnectionError, GraphQueryError, GraphCapacityError,
21
+ ProfileError, ExportError, ExportPermissionError, ImportVersionMismatch,
22
+ ImportCorrupted, SkillError, SkillNotFound, SkillManifestError,
23
+ SkillExecutionError,
24
+ )
25
+
26
+ __version__ = "0.1.0"
27
+ __author__ = "Jay Prakash Sonkar"
28
+ __email__ = "iamjpsonkar@gmail.com"
29
+ __license__ = "MIT"
30
+
31
+ __all__ = [
32
+ "JSAT",
33
+ "load_config",
34
+ "JSATError",
35
+ "__version__",
36
+ "__author__",
37
+ "__email__",
38
+ ]
@@ -0,0 +1,90 @@
1
+ """jsat._ai — AIProvider ABC and factory."""
2
+ from __future__ import annotations
3
+
4
+ from abc import ABC, abstractmethod
5
+ from typing import Any, Iterator
6
+
7
+
8
+ class AIProvider(ABC):
9
+ """Contract all AI/LLM backends must implement."""
10
+
11
+ @abstractmethod
12
+ def complete(self, prompt: str, max_tokens: int = 2048, temperature: float = 0.1) -> str: ...
13
+
14
+ @abstractmethod
15
+ async def complete_async(self, prompt: str, max_tokens: int = 2048, temperature: float = 0.1) -> str: ...
16
+
17
+ @abstractmethod
18
+ def stream(self, prompt: str, max_tokens: int = 2048) -> Iterator[str]: ...
19
+
20
+ @property
21
+ @abstractmethod
22
+ def provider_name(self) -> str: ...
23
+
24
+ @property
25
+ @abstractmethod
26
+ def model_name(self) -> str: ...
27
+
28
+ def is_available(self) -> bool:
29
+ return True
30
+
31
+
32
+ def get_ai_provider(cfg: Any) -> AIProvider:
33
+ """Factory: returns the right AIProvider based on cfg.ai.provider."""
34
+ import structlog
35
+ log = structlog.get_logger(__name__)
36
+
37
+ provider_name: str = getattr(getattr(cfg, "ai", None), "provider", "none") or "none"
38
+ log.info("ai_provider_factory", provider=provider_name)
39
+
40
+ if provider_name == "none":
41
+ from jsat._ai.none import NoOpProvider
42
+ return NoOpProvider()
43
+
44
+ if provider_name == "claude_cli":
45
+ from jsat._ai.claude_cli import ClaudeCliProvider
46
+ return ClaudeCliProvider(cfg)
47
+
48
+ if provider_name == "ollama":
49
+ try:
50
+ from jsat._ai.ollama import OllamaProvider
51
+ return OllamaProvider(cfg)
52
+ except ImportError as e:
53
+ _profile_error("ollama", "local", e)
54
+
55
+ if provider_name == "anthropic":
56
+ try:
57
+ from jsat._ai.anthropic import AnthropicProvider # type: ignore[import]
58
+ return AnthropicProvider(cfg)
59
+ except ImportError as e:
60
+ _profile_error("anthropic", "anthropic", e)
61
+
62
+ if provider_name == "openai":
63
+ try:
64
+ from jsat._ai.openai import OpenAIProvider # type: ignore[import]
65
+ return OpenAIProvider(cfg)
66
+ except ImportError as e:
67
+ _profile_error("openai", "openai", e)
68
+
69
+ raise ValueError(
70
+ f"Unknown ai.provider '{provider_name}'. "
71
+ "Valid: none, ollama, anthropic, openai. Run: jsat init --profile solo"
72
+ )
73
+
74
+
75
+ def _profile_error(provider: str, extra: str, cause: ImportError) -> None:
76
+ import structlog
77
+ structlog.get_logger(__name__).error(
78
+ "ai_provider_import_failed", provider=provider, extra=extra, error=str(cause)
79
+ )
80
+ try:
81
+ from jsat._exceptions import ProfileError
82
+ raise ProfileError(
83
+ f"AI provider '{provider}' requires jsat[{extra}].\n"
84
+ f"Install: pip install 'jsat[{extra}]'"
85
+ ) from cause
86
+ except ImportError:
87
+ raise ImportError(f"Install: pip install 'jsat[{extra}]'") from cause
88
+
89
+
90
+ __all__ = ["AIProvider", "get_ai_provider"]