heimdall-code 0.3.0__tar.gz → 0.3.1__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.
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/.claude-plugin/plugin.json +1 -1
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/CHANGELOG.md +11 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/PKG-INFO +2 -2
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/__init__.py +1 -1
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/cli.py +5 -1
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/registry.py +8 -3
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/pyproject.toml +1 -1
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/tests/test_heimdall.py +15 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/uv.lock +1 -1
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/.claude-plugin/marketplace.json +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/.github/workflows/release.yml +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/.gitignore +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/.mcp.json +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/CLAUDE.md +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/CONTRIBUTING.md +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/LICENSE +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/README.md +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/.gitignore +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/QUESTIONS.md +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/README.md +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/RESULTS.md +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/compare.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/dump_lbug.mjs +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/kubernetes.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/questions.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/bench/terraform.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/__main__.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/graph.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/index.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/install.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/mcp_server.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/heimdall/parse.py +0 -0
- {heimdall_code-0.3.0 → heimdall_code-0.3.1}/skills/heimdall/SKILL.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "heimdall",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "A code knowledge graph that sees everything. Indexes any repo into a SQLite property graph and answers what calls this, what breaks if I change it, and how does A reach B.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Bogdan Sapovskyi",
|
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
Notable changes, newest first. Versions follow [semver](https://semver.org); until 1.0
|
|
4
4
|
the graph schema and the JSON payloads may still move.
|
|
5
5
|
|
|
6
|
+
## 0.3.1 — 2026-08-12
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- A failed project lookup no longer takes the MCP server down with it. `search` with no
|
|
11
|
+
project, from a directory with no index, raised `SystemExit` — a `BaseException` the
|
|
12
|
+
tool handler never turned into an error reply, so it unwound the server's task group
|
|
13
|
+
and every later call found a dead pipe. `registry.resolve` raises `LookupError` now and
|
|
14
|
+
`cli.py` turns it back into `SystemExit` where a terminal is watching; the message and
|
|
15
|
+
exit code are unchanged there.
|
|
16
|
+
|
|
6
17
|
## 0.3.0 — 2026-08-01
|
|
7
18
|
|
|
8
19
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: heimdall-code
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A code knowledge graph that sees everything -- indexes any repository into a SQLite property graph and serves it to AI agents over MCP.
|
|
5
5
|
Project-URL: Homepage, https://github.com/stPhoenix/heimdall
|
|
6
6
|
Project-URL: Source, https://github.com/stPhoenix/heimdall
|
|
@@ -181,7 +181,11 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
181
181
|
serve(a.project)
|
|
182
182
|
return 0
|
|
183
183
|
|
|
184
|
-
|
|
184
|
+
try:
|
|
185
|
+
db = registry.resolve(a.project)
|
|
186
|
+
except LookupError as exc:
|
|
187
|
+
raise SystemExit(str(exc)) from None
|
|
188
|
+
g = Graph.open(db, readonly=True)
|
|
185
189
|
try:
|
|
186
190
|
match a.cmd:
|
|
187
191
|
case "search":
|
|
@@ -31,7 +31,12 @@ def register(name: str, db: Path) -> None:
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def resolve(project: str | None, cwd: Path | None = None) -> Path:
|
|
34
|
-
"""A project name, an explicit db path, or the repo in the current directory.
|
|
34
|
+
"""A project name, an explicit db path, or the repo in the current directory.
|
|
35
|
+
|
|
36
|
+
Failure is a LookupError, never SystemExit: this also runs inside the MCP server,
|
|
37
|
+
where a BaseException escapes the tool handler and kills the process mid-request --
|
|
38
|
+
the client then hangs on a reply that will never come.
|
|
39
|
+
"""
|
|
35
40
|
if project:
|
|
36
41
|
p = Path(project)
|
|
37
42
|
if p.suffix == ".db" and p.exists():
|
|
@@ -42,10 +47,10 @@ def resolve(project: str | None, cwd: Path | None = None) -> Path:
|
|
|
42
47
|
matches = [v for k, v in entries.items() if project in k]
|
|
43
48
|
if len(matches) == 1:
|
|
44
49
|
return Path(matches[0])
|
|
45
|
-
raise
|
|
50
|
+
raise LookupError(f"unknown project {project!r}; known: {', '.join(sorted(load())) or '(none)'}")
|
|
46
51
|
here = (cwd or Path.cwd()).resolve()
|
|
47
52
|
for d in (here, *here.parents):
|
|
48
53
|
db = d / ".heimdall" / "graph.db"
|
|
49
54
|
if db.exists():
|
|
50
55
|
return db
|
|
51
|
-
raise
|
|
56
|
+
raise LookupError("no index found here -- run `heimdall index` first, or pass --project")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
# `heimdall` on PyPI is an unrelated screenshot library; the command is still `heimdall`
|
|
3
3
|
name = "heimdall-code"
|
|
4
|
-
version = "0.3.
|
|
4
|
+
version = "0.3.1"
|
|
5
5
|
description = "A code knowledge graph that sees everything -- indexes any repository into a SQLite property graph and serves it to AI agents over MCP."
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
requires-python = ">=3.12"
|
|
@@ -451,6 +451,20 @@ def test_install_writes_agent_config() -> None:
|
|
|
451
451
|
assert r.returncode == 0, r.stdout + r.stderr # the assertion that failed, not just "exit 1"
|
|
452
452
|
|
|
453
453
|
|
|
454
|
+
def test_resolve_failures_are_ordinary_exceptions() -> None:
|
|
455
|
+
"""SystemExit here killed the MCP server mid-request; the client hung, then reconnected."""
|
|
456
|
+
from heimdall import registry
|
|
457
|
+
|
|
458
|
+
with tempfile.TemporaryDirectory() as d:
|
|
459
|
+
for bad in (lambda: registry.resolve(None, Path(d)), lambda: registry.resolve("nope::missing", Path(d))):
|
|
460
|
+
try:
|
|
461
|
+
bad()
|
|
462
|
+
except Exception as exc: # LookupError is an Exception; SystemExit is not
|
|
463
|
+
assert isinstance(exc, LookupError), exc
|
|
464
|
+
else:
|
|
465
|
+
raise AssertionError("expected a LookupError")
|
|
466
|
+
|
|
467
|
+
|
|
454
468
|
def test_every_declared_language_extracts() -> None:
|
|
455
469
|
from heimdall.parse import EXT_LANG, parse_source
|
|
456
470
|
|
|
@@ -466,5 +480,6 @@ if __name__ == "__main__":
|
|
|
466
480
|
test_end_to_end()
|
|
467
481
|
test_submodules_are_indexed()
|
|
468
482
|
test_install_writes_agent_config()
|
|
483
|
+
test_resolve_failures_are_ordinary_exceptions()
|
|
469
484
|
test_every_declared_language_extracts()
|
|
470
485
|
print("ok")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|