java-codebase-rag 0.11.2__py3-none-any.whl → 0.12.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.
- java_codebase_rag/_deprecation.py +103 -0
- java_codebase_rag/_version.py +2 -2
- java_codebase_rag/ast/ast_java.py +22 -0
- java_codebase_rag/ast/ast_kotlin.py +1794 -0
- java_codebase_rag/ast/chunk_heuristics.py +26 -5
- java_codebase_rag/ast/language.py +117 -0
- java_codebase_rag/cli.py +17 -17
- java_codebase_rag/cli_dispatch.py +251 -0
- java_codebase_rag/config.py +8 -8
- java_codebase_rag/eval/runner.py +3 -3
- java_codebase_rag/graph/build_ast_graph.py +130 -8
- java_codebase_rag/graph/graph_enrich.py +8 -5
- java_codebase_rag/graph/ladybug_queries.py +1 -1
- java_codebase_rag/graph/path_filtering.py +39 -7
- java_codebase_rag/index/java_index_flow_lancedb.py +160 -15
- java_codebase_rag/install_data/agents/explorer-rag-cli.md +6 -4
- java_codebase_rag/install_data/agents/explorer-rag-enhanced.md +4 -4
- java_codebase_rag/install_data/skills/explore-codebase/SKILL.md +4 -4
- java_codebase_rag/install_data/skills/explore-codebase-cli/SKILL.md +5 -5
- java_codebase_rag/installer.py +15 -15
- java_codebase_rag/jrag.py +25 -11
- java_codebase_rag/lance_optimize.py +7 -7
- java_codebase_rag/mcp/mcp_v2.py +2 -2
- java_codebase_rag/mcp/server.py +6 -4
- java_codebase_rag/pipeline.py +4 -4
- java_codebase_rag/progress.py +1 -1
- java_codebase_rag/search/search_lexical.py +1 -1
- java_codebase_rag/search/search_scoring.py +19 -5
- java_codebase_rag/watch/lock.py +1 -1
- java_codebase_rag/watch/watcher.py +45 -21
- {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/METADATA +31 -22
- {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/RECORD +36 -32
- java_codebase_rag-0.12.0.dist-info/entry_points.txt +5 -0
- java_codebase_rag-0.11.2.dist-info/entry_points.txt +0 -4
- {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/WHEEL +0 -0
- {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/licenses/LICENSE +0 -0
- {java_codebase_rag-0.11.2.dist-info → java_codebase_rag-0.12.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Legacy-alias deprecation notice for the ``jrag`` rename.
|
|
2
|
+
|
|
3
|
+
The tool is being renamed from ``java-codebase-rag`` to ``jrag``. The legacy
|
|
4
|
+
command aliases (``java-codebase-rag`` and ``java-codebase-rag-mcp``) continue
|
|
5
|
+
to work; when invoked through one of them in an interactive context, this
|
|
6
|
+
helper emits a single-line notice pointing the operator at the new name.
|
|
7
|
+
|
|
8
|
+
Suppression rule
|
|
9
|
+
----------------
|
|
10
|
+
The notice is suppressed when **either** of the following holds:
|
|
11
|
+
|
|
12
|
+
* ``$JRAG_NO_DEPRECATION`` is present and non-empty — any non-empty value
|
|
13
|
+
suppresses (so ``"1"``, ``"0"``, ``"false"``, ``"yes"`` all suppress; the
|
|
14
|
+
empty string and an unset variable do not). The simpler "present and
|
|
15
|
+
non-empty" rule is preferred over parsing truthy values so that operators
|
|
16
|
+
can shut the notice up with whatever value is easiest to reach for.
|
|
17
|
+
* ``sys.stderr.isatty()`` is false (or ``sys.stderr`` lacks ``isatty``) — i.e.
|
|
18
|
+
non-interactive contexts: piped, redirected, or captured stderr. Under real
|
|
19
|
+
MCP use stderr is not a TTY, so the call is silent in production; it exists
|
|
20
|
+
for the rare human-debug case.
|
|
21
|
+
|
|
22
|
+
This module is stdlib-only and import-light: it runs at MCP-server startup and
|
|
23
|
+
before ``--help``, so it must not pull in any backend (cli, search, mcp) code.
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
|
|
30
|
+
_LEGACY_ALIASES = frozenset({"java-codebase-rag", "java-codebase-rag-mcp"})
|
|
31
|
+
|
|
32
|
+
_DEPRECATION_LINE = (
|
|
33
|
+
"jrag: 'java-codebase-rag' is now 'jrag'; this alias continues to work. "
|
|
34
|
+
"Set JRAG_NO_DEPRECATION=1 to silence.\n"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
#: Executable suffixes appended by Windows (and packaging tools like pip) to
|
|
38
|
+
#: console-script wrappers. All three are exactly 4 characters long (``.exe``,
|
|
39
|
+
#: ``.bat``, ``.cmd``) so a single ``b[:-4]`` slice strips any of them. Stripping
|
|
40
|
+
#: keeps routing decisions stable across POSIX and Windows installs:
|
|
41
|
+
#: ``C:\\Users\\foo\\Scripts\\jrag.exe`` → ``"jrag"``;
|
|
42
|
+
#: ``...\\java-codebase-rag.exe`` → ``"java-codebase-rag"``.
|
|
43
|
+
_WINDOWS_EXE_SUFFIXES: tuple[str, ...] = (".exe", ".bat", ".cmd")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _invoked_program_name() -> str:
|
|
47
|
+
"""Basename of ``sys.argv[0]`` with a Windows executable suffix stripped.
|
|
48
|
+
|
|
49
|
+
Returns the empty string when ``sys.argv`` is empty. Otherwise takes
|
|
50
|
+
``os.path.basename(sys.argv[0])`` and, if it ends (case-insensitively) with
|
|
51
|
+
one of ``.exe`` / ``.bat`` / ``.cmd``, drops the 4-character suffix.
|
|
52
|
+
|
|
53
|
+
Shared with :mod:`java_codebase_rag.cli_dispatch` for identity-default
|
|
54
|
+
routing: both legacy-alias deprecation here and ``jrag``-vs-alias routing
|
|
55
|
+
there rely on the same canonicalized basename. Without this, Windows builds
|
|
56
|
+
would route ``jrag.exe --version`` through the wrong parser and never emit
|
|
57
|
+
the deprecation notice for ``java-codebase-rag.exe``.
|
|
58
|
+
"""
|
|
59
|
+
argv = sys.argv
|
|
60
|
+
if not argv:
|
|
61
|
+
return ""
|
|
62
|
+
base = os.path.basename(argv[0])
|
|
63
|
+
if base.lower().endswith(_WINDOWS_EXE_SUFFIXES):
|
|
64
|
+
return base[:-4]
|
|
65
|
+
return base
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _stderr_is_tty() -> bool:
|
|
69
|
+
"""True iff ``sys.stderr`` reports itself as a TTY.
|
|
70
|
+
|
|
71
|
+
Defensive against stderr replacements that omit ``isatty``.
|
|
72
|
+
"""
|
|
73
|
+
stderr = sys.stderr
|
|
74
|
+
return hasattr(stderr, "isatty") and stderr.isatty()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _suppressed() -> bool:
|
|
78
|
+
"""True iff the notice should be suppressed."""
|
|
79
|
+
if os.environ.get("JRAG_NO_DEPRECATION"):
|
|
80
|
+
return True
|
|
81
|
+
return not _stderr_is_tty()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def maybe_warn_legacy_alias(stream=None) -> None:
|
|
85
|
+
"""Emit a one-line legacy-alias deprecation notice when appropriate.
|
|
86
|
+
|
|
87
|
+
Detects a legacy invocation (``sys.argv[0]`` basename is exactly
|
|
88
|
+
``java-codebase-rag`` or ``java-codebase-rag-mcp``) and, if not suppressed,
|
|
89
|
+
writes a single line to ``stream`` (defaulting to ``sys.stderr``). Never
|
|
90
|
+
raises: any error inside the write is swallowed so the rename helper can
|
|
91
|
+
never break tool startup.
|
|
92
|
+
|
|
93
|
+
See module docstring for the suppression rule.
|
|
94
|
+
"""
|
|
95
|
+
if _invoked_program_name() not in _LEGACY_ALIASES:
|
|
96
|
+
return
|
|
97
|
+
if _suppressed():
|
|
98
|
+
return
|
|
99
|
+
target = stream if stream is not None else sys.stderr
|
|
100
|
+
try:
|
|
101
|
+
target.write(_DEPRECATION_LINE)
|
|
102
|
+
except Exception: # pragma: no cover - defensive: never break startup
|
|
103
|
+
return
|
java_codebase_rag/_version.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Version string for the CLI ``--version`` flag.
|
|
2
2
|
|
|
3
3
|
The single source of truth is the installed distribution metadata
|
|
4
|
-
(``
|
|
4
|
+
(``jrag-cli`` in pyproject.toml), read via :mod:`importlib.metadata`
|
|
5
5
|
so a pyproject bump propagates with no second hardcoded copy.
|
|
6
6
|
:func:`version_string` appends the CPython version for the
|
|
7
7
|
``<prog> <version> (python <x.y.z>)`` format chosen for the ``--version`` flag.
|
|
@@ -15,7 +15,7 @@ import platform
|
|
|
15
15
|
from importlib.metadata import PackageNotFoundError
|
|
16
16
|
from importlib.metadata import version as _dist_version
|
|
17
17
|
|
|
18
|
-
_PACKAGE = "
|
|
18
|
+
_PACKAGE = "jrag-cli"
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def package_version() -> str:
|
|
@@ -249,6 +249,11 @@ class AnnotationRef:
|
|
|
249
249
|
container_capability_values: tuple[str, ...] = field(default_factory=tuple)
|
|
250
250
|
# Entry-aligned with `container_capability_values`; each value is "enum" | "string".
|
|
251
251
|
container_capability_kinds: tuple[str, ...] = field(default_factory=tuple)
|
|
252
|
+
# Kotlin use-site target (one of "field"|"get"|"set"|"param"|"property"|"file") or
|
|
253
|
+
# None. Java ``parse_java`` always leaves this None — Java has no use-site targets.
|
|
254
|
+
# This is an AST-level field (not a persisted graph column); it drives Kotlin-only
|
|
255
|
+
# routing of an annotation to the FieldDecl / accessor MethodDecl / ParamDecl slot.
|
|
256
|
+
use_site_target: str | None = None
|
|
252
257
|
|
|
253
258
|
|
|
254
259
|
@dataclass
|
|
@@ -394,11 +399,26 @@ class JavaFileAst:
|
|
|
394
399
|
explicit_imports: dict[str, str] # "List" -> "java.util.List"
|
|
395
400
|
top_level_types: list[TypeDecl]
|
|
396
401
|
all_types: list[TypeDecl] # flat, includes nested
|
|
402
|
+
# Language-dispatch seam (Task 1). Required — no default — so every
|
|
403
|
+
# construction site names the language explicitly. Validated against the
|
|
404
|
+
# registry in ``language.KNOWN_LANGUAGE_IDS``. Lazily imported inside
|
|
405
|
+
# ``__post_init__`` to avoid a module-load cycle (``language`` imports
|
|
406
|
+
# ``JavaFileAst``/``parse_java`` from this module).
|
|
407
|
+
language: str
|
|
397
408
|
parse_error: bool = False
|
|
398
409
|
source_bytes: int = 0
|
|
399
410
|
file_imports: FileImports = field(default_factory=FileImports)
|
|
400
411
|
routes_skipped_unresolved: int = 0
|
|
401
412
|
|
|
413
|
+
def __post_init__(self) -> None:
|
|
414
|
+
from .language import KNOWN_LANGUAGE_IDS
|
|
415
|
+
|
|
416
|
+
if self.language not in KNOWN_LANGUAGE_IDS:
|
|
417
|
+
raise ValueError(
|
|
418
|
+
f"Unknown language id {self.language!r}; "
|
|
419
|
+
f"expected one of {sorted(KNOWN_LANGUAGE_IDS)}"
|
|
420
|
+
)
|
|
421
|
+
|
|
402
422
|
|
|
403
423
|
@dataclass
|
|
404
424
|
class _ParseCtx:
|
|
@@ -2625,6 +2645,7 @@ def parse_java(source: bytes | str, *, filename: str = "", verbose: bool = False
|
|
|
2625
2645
|
explicit_imports={},
|
|
2626
2646
|
top_level_types=[],
|
|
2627
2647
|
all_types=[],
|
|
2648
|
+
language="java",
|
|
2628
2649
|
parse_error=False,
|
|
2629
2650
|
source_bytes=len(src),
|
|
2630
2651
|
file_imports=FileImports(),
|
|
@@ -2710,6 +2731,7 @@ def parse_java(source: bytes | str, *, filename: str = "", verbose: bool = False
|
|
|
2710
2731
|
explicit_imports=explicit_imports,
|
|
2711
2732
|
top_level_types=top_types,
|
|
2712
2733
|
all_types=all_types,
|
|
2734
|
+
language="java",
|
|
2713
2735
|
parse_error=root.has_error,
|
|
2714
2736
|
source_bytes=len(src),
|
|
2715
2737
|
file_imports=file_imports,
|