java-codebase-rag 0.9.4__py3-none-any.whl → 0.9.5__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.
- absence_diagnosis.py +700 -0
- absence_types.py +124 -0
- absence_vocab.py +455 -0
- ast_java.py +1 -1
- build_ast_graph.py +85 -7
- graph_enrich.py +245 -0
- graph_types.py +4 -0
- java_codebase_rag/cli.py +1 -6
- java_codebase_rag/config.py +116 -0
- java_codebase_rag/jrag.py +56 -1
- java_codebase_rag/jrag_envelope.py +10 -1
- java_codebase_rag/jrag_render.py +67 -3
- java_codebase_rag/pipeline.py +10 -0
- {java_codebase_rag-0.9.4.dist-info → java_codebase_rag-0.9.5.dist-info}/METADATA +2 -2
- {java_codebase_rag-0.9.4.dist-info → java_codebase_rag-0.9.5.dist-info}/RECORD +27 -22
- {java_codebase_rag-0.9.4.dist-info → java_codebase_rag-0.9.5.dist-info}/top_level.txt +5 -0
- java_index_flow_lancedb.py +27 -7
- ladybug_queries.py +4 -4
- mcp_v2.py +272 -73
- resolve_service.py +69 -2
- search_lancedb.py +50 -311
- search_lexical.py +329 -0
- search_scoring.py +338 -0
- server.py +101 -34
- {java_codebase_rag-0.9.4.dist-info → java_codebase_rag-0.9.5.dist-info}/WHEEL +0 -0
- {java_codebase_rag-0.9.4.dist-info → java_codebase_rag-0.9.5.dist-info}/entry_points.txt +0 -0
- {java_codebase_rag-0.9.4.dist-info → java_codebase_rag-0.9.5.dist-info}/licenses/LICENSE +0 -0
java_codebase_rag/jrag.py
CHANGED
|
@@ -1163,6 +1163,20 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1163
1163
|
)
|
|
1164
1164
|
search.set_defaults(handler=_cmd_search, auto_scope=True)
|
|
1165
1165
|
|
|
1166
|
+
# ---- vocab-index subparser (PR-ABS-1) ----
|
|
1167
|
+
vocab_index = subparsers.add_parser(
|
|
1168
|
+
"vocab-index",
|
|
1169
|
+
help="Rebuild the vocabulary index (absence diagnosis).",
|
|
1170
|
+
parents=[_core_parser()],
|
|
1171
|
+
description=(
|
|
1172
|
+
"Rebuild the vocabulary index sidecar from the current Ladybug graph. "
|
|
1173
|
+
"The index is a search-optimized projection of Symbol nodes used for "
|
|
1174
|
+
"did-you-mean suggestions and external membership checks in absence "
|
|
1175
|
+
"diagnosis. Printed on success: symbol count and sidecar path."
|
|
1176
|
+
),
|
|
1177
|
+
)
|
|
1178
|
+
vocab_index.set_defaults(handler=_cmd_vocab_index, detail="full")
|
|
1179
|
+
|
|
1166
1180
|
return parser
|
|
1167
1181
|
|
|
1168
1182
|
|
|
@@ -1217,6 +1231,40 @@ def _load_graph(cfg): # type: ignore[no-untyped-def]
|
|
|
1217
1231
|
raise _IndexStale(str(exc)) from exc
|
|
1218
1232
|
|
|
1219
1233
|
|
|
1234
|
+
def _cmd_vocab_index(args: argparse.Namespace) -> int:
|
|
1235
|
+
"""Rebuild the vocabulary index sidecar from the Ladybug graph."""
|
|
1236
|
+
from ast_java import ONTOLOGY_VERSION
|
|
1237
|
+
from absence_vocab import VocabularyIndex, VOCAB_INDEX_FILENAME
|
|
1238
|
+
|
|
1239
|
+
cfg = _resolve_cfg(args)
|
|
1240
|
+
try:
|
|
1241
|
+
graph = _load_graph(cfg)
|
|
1242
|
+
except (_IndexNotFound, _IndexStale) as exc:
|
|
1243
|
+
print(f"[error] {exc}", file=sys.stderr)
|
|
1244
|
+
return 2
|
|
1245
|
+
|
|
1246
|
+
# Build vocabulary index
|
|
1247
|
+
try:
|
|
1248
|
+
index = VocabularyIndex.build(graph, q=cfg.absence_ngram_q)
|
|
1249
|
+
except Exception as e:
|
|
1250
|
+
print(f"[error] Vocabulary index build failed: {e}", file=sys.stderr)
|
|
1251
|
+
return 1
|
|
1252
|
+
|
|
1253
|
+
# Save to sidecar
|
|
1254
|
+
sidecar_path = cfg.ladybug_path.parent / VOCAB_INDEX_FILENAME
|
|
1255
|
+
try:
|
|
1256
|
+
index.save(sidecar_path, ontology_version=ONTOLOGY_VERSION)
|
|
1257
|
+
except Exception as e:
|
|
1258
|
+
print(f"[error] Failed to save vocabulary index: {e}", file=sys.stderr)
|
|
1259
|
+
return 1
|
|
1260
|
+
|
|
1261
|
+
# Print success message (simple format for admin command)
|
|
1262
|
+
print(f"Vocabulary index rebuilt successfully:")
|
|
1263
|
+
print(f" Symbol count: {index.symbol_count}")
|
|
1264
|
+
print(f" Sidecar path: {sidecar_path}")
|
|
1265
|
+
return 0
|
|
1266
|
+
|
|
1267
|
+
|
|
1220
1268
|
def _cmd_status(args: argparse.Namespace) -> int:
|
|
1221
1269
|
from java_codebase_rag.jrag_envelope import Envelope
|
|
1222
1270
|
from java_codebase_rag.jrag_render import render
|
|
@@ -4321,13 +4369,20 @@ def _cmd_search(args: argparse.Namespace) -> int:
|
|
|
4321
4369
|
d["kind"] = "search_hit"
|
|
4322
4370
|
# Add explain token when --explain is set
|
|
4323
4371
|
if args.explain:
|
|
4324
|
-
|
|
4372
|
+
# search_lancedb is unimportable on graph-only (macOS Intel) installs —
|
|
4373
|
+
# lancedb/sentence-transformers are excluded by the PEP 508 markers in
|
|
4374
|
+
# pyproject.toml, and this module imports them at module top. Importing the
|
|
4375
|
+
# explain renderer from there would crash `jrag search ... --explain` on the
|
|
4376
|
+
# exact Intel install that runs the lexical path. search_scoring is
|
|
4377
|
+
# dependency-free and always installed, so the explain import works everywhere.
|
|
4378
|
+
from search_scoring import explain_score_components
|
|
4325
4379
|
comps = d.get("score_components")
|
|
4326
4380
|
d["explain"] = explain_score_components(
|
|
4327
4381
|
comps,
|
|
4328
4382
|
role=d.get("role"),
|
|
4329
4383
|
hybrid=bool(args.hybrid),
|
|
4330
4384
|
graph_expanded=False,
|
|
4385
|
+
lexical=bool(getattr(out, "lexical_mode", False)),
|
|
4331
4386
|
)
|
|
4332
4387
|
hit_dicts.append(d)
|
|
4333
4388
|
|
|
@@ -18,6 +18,7 @@ import re
|
|
|
18
18
|
from dataclasses import dataclass, field
|
|
19
19
|
from typing import Any, Literal
|
|
20
20
|
|
|
21
|
+
from absence_types import AbsenceDiagnosis
|
|
21
22
|
from graph_types import NodeRef
|
|
22
23
|
|
|
23
24
|
__all__ = [
|
|
@@ -118,6 +119,9 @@ class Envelope:
|
|
|
118
119
|
# zero in-repo callers. Distinguishes the *correct* empty result ("external
|
|
119
120
|
# entrypoint — no in-repo callers") from a bug-looking bare "0 callers".
|
|
120
121
|
is_external_entrypoint: bool = False
|
|
122
|
+
# Absence diagnosis explaining why a result is empty (PR-ABS-4). Carried
|
|
123
|
+
# from MCP outputs and rendered in CLI text/JSON. None on ok/ambiguous.
|
|
124
|
+
absence: AbsenceDiagnosis | None = None
|
|
121
125
|
|
|
122
126
|
def to_dict(self) -> dict[str, Any]:
|
|
123
127
|
"""Serialize to a JSON-ready dict, omitting empty optionals.
|
|
@@ -151,6 +155,8 @@ class Envelope:
|
|
|
151
155
|
out["message"] = self.message
|
|
152
156
|
if self.is_external_entrypoint:
|
|
153
157
|
out["is_external_entrypoint"] = True
|
|
158
|
+
if self.absence is not None:
|
|
159
|
+
out["absence"] = self.absence.model_dump()
|
|
154
160
|
return out
|
|
155
161
|
|
|
156
162
|
def to_json(self) -> str:
|
|
@@ -237,6 +243,8 @@ class Envelope:
|
|
|
237
243
|
out["message"] = self.message
|
|
238
244
|
if self.is_external_entrypoint:
|
|
239
245
|
out["is_external_entrypoint"] = True
|
|
246
|
+
if self.absence is not None:
|
|
247
|
+
out["absence"] = self.absence.model_dump()
|
|
240
248
|
return out
|
|
241
249
|
|
|
242
250
|
@staticmethod
|
|
@@ -610,7 +618,7 @@ def resolve_query(
|
|
|
610
618
|
# the agent-facing CLI).
|
|
611
619
|
if "jrag search" not in raw_msg:
|
|
612
620
|
raw_msg = f"{raw_msg} Use `jrag search <query>` for ranked fuzzy lookup."
|
|
613
|
-
return None, Envelope(status="not_found", message=raw_msg)
|
|
621
|
+
return None, Envelope(status="not_found", message=raw_msg, absence=out.absence)
|
|
614
622
|
|
|
615
623
|
|
|
616
624
|
# Listing breadcrumbs (root is None): 1–2 template hints pointing at the natural
|
|
@@ -1082,4 +1090,5 @@ def project_envelope(envelope: Envelope, detail: str) -> Envelope:
|
|
|
1082
1090
|
file_location=envelope.file_location,
|
|
1083
1091
|
message=envelope.message,
|
|
1084
1092
|
is_external_entrypoint=envelope.is_external_entrypoint,
|
|
1093
|
+
absence=envelope.absence,
|
|
1085
1094
|
)
|
java_codebase_rag/jrag_render.py
CHANGED
|
@@ -12,6 +12,7 @@ from __future__ import annotations
|
|
|
12
12
|
|
|
13
13
|
from typing import Any
|
|
14
14
|
|
|
15
|
+
from absence_types import AbsenceDiagnosis
|
|
15
16
|
from java_codebase_rag.jrag_envelope import Envelope, project_envelope, simple_name
|
|
16
17
|
|
|
17
18
|
__all__ = ["render", "tiered_name", "display_name"]
|
|
@@ -32,6 +33,23 @@ _CALLS_FAMILY_EDGES = frozenset({"CALLS", "HTTP_CALLS", "ASYNC_CALLS"})
|
|
|
32
33
|
# none) and are left untagged.
|
|
33
34
|
_ROUTE_KIND_TAGS: dict[str, str] = {"kafka_topic": "kafka", "http_endpoint": "http"}
|
|
34
35
|
|
|
36
|
+
# Absence verdict → human-readable label, shared by the not-found / listing /
|
|
37
|
+
# traversal empty-result renderers. ``AbsenceVerdict`` is a closed Literal of
|
|
38
|
+
# these four values.
|
|
39
|
+
_ABSENCE_VERDICT_TEXT: dict[str, str] = {
|
|
40
|
+
"not_in_project": "not in project",
|
|
41
|
+
"external_dependency": "external dependency",
|
|
42
|
+
"refine_query": "refine your query",
|
|
43
|
+
"correct_empty": "correct empty",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _verdict_line(absence: AbsenceDiagnosis) -> str | None:
|
|
48
|
+
"""A ``Verdict: <label>`` line for an absence diagnosis, or ``None`` if the
|
|
49
|
+
verdict is not one of the known values."""
|
|
50
|
+
text = _ABSENCE_VERDICT_TEXT.get(absence.verdict)
|
|
51
|
+
return f"Verdict: {text}" if text else None
|
|
52
|
+
|
|
35
53
|
# Identity keys already represented in a listing line (display_name + @service +
|
|
36
54
|
# kind tag). At ``--detail full`` the per-row kv-block skips these (they are in
|
|
37
55
|
# the header line) and renders every OTHER key, so full listing == per-row
|
|
@@ -226,7 +244,35 @@ def _render_error(envelope: Envelope) -> str:
|
|
|
226
244
|
|
|
227
245
|
def _render_not_found(envelope: Envelope) -> str:
|
|
228
246
|
msg = envelope.message or "not found"
|
|
229
|
-
|
|
247
|
+
base = f"not found: {msg}"
|
|
248
|
+
|
|
249
|
+
# If absence diagnosis is present, append verdict + message (+ did-you-mean)
|
|
250
|
+
if envelope.absence is not None:
|
|
251
|
+
lines = [base]
|
|
252
|
+
# Verdict line (human-readable label)
|
|
253
|
+
vline = _verdict_line(envelope.absence)
|
|
254
|
+
if vline:
|
|
255
|
+
lines.append(vline)
|
|
256
|
+
|
|
257
|
+
# Per-cause explanation message — surfaces the diagnosis's authored help
|
|
258
|
+
# (external-identity context, filter-relaxation suggestions, etc.).
|
|
259
|
+
if envelope.absence.message:
|
|
260
|
+
lines.append(envelope.absence.message)
|
|
261
|
+
|
|
262
|
+
# Add did-you-mean line if closest_symbols is non-empty
|
|
263
|
+
if envelope.absence.closest_symbols:
|
|
264
|
+
symbols = [s.fqn for s in envelope.absence.closest_symbols]
|
|
265
|
+
if len(symbols) == 1:
|
|
266
|
+
lines.append(f"Did you mean: {symbols[0]}?")
|
|
267
|
+
elif len(symbols) == 2:
|
|
268
|
+
lines.append(f"Did you mean: {symbols[0]} or {symbols[1]}?")
|
|
269
|
+
else:
|
|
270
|
+
joined = ", ".join(symbols[:-1]) + f", or {symbols[-1]}"
|
|
271
|
+
lines.append(f"Did you mean: {joined}?")
|
|
272
|
+
|
|
273
|
+
return "\n".join(lines)
|
|
274
|
+
|
|
275
|
+
return base
|
|
230
276
|
|
|
231
277
|
|
|
232
278
|
def _render_listing(envelope: Envelope, *, noun: str, detail: str = "normal") -> str:
|
|
@@ -295,7 +341,12 @@ def _render_listing(envelope: Envelope, *, noun: str, detail: str = "normal") ->
|
|
|
295
341
|
if rest:
|
|
296
342
|
lines.extend(_render_inspect_block(rest, 1))
|
|
297
343
|
if not lines:
|
|
298
|
-
|
|
344
|
+
# Handle absence diagnosis (PR-ABS-4)
|
|
345
|
+
if envelope.absence is not None:
|
|
346
|
+
vline = _verdict_line(envelope.absence)
|
|
347
|
+
lines.append(vline if vline else f"0 {noun}".rstrip())
|
|
348
|
+
else:
|
|
349
|
+
lines.append(f"0 {noun}".rstrip())
|
|
299
350
|
# Listing breadcrumbs (Phase 2): <=2 `next:` hint lines when the listing
|
|
300
351
|
# command emitted agent_next_actions (routes/clients/producers/topics).
|
|
301
352
|
lines.extend(_next_action_lines(envelope))
|
|
@@ -413,10 +464,23 @@ def _render_traversal(envelope: Envelope, *, noun: str, detail: str = "normal")
|
|
|
413
464
|
root_node = envelope.nodes.get(root_id, {})
|
|
414
465
|
root_fqn = str(root_node.get("fqn") or "").strip()
|
|
415
466
|
root_svc = str(root_node.get("microservice") or "").strip()
|
|
416
|
-
|
|
467
|
+
|
|
468
|
+
# Handle absence diagnosis (PR-ABS-4)
|
|
469
|
+
if envelope.absence is not None:
|
|
470
|
+
absence = envelope.absence
|
|
471
|
+
if absence.verdict == "correct_empty":
|
|
472
|
+
# Same text as the is_external_entrypoint case.
|
|
473
|
+
parts = ["external entrypoint — no in-repo callers"]
|
|
474
|
+
else:
|
|
475
|
+
vline = _verdict_line(absence)
|
|
476
|
+
if vline:
|
|
477
|
+
lines.append(vline)
|
|
478
|
+
parts = [f"0 {noun}".rstrip()]
|
|
479
|
+
elif envelope.is_external_entrypoint:
|
|
417
480
|
parts = ["external entrypoint — no in-repo callers"]
|
|
418
481
|
else:
|
|
419
482
|
parts = [f"0 {noun}".rstrip()]
|
|
483
|
+
|
|
420
484
|
if root_fqn:
|
|
421
485
|
parts.append(root_fqn)
|
|
422
486
|
if root_svc:
|
java_codebase_rag/pipeline.py
CHANGED
|
@@ -18,6 +18,16 @@ from java_codebase_rag.progress import ProgressEvent, ProgressRelay, make_relay
|
|
|
18
18
|
|
|
19
19
|
COCOINDEX_TARGET = "java_index_flow_lancedb.py:JavaCodeIndexLance"
|
|
20
20
|
|
|
21
|
+
# Operator-facing line printed when an indexing command skips the vectors phase
|
|
22
|
+
# because the vector stack is absent (graph-only install, e.g. macOS Intel where
|
|
23
|
+
# cocoindex[lancedb]/lancedb/sentence-transformers are gated off by PEP 508 markers).
|
|
24
|
+
# Single source of truth — imported by cli.py (init/increment) and server.py
|
|
25
|
+
# (reprocess) so the wording can't drift between the two paths.
|
|
26
|
+
VECTORS_SKIPPED_GRAPH_ONLY = (
|
|
27
|
+
"java-codebase-rag: vectors skipped — vector stack not installed on this platform "
|
|
28
|
+
"(graph-only mode). The graph is built/refreshed; semantic search is unavailable."
|
|
29
|
+
)
|
|
30
|
+
|
|
21
31
|
|
|
22
32
|
def bundle_dir() -> Path:
|
|
23
33
|
return Path(__file__).resolve().parent.parent
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: java-codebase-rag
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.5
|
|
4
4
|
Summary: MCP server for semantic + structural search over Java codebases
|
|
5
5
|
Author: HumanBean17
|
|
6
6
|
License-Expression: MIT
|
|
@@ -86,7 +86,7 @@ The rest of this README is the install, the tool/command orientation, and the re
|
|
|
86
86
|
pip install java-codebase-rag
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
Python **3.11+** required, on **Linux, macOS, and Windows**. On Linux, Windows, and **Apple Silicon** Macs every native dependency (LanceDB, LadybugDB/kuzu, CocoIndex) ships a wheel and you get the full semantic + graph search. **Intel Macs (x86_64) install graph-only**: PyTorch ≥2.3 and LanceDB ≥0.26 dropped macOS Intel wheels, so the vector stack is auto-excluded via PEP 508 markers — `pip install java-codebase-rag` works out of the box, the graph layer (`find` / `describe` / `neighbors` / `resolve`) is fully usable, and the `search` (
|
|
89
|
+
Python **3.11+** required, on **Linux, macOS, and Windows**. On Linux, Windows, and **Apple Silicon** Macs every native dependency (LanceDB, LadybugDB/kuzu, CocoIndex) ships a wheel and you get the full semantic + graph search. **Intel Macs (x86_64) install graph-only**: PyTorch ≥2.3 and LanceDB ≥0.26 dropped macOS Intel wheels, so the vector stack is auto-excluded via PEP 508 markers — `pip install java-codebase-rag` works out of the box, the graph layer (`find` / `describe` / `neighbors` / `resolve`) is fully usable, and the `search` tool falls back to **lexical (keyword) search** over the symbol graph (same tool contract, keyword-ranked instead of semantic; an advisory notes the mode). Semantic/vector search needs Apple Silicon, Linux, or Windows. After install, `java-codebase-rag --help` should print the CLI groups.
|
|
90
90
|
The package includes the CocoIndex lifecycle dependency used by `init`, `increment`, `reprocess`, and `erase` on platforms that have it (it is absent on Intel Mac).
|
|
91
91
|
|
|
92
92
|
### Interactive setup (recommended)
|
|
@@ -1,44 +1,49 @@
|
|
|
1
|
-
|
|
1
|
+
absence_diagnosis.py,sha256=EorBpkVM5LRWxaTbmbQ3eo6Ew_V7r6enTgtXfcjqzfw,27533
|
|
2
|
+
absence_types.py,sha256=ukDy1GKgebCYdM0OYJ7a5xoI82M2wd0i0KEJwxQFGlo,4220
|
|
3
|
+
absence_vocab.py,sha256=yySRdonAR8hXv0YpTgvaUV0UzihvbvUuSoIXJa5WBiU,15897
|
|
4
|
+
ast_java.py,sha256=1E5XU5lsc1Ltyv96kSv5VNhRl_KRTsYeHG_qDLgPMcc,99419
|
|
2
5
|
brownfield_events.py,sha256=yxXkKDgMb3VPtaiakGzncHM_EGnda8xIue6w90yYp8s,2055
|
|
3
|
-
build_ast_graph.py,sha256=
|
|
6
|
+
build_ast_graph.py,sha256=scaC7TnmmmrjAv3R3qy_30kLb2DH4w7lznLxjDCntOs,176403
|
|
4
7
|
chunk_heuristics.py,sha256=aQk2NOKxzUdqoUAJUO3G3LE0MN_bYZWNLQ0tkmj5uts,1813
|
|
5
|
-
graph_enrich.py,sha256=
|
|
6
|
-
graph_types.py,sha256=
|
|
8
|
+
graph_enrich.py,sha256=CYc2K7Zw_CTefaJkL9h6nZmvw3uN8XbIkg4iYQ-ICY0,72528
|
|
9
|
+
graph_types.py,sha256=bf8EEkvWSyRxFQgycTnxxZQwlikLZSU3B-U1Z1cFQtg,4789
|
|
7
10
|
index_common.py,sha256=HT6FKHFJ084eFvd3fR1j8z8gf4eWoPHVW8GXLpw464I,285
|
|
8
|
-
java_index_flow_lancedb.py,sha256=
|
|
11
|
+
java_index_flow_lancedb.py,sha256=kZh8HgwtGV8Ul_pwdBS7g62hVvKkk8EXTk-qr6NNba8,29676
|
|
9
12
|
java_index_v1_common.py,sha256=nF1KrSqboF_RRvWerG9knRRFmWwsrG_CvhgnsoZ8KqA,1154
|
|
10
13
|
java_ontology.py,sha256=eUGFa96GV_09s2f2sWSMdqYmoxU3-1pyU2iipvcDjG0,17219
|
|
11
|
-
ladybug_queries.py,sha256=
|
|
14
|
+
ladybug_queries.py,sha256=SXXNcYxdXCHcQ6SBZdZyqAa-hv5_OFaKsfNx4zVtPgY,100688
|
|
12
15
|
mcp_hints.py,sha256=zp-4cnOmbYD0YovmZiLS2oGcvWcWE7n8jKVz4_xifno,42512
|
|
13
|
-
mcp_v2.py,sha256=
|
|
16
|
+
mcp_v2.py,sha256=Q69-0IOna1XRG06RcEFEsS-YucuBh60sAVIIDKoOnBc,76688
|
|
14
17
|
path_filtering.py,sha256=R--XzI51LXBu5IBKMCnJWbkNr6I5d-SDmltyQQnWco0,17674
|
|
15
18
|
pr_analysis.py,sha256=zrmZZD5yotJtM02Kif6_jgI_oeformOao793akp0N6Y,18394
|
|
16
|
-
resolve_service.py,sha256=
|
|
17
|
-
search_lancedb.py,sha256=
|
|
18
|
-
|
|
19
|
+
resolve_service.py,sha256=EAfWlGQ4U1qKoPCfZ7BZUUy8pm0w9tldga3Krw0_GO4,28543
|
|
20
|
+
search_lancedb.py,sha256=LmratGpyEKcCYohXVTapjGd-rk_kryS93oD43foGZeQ,34486
|
|
21
|
+
search_lexical.py,sha256=6U0SgRH36Qmh3IIPzMi553ztW7MCnCvg5cSlMpxIdu8,14250
|
|
22
|
+
search_scoring.py,sha256=SSs2GLvHCB_gsKPo0N-YPGeAVNWx-TsXXPJO2JPsOOY,12321
|
|
23
|
+
server.py,sha256=SWh7hZshzVuhYqEm6Leq1GS2VP6olml4dz9nrGwf-KM,39889
|
|
19
24
|
java_codebase_rag/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
20
25
|
java_codebase_rag/_fdlimit.py,sha256=vkwjsPbZfxzZ2DZTPWO5DxtuNlLzOADzIq07iYX7GCU,2465
|
|
21
26
|
java_codebase_rag/_stdio.py,sha256=TDNbpt2EP0_Zd622ihdlKwlMfxkKHWOfgLVcU6TcNbo,1458
|
|
22
27
|
java_codebase_rag/_version.py,sha256=Dnoh_a-c13fqPQ-HV9CsSPbFUkihUJl_z5CACW4qDyA,1365
|
|
23
|
-
java_codebase_rag/cli.py,sha256=
|
|
28
|
+
java_codebase_rag/cli.py,sha256=LcNgfOS7r8_vTckuyUbUxI7bhUyYoU_iwzUb37nT5Ts,45296
|
|
24
29
|
java_codebase_rag/cli_format.py,sha256=CT7-xdwZ0bMCdP68_UOwkvm-mnLluU3LutlM-mDNk60,1839
|
|
25
30
|
java_codebase_rag/cli_progress.py,sha256=q6Wh97yzLGs1B8UFk_WAKivfQu7Y5RnUUE-T2YHWkIs,3237
|
|
26
|
-
java_codebase_rag/config.py,sha256=
|
|
31
|
+
java_codebase_rag/config.py,sha256=VPs69os_3co3UPSoBVhpfoVnqDaPJ6Ycbk8A4AyXZOo,30548
|
|
27
32
|
java_codebase_rag/installer.py,sha256=c-_tR1Ct_O3yhmruFRnDoM1Wilz-igD9qdkDPsNqLMI,79934
|
|
28
|
-
java_codebase_rag/jrag.py,sha256=
|
|
29
|
-
java_codebase_rag/jrag_envelope.py,sha256=
|
|
33
|
+
java_codebase_rag/jrag.py,sha256=XJN1ejEwxLpTrDJW4lyPjdhP21m7ZRv-JZh73aQDc14,199393
|
|
34
|
+
java_codebase_rag/jrag_envelope.py,sha256=cTe-2lk8-Fvmo9_Ps6rN0QtBSw4muSD_UXvm_rkUc48,47984
|
|
30
35
|
java_codebase_rag/jrag_hints.py,sha256=k2PFE4s3lZgBYHMdZcTjx1-w28nfQcBtQEVsSxI_DvE,9262
|
|
31
|
-
java_codebase_rag/jrag_render.py,sha256=
|
|
36
|
+
java_codebase_rag/jrag_render.py,sha256=MYPyiB7JiQrSw_KHMjCdWg9JuaxpO3Pv_FI4W7bG8sQ,34917
|
|
32
37
|
java_codebase_rag/lance_optimize.py,sha256=HI3aFebP1fenLL6Cav1jMG5kLXSrHLndO_MIJY6qQVo,11977
|
|
33
|
-
java_codebase_rag/pipeline.py,sha256=
|
|
38
|
+
java_codebase_rag/pipeline.py,sha256=OCqBVjkGZOCvzmBElKMes6ynYn9dSN9J1bhRFyEceVE,18355
|
|
34
39
|
java_codebase_rag/progress.py,sha256=2IxdMALDM0wAQCyJrrfZ975zM_85C-4BfHxf4AtYifE,23212
|
|
35
40
|
java_codebase_rag/install_data/agents/explorer-rag-cli.md,sha256=bVmmzrBSSamMz7hDIKxL5alAZOXsJ_Km8TQnCcxDad0,10292
|
|
36
41
|
java_codebase_rag/install_data/agents/explorer-rag-enhanced.md,sha256=gZsNFbuK0lSnOIlplbbS_muz2ozokJqvFUv65QM0NDM,10406
|
|
37
42
|
java_codebase_rag/install_data/skills/explore-codebase/SKILL.md,sha256=A-v2dueVnxwBzBlxoRjZ2zOJk8DranLQ1TElwn94h0s,11529
|
|
38
43
|
java_codebase_rag/install_data/skills/explore-codebase-cli/SKILL.md,sha256=K2qwZqk2xPxjPxXtUHvax1Ug2J7nBYeMTIjRznO100g,10059
|
|
39
|
-
java_codebase_rag-0.9.
|
|
40
|
-
java_codebase_rag-0.9.
|
|
41
|
-
java_codebase_rag-0.9.
|
|
42
|
-
java_codebase_rag-0.9.
|
|
43
|
-
java_codebase_rag-0.9.
|
|
44
|
-
java_codebase_rag-0.9.
|
|
44
|
+
java_codebase_rag-0.9.5.dist-info/licenses/LICENSE,sha256=gxvtiHtuviR_q8ZAjWw-QTcF3DyPzg6ZY-lQrr8OPpw,1068
|
|
45
|
+
java_codebase_rag-0.9.5.dist-info/METADATA,sha256=cxCb0ljrq1h-E0nS7d7WI8t8LTQwUpIcYNwZXgUkMjM,20331
|
|
46
|
+
java_codebase_rag-0.9.5.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
47
|
+
java_codebase_rag-0.9.5.dist-info/entry_points.txt,sha256=cj3QTc11UYVQnj9T3orc4daiIGaCYrXP149vKbH2R4U,168
|
|
48
|
+
java_codebase_rag-0.9.5.dist-info/top_level.txt,sha256=gYhQnlcJKpqwIOTwAneruJrkeBzIjoC71LeHMGMZLAY,349
|
|
49
|
+
java_codebase_rag-0.9.5.dist-info/RECORD,,
|
java_index_flow_lancedb.py
CHANGED
|
@@ -51,7 +51,13 @@ from java_index_v1_common import (
|
|
|
51
51
|
)
|
|
52
52
|
from path_filtering import LayeredIgnore
|
|
53
53
|
from ast_java import ONTOLOGY_VERSION, parse_java
|
|
54
|
-
from graph_enrich import
|
|
54
|
+
from graph_enrich import (
|
|
55
|
+
classify_java_file,
|
|
56
|
+
collect_annotation_meta_chain,
|
|
57
|
+
enrich_chunk,
|
|
58
|
+
load_brownfield_overrides,
|
|
59
|
+
load_generated_detection,
|
|
60
|
+
)
|
|
55
61
|
|
|
56
62
|
# Older cocoindex (e.g. 1.0.0a43) uses ``tracked=False``; newer releases renamed
|
|
57
63
|
# the flag to ``detect_change`` (default False) and reject ``tracked``.
|
|
@@ -280,6 +286,9 @@ class JavaLanceChunk:
|
|
|
280
286
|
annotations_on_type: Annotated[list[str], LanceType(pa.list_(pa.string()))]
|
|
281
287
|
symbols: Annotated[list[str], LanceType(pa.list_(pa.string()))]
|
|
282
288
|
ontology_version: int
|
|
289
|
+
# Generated source detection: populated per-file, not per-chunk
|
|
290
|
+
generated: bool
|
|
291
|
+
generated_by: str | None
|
|
283
292
|
|
|
284
293
|
|
|
285
294
|
@dataclass
|
|
@@ -364,12 +373,13 @@ def _parse_and_enrich_java(
|
|
|
364
373
|
chunks: list[Any],
|
|
365
374
|
rel: str,
|
|
366
375
|
project_root: Path,
|
|
367
|
-
) -> list[Any]:
|
|
376
|
+
) -> tuple[list[Any], Any]:
|
|
368
377
|
"""Parse one Java file and enrich every chunk, off the event loop.
|
|
369
378
|
|
|
370
|
-
Returns a
|
|
371
|
-
|
|
372
|
-
|
|
379
|
+
Returns a tuple of (enrichments, ast) where enrichments is a list of
|
|
380
|
+
:class:`graph_enrich.ChunkEnrichment` aligned 1:1 with ``chunks``, and ast
|
|
381
|
+
is the parsed :class:`JavaFileAst`. Intended to run via ``asyncio.to_thread``
|
|
382
|
+
from ``process_java_file`` (vectors perf lever #2): while the worker thread
|
|
373
383
|
parses + enriches, the event loop is free to drive other files and keep the
|
|
374
384
|
embedder's batching queue fed.
|
|
375
385
|
|
|
@@ -381,7 +391,7 @@ def _parse_and_enrich_java(
|
|
|
381
391
|
``lru_cache`` reads are thread-safe under the GIL.
|
|
382
392
|
"""
|
|
383
393
|
ast = parse_java(content_bytes)
|
|
384
|
-
|
|
394
|
+
enrichments = [
|
|
385
395
|
enrich_chunk(
|
|
386
396
|
ast,
|
|
387
397
|
chunk_start_byte=ch.start.byte_offset,
|
|
@@ -391,6 +401,7 @@ def _parse_and_enrich_java(
|
|
|
391
401
|
)
|
|
392
402
|
for ch in chunks
|
|
393
403
|
]
|
|
404
|
+
return enrichments, ast
|
|
394
405
|
|
|
395
406
|
|
|
396
407
|
@coco.fn(memo=True)
|
|
@@ -430,9 +441,16 @@ async def process_java_file(
|
|
|
430
441
|
# (vectors perf lever #2) parse + enrich off the event loop so the loop can
|
|
431
442
|
# keep the embedder's batching queue fed while this file is being parsed.
|
|
432
443
|
# parse_java is thread-safe (per-thread tree-sitter Parser in ast_java).
|
|
433
|
-
enrichments = await asyncio.to_thread(
|
|
444
|
+
enrichments, ast = await asyncio.to_thread(
|
|
434
445
|
_parse_and_enrich_java, content_bytes, chunks, rel, project_root
|
|
435
446
|
)
|
|
447
|
+
|
|
448
|
+
# Compute generated source detection once per file (uses the AST and content_bytes)
|
|
449
|
+
generated_config = load_generated_detection(project_root)
|
|
450
|
+
generated, generated_by = classify_java_file(
|
|
451
|
+
content_bytes, ast, config=generated_config, project_root=project_root
|
|
452
|
+
)
|
|
453
|
+
|
|
436
454
|
# (vectors perf lever #1) embed all chunks concurrently so the batched
|
|
437
455
|
# embedder groups them into one ``model.encode(...)`` (max_batch_size=64)
|
|
438
456
|
# instead of N serial batch-of-1 calls. Dominant win for ``increment``
|
|
@@ -462,6 +480,8 @@ async def process_java_file(
|
|
|
462
480
|
annotations_on_type=enrich.annotations_on_type,
|
|
463
481
|
symbols=enrich.symbols,
|
|
464
482
|
ontology_version=ONTOLOGY_VERSION,
|
|
483
|
+
generated=generated,
|
|
484
|
+
generated_by=generated_by,
|
|
465
485
|
)
|
|
466
486
|
)
|
|
467
487
|
|
ladybug_queries.py
CHANGED
|
@@ -207,7 +207,7 @@ def _symbol_return_for(alias: str) -> str:
|
|
|
207
207
|
f"{alias}.modifiers AS modifiers, {alias}.annotations AS annotations, "
|
|
208
208
|
f"{alias}.capabilities AS capabilities, "
|
|
209
209
|
f"{alias}.role AS role, {alias}.signature AS signature, "
|
|
210
|
-
f"{alias}.parent_id AS parent_id, {alias}.resolved AS resolved"
|
|
210
|
+
f"{alias}.parent_id AS parent_id, {alias}.resolved AS resolved, {alias}.generated AS generated, {alias}.generated_by AS generated_by"
|
|
211
211
|
)
|
|
212
212
|
|
|
213
213
|
|
|
@@ -296,7 +296,7 @@ def _row_to_symbol(row: dict[str, Any]) -> SymbolHit:
|
|
|
296
296
|
_SYM_COLS = (
|
|
297
297
|
"id", "kind", "name", "fqn", "package", "module", "microservice",
|
|
298
298
|
"filename", "start_line", "end_line", "start_byte", "end_byte",
|
|
299
|
-
"modifiers", "annotations", "capabilities", "role", "signature", "parent_id", "resolved",
|
|
299
|
+
"modifiers", "annotations", "capabilities", "role", "signature", "parent_id", "resolved", "generated", "generated_by",
|
|
300
300
|
)
|
|
301
301
|
|
|
302
302
|
|
|
@@ -1107,14 +1107,14 @@ class LadybugGraph:
|
|
|
1107
1107
|
f"s.{c} AS s_{c}" for c in (
|
|
1108
1108
|
"id", "kind", "name", "fqn", "package", "module", "microservice",
|
|
1109
1109
|
"filename", "start_line", "end_line", "start_byte", "end_byte",
|
|
1110
|
-
"modifiers", "annotations", "capabilities", "role", "signature", "parent_id", "resolved",
|
|
1110
|
+
"modifiers", "annotations", "capabilities", "role", "signature", "parent_id", "resolved", "generated", "generated_by",
|
|
1111
1111
|
)
|
|
1112
1112
|
)
|
|
1113
1113
|
t_proj = ", ".join(
|
|
1114
1114
|
f"t.{c} AS t_{c}" for c in (
|
|
1115
1115
|
"id", "kind", "name", "fqn", "package", "module", "microservice",
|
|
1116
1116
|
"filename", "start_line", "end_line", "start_byte", "end_byte",
|
|
1117
|
-
"modifiers", "annotations", "capabilities", "role", "signature", "parent_id", "resolved",
|
|
1117
|
+
"modifiers", "annotations", "capabilities", "role", "signature", "parent_id", "resolved", "generated", "generated_by",
|
|
1118
1118
|
)
|
|
1119
1119
|
)
|
|
1120
1120
|
q = (
|