tscode-kg 0.5.1__tar.gz → 0.7.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 (36) hide show
  1. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/PKG-INFO +6 -6
  2. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/README.md +3 -3
  3. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/pyproject.toml +4 -40
  4. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/__init__.py +1 -1
  5. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_snapshot.py +40 -11
  6. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/mcp_server.py +19 -0
  7. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/LICENSE +0 -0
  8. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/__main__.py +0 -0
  9. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/analysis.py +0 -0
  10. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/app.py +0 -0
  11. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/bridge.py +0 -0
  12. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/centrality.py +0 -0
  13. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/__init__.py +0 -0
  14. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_analyze.py +0 -0
  15. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_bridges.py +0 -0
  16. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_build.py +0 -0
  17. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_centrality.py +0 -0
  18. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_explain.py +0 -0
  19. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_framework_nodes.py +0 -0
  20. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_hooks.py +0 -0
  21. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_init.py +0 -0
  22. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_mcp.py +0 -0
  23. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_model.py +0 -0
  24. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_query.py +0 -0
  25. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/cmd_viz.py +0 -0
  26. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/cli/main.py +0 -0
  27. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/coderank.py +0 -0
  28. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/config.py +0 -0
  29. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/explain.py +0 -0
  30. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/extractor.py +0 -0
  31. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/framework_detector.py +0 -0
  32. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/kg.py +0 -0
  33. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/layout3d.py +0 -0
  34. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/snapshots.py +0 -0
  35. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/viz3d.py +0 -0
  36. {tscode_kg-0.5.1 → tscode_kg-0.7.0}/src/tscode_kg/viz3d_timeline.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tscode-kg
3
- Version: 0.5.1
3
+ Version: 0.7.0
4
4
  Summary: Knowledge graph for TypeScript/JavaScript codebases — AST extraction, hybrid semantic+structural search
5
5
  License-Expression: Elastic-2.0
6
6
  License-File: LICENSE
@@ -19,9 +19,9 @@ Provides-Extra: viz
19
19
  Provides-Extra: viz3d
20
20
  Requires-Dist: PyQt5 (>=5.15.11,<5.16) ; extra == "viz3d"
21
21
  Requires-Dist: click (>=8.1.0,<9)
22
- Requires-Dist: kgmodule-utils[semantic,sqlite-vec] (>=0.22.0)
22
+ Requires-Dist: kgmodule-utils[semantic,sqlite-vec] (>=0.23.0)
23
23
  Requires-Dist: markdown (>=3.10,<3.11) ; extra == "viz3d"
24
- Requires-Dist: mcp (>=1.0.0,<2)
24
+ Requires-Dist: mcp (>=1.3.0,<2)
25
25
  Requires-Dist: networkx (>=3.0)
26
26
  Requires-Dist: param (>=2.4,<2.5) ; extra == "viz3d"
27
27
  Requires-Dist: plotly (>=6.8.0,<6.9) ; extra == "viz"
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
  [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
43
43
  [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
44
44
  [![PyPI](https://img.shields.io/pypi/v/tscode-kg.svg)](https://pypi.org/project/tscode-kg/)
45
- [![Version](https://img.shields.io/badge/version-0.5.1-blue.svg)](https://github.com/Flux-Frontiers/tscode_kg/releases)
45
+ [![Version](https://img.shields.io/badge/version-0.7.0-blue.svg)](https://github.com/Flux-Frontiers/tscode_kg/releases)
46
46
  [![CI](https://github.com/Flux-Frontiers/tscode_kg/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/tscode_kg/actions/workflows/ci.yml)
47
47
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
48
48
  [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22559450-blue.svg)](https://doi.org/10.5281/zenodo.22559450)
@@ -195,13 +195,13 @@ If you use TypeScriptKG in your research or project, please cite it:
195
195
 
196
196
  [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22559450-blue.svg)](https://doi.org/10.5281/zenodo.22559450)
197
197
 
198
- > Suchanek, E. G. (2026). *TypeScriptKG: Semantic Knowledge Graph for TypeScript/JavaScript Codebases* (Version 0.5.1) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.22559450
198
+ > Suchanek, E. G. (2026). *TypeScriptKG: Semantic Knowledge Graph for TypeScript/JavaScript Codebases* (Version 0.7.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.22559450
199
199
 
200
200
  ```bibtex
201
201
  @software{suchanek_tscode_kg,
202
202
  author = {Suchanek, Eric G.},
203
203
  title = {{TypeScriptKG}: Semantic Knowledge Graph for TypeScript/JavaScript Codebases},
204
- version = {0.5.1},
204
+ version = {0.7.0},
205
205
  year = {2026},
206
206
  publisher = {Flux-Frontiers},
207
207
  doi = {10.5281/zenodo.22559450},
@@ -3,7 +3,7 @@
3
3
  [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
4
4
  [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
5
5
  [![PyPI](https://img.shields.io/pypi/v/tscode-kg.svg)](https://pypi.org/project/tscode-kg/)
6
- [![Version](https://img.shields.io/badge/version-0.5.1-blue.svg)](https://github.com/Flux-Frontiers/tscode_kg/releases)
6
+ [![Version](https://img.shields.io/badge/version-0.7.0-blue.svg)](https://github.com/Flux-Frontiers/tscode_kg/releases)
7
7
  [![CI](https://github.com/Flux-Frontiers/tscode_kg/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/tscode_kg/actions/workflows/ci.yml)
8
8
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
9
9
  [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22559450-blue.svg)](https://doi.org/10.5281/zenodo.22559450)
@@ -156,13 +156,13 @@ If you use TypeScriptKG in your research or project, please cite it:
156
156
 
157
157
  [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22559450-blue.svg)](https://doi.org/10.5281/zenodo.22559450)
158
158
 
159
- > Suchanek, E. G. (2026). *TypeScriptKG: Semantic Knowledge Graph for TypeScript/JavaScript Codebases* (Version 0.5.1) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.22559450
159
+ > Suchanek, E. G. (2026). *TypeScriptKG: Semantic Knowledge Graph for TypeScript/JavaScript Codebases* (Version 0.7.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.22559450
160
160
 
161
161
  ```bibtex
162
162
  @software{suchanek_tscode_kg,
163
163
  author = {Suchanek, Eric G.},
164
164
  title = {{TypeScriptKG}: Semantic Knowledge Graph for TypeScript/JavaScript Codebases},
165
- version = {0.5.1},
165
+ version = {0.7.0},
166
166
  year = {2026},
167
167
  publisher = {Flux-Frontiers},
168
168
  doi = {10.5281/zenodo.22559450},
@@ -38,7 +38,7 @@ packages = [{ include = "tscode_kg", from = "src" }]
38
38
 
39
39
  [project]
40
40
  name = "tscode-kg"
41
- version = "0.5.1"
41
+ version = "0.7.0"
42
42
  description = "Knowledge graph for TypeScript/JavaScript codebases — AST extraction, hybrid semantic+structural search"
43
43
  readme = "README.md"
44
44
  license = "Elastic-2.0"
@@ -68,7 +68,7 @@ dependencies = [
68
68
  # manager is now the package_name class attribute, where it used to be an
69
69
  # __init__ that only forwarded to super(). Against 0.19.x the manager
70
70
  # reports itself as "kg-utils" in every snapshot's tool field.
71
- "kgmodule-utils[semantic,sqlite-vec]>=0.22.0",
71
+ "kgmodule-utils[semantic,sqlite-vec]>=0.23.0",
72
72
  "click>=8.1.0,<9",
73
73
  # Upper-bounded: mcp 2.0 removed the bundled `mcp.server.fastmcp` module
74
74
  # (FastMCP was split out into the standalone `fastmcp` package) and rebuilt
@@ -76,7 +76,7 @@ dependencies = [
76
76
  # FastMCP from mcp, so an unbounded floor lets a clean install pull 2.x and
77
77
  # break `tscodekg-mcp` at import time. Lift this only alongside a port to
78
78
  # the standalone fastmcp package.
79
- "mcp>=1.0.0,<2",
79
+ "mcp>=1.3.0,<2",
80
80
  "networkx>=3.0",
81
81
  ]
82
82
 
@@ -123,43 +123,7 @@ pytest-cov = ">=5.0.0"
123
123
  # Capped below 0.16 to match the fleet: 0.16 formats Python inside Markdown
124
124
  # code blocks as stable behaviour. The floor was unbounded, so the lock could
125
125
  # drift away from the version .pre-commit-config.yaml pins.
126
- ruff = ">=0.4.0,<0.16"
127
-
128
- # ---------------------------------------------------------------------------
129
- # Maintainer tooling (Poetry group, not a PEP 621 extra)
130
- # ---------------------------------------------------------------------------
131
- # pycode-kg is a tool this repo *runs*, not a library it imports: PyCodeKG
132
- # indexes this repo's Python source from the outside, via the `pycodekg` CLI in
133
- # .git/hooks/pre-commit. It belongs in a Poetry group -- locked and installable,
134
- # but never written into the wheel, so no published extra acquires a sibling.
135
- #
136
- # doc-kg rides along for fleet uniformity: every repo's `kg` group carries the
137
- # same two CLIs, so `poetry install --with kg` means one thing everywhere. This
138
- # repo has no DocKG index today (no .mcp.json, no `dockg` invocation), so the
139
- # CLI is simply available rather than required -- and it is here, not in an
140
- # extra, precisely because nothing depends on it at runtime.
141
- #
142
- # poetry install --with kg # get the pycodekg CLI into .venv/bin
143
- # poetry install # default: group is optional, skipped
144
- #
145
- # This supersedes the standing "install it by hand" workaround. That note
146
- # described a real deadlock -- older pycode-kg capped transformers below 4.57
147
- # while kgmodule-utils >=0.9.0 needs >=5.5.0, which silently held this repo on
148
- # the pre-CVE transformers line. pycode-kg 0.21.4 no longer pins transformers at
149
- # all; it inherits the same kgmodule-utils[semantic] constraint this project
150
- # already uses, so the two no longer conflict. Verified: locking with this group
151
- # keeps transformers at 5.14.1.
152
- [tool.poetry.group.kg]
153
- optional = true
154
-
155
- [tool.poetry.group.kg.dependencies]
156
- # Both floors are the releases that retired these packages' own snapshot
157
- # overrides and moved them onto kgmodule-utils>=0.20.0, the same SDK this repo
158
- # now requires. Pinned lower, `poetry install --with kg` could resolve a dockg
159
- # or pycodekg predating the shared extension points into the same environment
160
- # as a tscode_kg that depends on them.
161
- doc-kg = ">=0.26.0"
162
- pycode-kg = ">=0.27.1"
126
+ ruff = ">=0.15,<0.16"
163
127
 
164
128
  [project.urls]
165
129
  Homepage = "https://github.com/Flux-Frontiers/tscode_kg"
@@ -18,7 +18,7 @@ KGExtractor SDK::
18
18
  from tscode_kg import TSCodeExtractor
19
19
  """
20
20
 
21
- __version__ = "0.5.1"
21
+ __version__ = "0.7.0"
22
22
  __author__ = "Eric G. Suchanek, PhD"
23
23
 
24
24
  from tscode_kg.extractor import TSCodeExtractor
@@ -14,12 +14,38 @@ from __future__ import annotations
14
14
 
15
15
  import json
16
16
  import logging
17
+ import re
17
18
  from pathlib import Path
18
19
 
19
20
  import click
20
21
 
21
22
  logger = logging.getLogger(__name__)
22
23
 
24
+ _CFF_VERSION_RE = re.compile(r'^version:\s*["\']?([^"\'\s]+)', re.M)
25
+
26
+
27
+ def repo_version(repo_root: Path) -> str | None:
28
+ """Return the measured repo's own version, if it declares one.
29
+
30
+ Reads ``version`` from the root ``package.json``, then from
31
+ ``CITATION.cff``, which covers a repo whose ``package.json`` sits in a
32
+ subdirectory or that has none.
33
+
34
+ :param repo_root: Repository root.
35
+ :return: The version string, or ``None`` when neither file declares one.
36
+ """
37
+ try:
38
+ version = json.loads((repo_root / "package.json").read_text()).get("version")
39
+ except (OSError, ValueError, AttributeError):
40
+ version = None
41
+ if isinstance(version, str) and version:
42
+ return version
43
+ try:
44
+ match = _CFF_VERSION_RE.search((repo_root / "CITATION.cff").read_text())
45
+ except OSError:
46
+ return None
47
+ return match.group(1) if match else None
48
+
23
49
 
24
50
  @click.group("snapshot")
25
51
  def snapshot() -> None:
@@ -85,9 +111,10 @@ def save_snapshot(
85
111
  Reads graph statistics and JSDoc coverage from the SQLite graph, runs the
86
112
  analyzer for issue counts and hotspots, then saves a snapshot keyed on
87
113
  VERSION. Omit VERSION and the snapshot is keyed on a UTC timestamp, which
88
- is the right answer for a corpus with no release tag. The tree hash is
89
- recorded as provenance and auto-detected from git when not provided; it
90
- is not the key.
114
+ is the right answer for a corpus with no release tag, and records the
115
+ repo's own version from its root package.json or CITATION.cff. The tree
116
+ hash is recorded as provenance and auto-detected from git when not
117
+ provided; it is not the key.
91
118
 
92
119
  Snapshots are stored in .tscodekg/snapshots/{key}.json, with a
93
120
  manifest.json tracking all snapshots and their metrics.
@@ -118,10 +145,11 @@ def capture_snapshot(
118
145
  ) -> None:
119
146
  """Capture and persist a snapshot; shared by ``snapshot save`` and ``init``.
120
147
 
121
- :param version: Release tag, becoming the snapshot's key; auto-detected
122
- from the installed package when falsy, which then yields a UTC
123
- timestamp key instead -- the right answer for a corpus, not a repo
124
- release. Never used as the key without being explicitly passed here.
148
+ :param version: Release tag, becoming the snapshot's key. When falsy,
149
+ the snapshot records the repo's own version from :func:`repo_version`
150
+ (or, failing that, the installed package's) and is keyed on a UTC
151
+ timestamp instead. Never used as the key without being explicitly
152
+ passed here.
125
153
  :param repo: Repository root path.
126
154
  :param db: SQLite graph path; defaults to ``<repo>/.tscodekg/graph.sqlite``.
127
155
  :param snapshots_dir: Snapshots directory; defaults to ``<repo>/.tscodekg/snapshots``.
@@ -129,7 +157,8 @@ def capture_snapshot(
129
157
  :param tree_hash: Git tree hash, recorded as provenance; auto-detected
130
158
  when empty. It is not the snapshot's key.
131
159
  :param subject: What was measured, e.g. ``repo:tscode-kg``. Recorded
132
- separately from ``version``, which names the measuring tool.
160
+ separately from ``tool`` and ``tool_version``, which name the measuring
161
+ tool.
133
162
  """
134
163
  from tscode_kg.kg import TypeScriptKG # pylint: disable=import-outside-toplevel
135
164
  from tscode_kg.snapshots import SnapshotManager # pylint: disable=import-outside-toplevel
@@ -180,7 +209,7 @@ def capture_snapshot(
180
209
  kg.close()
181
210
 
182
211
  snapshot_obj = snap_mgr.capture(
183
- version=version or None,
212
+ version=version or repo_version(repo_root),
184
213
  branch=branch,
185
214
  graph_stats_dict=stats,
186
215
  critical_issues=critical_issues,
@@ -188,8 +217,8 @@ def capture_snapshot(
188
217
  hotspots=hotspots,
189
218
  issues=issue_strings,
190
219
  tree_hash=tree_hash,
191
- # An explicit VERSION is a release tag and becomes the key. An
192
- # auto-detected one is the measuring tool's version and must not be.
220
+ # An explicit VERSION is a release tag and becomes the key. A
221
+ # detected one (the repo's, or the tool's) must not be.
193
222
  key=version or "",
194
223
  subject=subject,
195
224
  )
@@ -74,6 +74,8 @@ from __future__ import annotations
74
74
  import argparse
75
75
  import json
76
76
  import sys
77
+ from collections.abc import AsyncIterator
78
+ from contextlib import asynccontextmanager
77
79
  from pathlib import Path
78
80
 
79
81
  from kg_utils.semantic import DEFAULT_MODEL
@@ -142,6 +144,22 @@ def _snapshot_freshness(snapshot_total_nodes: int) -> dict:
142
144
  # MCP server
143
145
  # ---------------------------------------------------------------------------
144
146
 
147
+
148
+ @asynccontextmanager
149
+ async def _lifespan(_server: FastMCP) -> AsyncIterator[None]:
150
+ """Close the graph's SQLite connection(s) when the server shuts down.
151
+
152
+ ``main()`` sets the module-level ``_kg`` before ``mcp.run()`` calls into
153
+ this, and both the stdio and SSE transports route through the same
154
+ underlying ``Server.run()``, so this fires on either one.
155
+ """
156
+ try:
157
+ yield
158
+ finally:
159
+ if _kg is not None:
160
+ _kg.close()
161
+
162
+
145
163
  mcp = FastMCP(
146
164
  "tscodekg",
147
165
  instructions=(
@@ -202,6 +220,7 @@ mcp = FastMCP(
202
220
  "- **Track codebase evolution**: snapshot_list → snapshot_diff(key_a, key_b)\n"
203
221
  "- **Answer 'how does X work?'**: pack_snippets with a descriptive query\n"
204
222
  ),
223
+ lifespan=_lifespan,
205
224
  )
206
225
 
207
226
 
File without changes
File without changes