@backbencher/brain 0.0.0-stage → 0.1.0
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.
- package/CHANGELOG.md +298 -0
- package/EMBEDDINGS.md +355 -0
- package/LICENSE +21 -0
- package/README.md +415 -2
- package/bin/bb +13 -0
- package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
- package/dist/brain-index-health-KY7K552E.js +17 -0
- package/dist/brain-relationship-enrichment-QH7OOHUF.js +558 -0
- package/dist/brain.sql-EIM4WS4D.js +29 -0
- package/dist/chunk-2BSKD7O3.js +40 -0
- package/dist/chunk-2DE27DVC.js +1314 -0
- package/dist/chunk-2RRBMNBQ.js +322 -0
- package/dist/chunk-2RTN2DFU.js +711 -0
- package/dist/chunk-2WXYNLBA.js +29 -0
- package/dist/chunk-3CTFIJJB.js +17 -0
- package/dist/chunk-3LFTSMIV.js +174 -0
- package/dist/chunk-47HKX4AJ.js +930 -0
- package/dist/chunk-4H22TLOT.js +543 -0
- package/dist/chunk-5SD45FLC.js +818 -0
- package/dist/chunk-66A5ZFYA.js +1758 -0
- package/dist/chunk-6AIRWAO2.js +247 -0
- package/dist/chunk-6WNGD3NN.js +196 -0
- package/dist/chunk-7AN7U5IZ.js +371 -0
- package/dist/chunk-BHB7BYYI.js +626 -0
- package/dist/chunk-BQ3OVQ3P.js +125 -0
- package/dist/chunk-CW4XXSNN.js +1479 -0
- package/dist/chunk-D2Q4Y47A.js +53 -0
- package/dist/chunk-DIYAGQJL.js +34 -0
- package/dist/chunk-DYM4FQEE.js +90 -0
- package/dist/chunk-EWMWK7WN.js +75 -0
- package/dist/chunk-FVVQTSIM.js +3427 -0
- package/dist/chunk-FWSL4VG6.js +1290 -0
- package/dist/chunk-GBI7V7KY.js +69 -0
- package/dist/chunk-GEFFO6O2.js +152 -0
- package/dist/chunk-HOWAQXJO.js +236 -0
- package/dist/chunk-HQSPJDHI.js +613 -0
- package/dist/chunk-IFZNR5UJ.js +2863 -0
- package/dist/chunk-J4PMBXQQ.js +336 -0
- package/dist/chunk-KAET47ZL.js +125 -0
- package/dist/chunk-KCDECRJY.js +440 -0
- package/dist/chunk-KLK3PBTO.js +1119 -0
- package/dist/chunk-L5TDYKYK.js +76 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-OWISBAOF.js +61 -0
- package/dist/chunk-PJTNGD3Z.js +6924 -0
- package/dist/chunk-QLK6ED4Q.js +235 -0
- package/dist/chunk-R2GW4F6R.js +19 -0
- package/dist/chunk-RCMTFSEF.js +87 -0
- package/dist/chunk-RH7KC5HU.js +12050 -0
- package/dist/chunk-RM3PY6TG.js +376 -0
- package/dist/chunk-ROMM6KMC.js +433 -0
- package/dist/chunk-SK6YVHFZ.js +211 -0
- package/dist/chunk-SM7RFQRO.js +214 -0
- package/dist/chunk-UFE77L67.js +782 -0
- package/dist/chunk-UGR4QIGS.js +67 -0
- package/dist/chunk-UUNHHX4M.js +13 -0
- package/dist/chunk-V44PGPA6.js +2104 -0
- package/dist/chunk-VL52PL2T.js +71 -0
- package/dist/chunk-VURYFIHW.js +201 -0
- package/dist/chunk-XJKJYIPP.js +7436 -0
- package/dist/chunk-YI6FF2ZR.js +340 -0
- package/dist/cli/index.js +37 -0
- package/dist/config-HZAAYDP3.js +10 -0
- package/dist/content-search-642F7E5V.js +593 -0
- package/dist/database-TCTZDLE5.js +9 -0
- package/dist/doctor-GXCKSJOX.js +395 -0
- package/dist/edit-engine-KM7MPFEC.js +51 -0
- package/dist/engine-42TZFNIZ.js +11 -0
- package/dist/engine-LO6L4JLQ.js +18 -0
- package/dist/fingerprint-XDXFRWO6.js +33 -0
- package/dist/framework-intelligence-DWFCKV44.js +860 -0
- package/dist/freshness-3K6VU5OT.js +174 -0
- package/dist/graph-engine-PL5YA7BA.js +21 -0
- package/dist/graph_request-MM4REP6H.js +350 -0
- package/dist/impact_request-WDE47IZ5.js +68 -0
- package/dist/index-space-IUUN5WYV.js +15 -0
- package/dist/index-status-6BD7UBHR.js +34 -0
- package/dist/index.js +159 -0
- package/dist/instance-FO6QZRLH.js +19 -0
- package/dist/language-detection-DFCAU5DZ.js +11 -0
- package/dist/lsp/server.js +4301 -0
- package/dist/mcp/server.js +132 -0
- package/dist/onboard-DIQZV2NW.js +161 -0
- package/dist/override-companion-pass-XR7MHTP7.js +117 -0
- package/dist/parallel-indexer-4PW3AFXP.js +88 -0
- package/dist/pool-worker.js +1153 -0
- package/dist/project-health-ZS5TS2Z6.js +94 -0
- package/dist/project-index-5SDPHITE.js +57 -0
- package/dist/project-registry-DGZBIZS7.js +355 -0
- package/dist/real-bash-analyzer-SXSV67E2.js +2201 -0
- package/dist/real-c-analyzer-SY7FTZ6W.js +5942 -0
- package/dist/real-clean-analyzer-IGDHHLZK.js +3470 -0
- package/dist/real-clojure-analyzer-4OH7IWLB.js +2818 -0
- package/dist/real-cpp-analyzer-7LTDRJRJ.js +4101 -0
- package/dist/real-csharp-analyzer-KICU3TLH.js +3298 -0
- package/dist/real-css-analyzer-HPU277Q6.js +15 -0
- package/dist/real-dart-analyzer-7LZ5LCMW.js +3944 -0
- package/dist/real-elixir-analyzer-BE3MEVZO.js +2192 -0
- package/dist/real-erlang-analyzer-BZMAKYBK.js +1731 -0
- package/dist/real-fsharp-analyzer-5QLTOV3E.js +2390 -0
- package/dist/real-go-analyzer-POD7MZQR.js +4126 -0
- package/dist/real-graphql-analyzer-MAQRZ6QW.js +1442 -0
- package/dist/real-groovy-analyzer-MEWSUPMJ.js +2285 -0
- package/dist/real-haskell-analyzer-I5L2GR3Y.js +2533 -0
- package/dist/real-hcl-analyzer-DBOPXSWJ.js +725 -0
- package/dist/real-html-analyzer-O63XZLZD.js +1759 -0
- package/dist/real-java-analyzer-CHCW3EKA.js +4677 -0
- package/dist/real-javascript-analyzer-QAAJQYZE.js +14 -0
- package/dist/real-json-analyzer-UGBR7YQN.js +1640 -0
- package/dist/real-julia-analyzer-35Q4GHOZ.js +2085 -0
- package/dist/real-kotlin-analyzer-GRAYCWW2.js +3956 -0
- package/dist/real-lua-analyzer-5BAPDZDF.js +1957 -0
- package/dist/real-makefile-analyzer-YJKAHNAS.js +920 -0
- package/dist/real-markdown-analyzer-UKUQZO4F.js +1215 -0
- package/dist/real-matlab-analyzer-FVIKQZKG.js +480 -0
- package/dist/real-nim-analyzer-M7FAIABG.js +3603 -0
- package/dist/real-objective-c-analyzer-XMYQIGQI.js +1518 -0
- package/dist/real-perl-analyzer-ZLY6M2DZ.js +1865 -0
- package/dist/real-php-analyzer-KI2ZAM7X.js +9368 -0
- package/dist/real-powershell-analyzer-B3T5ZP6U.js +2915 -0
- package/dist/real-protobuf-analyzer-23OZ75XV.js +867 -0
- package/dist/real-python-analyzer-I4TIUB6D.js +4880 -0
- package/dist/real-r-analyzer-FJZJXXS6.js +2596 -0
- package/dist/real-ruby-analyzer-M3UFIVTQ.js +2429 -0
- package/dist/real-rust-analyzer-LVSONPAN.js +3359 -0
- package/dist/real-scala-analyzer-CWPI33Q2.js +3293 -0
- package/dist/real-scss-analyzer-TGRJQ7TH.js +1515 -0
- package/dist/real-solidity-analyzer-4P2VBVWA.js +2608 -0
- package/dist/real-sql-analyzer-J7DYZOZR.js +3840 -0
- package/dist/real-svelte-analyzer-NHEN2SX5.js +2532 -0
- package/dist/real-swift-analyzer-2NSYULWI.js +2311 -0
- package/dist/real-toml-analyzer-L3C66L7Q.js +929 -0
- package/dist/real-typescript-analyzer-FTC6ETRQ.js +14 -0
- package/dist/real-vb-analyzer-ORY7LAQS.js +3145 -0
- package/dist/real-vba-analyzer-JH2TTUFI.js +466 -0
- package/dist/real-vue-analyzer-OO4FUGBV.js +2680 -0
- package/dist/real-xml-analyzer-6CQVR477.js +2405 -0
- package/dist/real-yaml-analyzer-J6MQG3YX.js +3528 -0
- package/dist/real-zig-analyzer-EFKCPJNU.js +2430 -0
- package/dist/regex-search-OPTLKUN5.js +239 -0
- package/dist/rules-I453JTRC.js +152 -0
- package/dist/scoped-path-MJYWJZQX.js +11 -0
- package/dist/setup-show-Y5GB5KXA.js +15 -0
- package/dist/setup-wizard-G5YYR5T6.js +24 -0
- package/dist/symbol-search-KB4MU4SI.js +16 -0
- package/dist/taint-YOTN5X55.js +202 -0
- package/dist/taint-analyzer-N7YLZU3N.js +163 -0
- package/dist/tool-handlers-G4NAGJIH.js +72 -0
- package/dist/tool-registry-BPEJNSZG.js +17 -0
- package/dist/tool-validation-RF675A3C.js +32 -0
- package/dist/type-inference-4Y7WTMFE.js +13 -0
- package/dist/vector-binary-LMY4QGAN.js +19 -0
- package/dist/version-LXGNFO37.js +9 -0
- package/dist/wasm-NMWO3WXY.js +16 -0
- package/docs/EMBEDDINGS.md +132 -0
- package/docs/README.md +178 -0
- package/docs/data/m10-baseline.json +602 -0
- package/docs/data/m10-benchmark-baseline.json +57 -0
- package/docs/data/m10-benchmark-last-run.json +127 -0
- package/docs/data/m10-final-audit.json +215 -0
- package/docs/data/m12-final-audit.json +138 -0
- package/docs/data/m12-surface-matrix.json +50 -0
- package/docs/data/public-tools.json +1902 -0
- package/docs/indexing/DEAD-ASSETS.md +88 -0
- package/docs/indexing/INDEXER-REVIEW.md +634 -0
- package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
- package/docs/indexing/README.md +427 -0
- package/docs/indexing/discovery-matrix.md +41 -0
- package/docs/indexing/embeddings.md +325 -0
- package/docs/indexing/environment-variables.md +77 -0
- package/docs/indexing/performance.md +323 -0
- package/docs/indexing/resume.md +345 -0
- package/docs/indexing/troubleshooting.md +391 -0
- package/docs/man/bb.1 +190 -0
- package/docs/tools/bb_analyze.md +147 -0
- package/docs/tools/bb_annotate.md +110 -0
- package/docs/tools/bb_annotations.md +106 -0
- package/docs/tools/bb_ask.md +101 -0
- package/docs/tools/bb_cross_language.md +103 -0
- package/docs/tools/bb_doc.md +169 -0
- package/docs/tools/bb_edit.md +185 -0
- package/docs/tools/bb_graph.md +169 -0
- package/docs/tools/bb_health.md +156 -0
- package/docs/tools/bb_impact.md +117 -0
- package/docs/tools/bb_index.md +108 -0
- package/docs/tools/bb_migrate.md +135 -0
- package/docs/tools/bb_patterns.md +140 -0
- package/docs/tools/bb_search.md +150 -0
- package/docs/tools/bb_security.md +100 -0
- package/docs/tools/bb_visualize.md +184 -0
- package/grammars/README.md +57 -0
- package/grammars/THIRD-PARTY-NOTICES.md +50 -0
- package/grammars/tree-sitter-c/LICENSE +21 -0
- package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
- package/grammars/tree-sitter-cpp/LICENSE +21 -0
- package/grammars/tree-sitter-csharp/LICENSE +21 -0
- package/grammars/tree-sitter-css/LICENSE +21 -0
- package/grammars/tree-sitter-css/README.md +21 -0
- package/grammars/tree-sitter-dart/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/README.md +18 -0
- package/grammars/tree-sitter-elixir/LICENSE +176 -0
- package/grammars/tree-sitter-elixir/README.md +11 -0
- package/grammars/tree-sitter-fsharp/LICENSE +21 -0
- package/grammars/tree-sitter-fsharp/README.md +45 -0
- package/grammars/tree-sitter-graphql/LICENSE +21 -0
- package/grammars/tree-sitter-graphql/README.md +106 -0
- package/grammars/tree-sitter-groovy/LICENSE +21 -0
- package/grammars/tree-sitter-groovy/README.md +4 -0
- package/grammars/tree-sitter-haskell/LICENSE +21 -0
- package/grammars/tree-sitter-haskell/README.md +394 -0
- package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
- package/grammars/tree-sitter-hcl/LICENSE +201 -0
- package/grammars/tree-sitter-hcl/README.md +39 -0
- package/grammars/tree-sitter-html/LICENSE +21 -0
- package/grammars/tree-sitter-html/README.md +21 -0
- package/grammars/tree-sitter-julia/LICENSE +21 -0
- package/grammars/tree-sitter-julia/README.md +24 -0
- package/grammars/tree-sitter-kotlin/LICENSE +9 -0
- package/grammars/tree-sitter-lua/LICENSE.md +21 -0
- package/grammars/tree-sitter-lua/README.md +29 -0
- package/grammars/tree-sitter-make/LICENSE +21 -0
- package/grammars/tree-sitter-matlab/LICENSE +19 -0
- package/grammars/tree-sitter-matlab/README.md +99 -0
- package/grammars/tree-sitter-nim/LICENSE +373 -0
- package/grammars/tree-sitter-nim/README.md +46 -0
- package/grammars/tree-sitter-objc/LICENSE +21 -0
- package/grammars/tree-sitter-objc/README.md +20 -0
- package/grammars/tree-sitter-perl/LICENSE +7 -0
- package/grammars/tree-sitter-perl/README.md +100 -0
- package/grammars/tree-sitter-powershell/LICENSE +21 -0
- package/grammars/tree-sitter-powershell/README.md +7 -0
- package/grammars/tree-sitter-proto/LICENSE +21 -0
- package/grammars/tree-sitter-proto/README.md +105 -0
- package/grammars/tree-sitter-r/LICENSE +9 -0
- package/grammars/tree-sitter-r/README.md +66 -0
- package/grammars/tree-sitter-ruby/LICENSE +22 -0
- package/grammars/tree-sitter-scss/LICENSE +21 -0
- package/grammars/tree-sitter-scss/README.md +17 -0
- package/grammars/tree-sitter-solidity/LICENSE +7 -0
- package/grammars/tree-sitter-sql/LICENSE +21 -0
- package/grammars/tree-sitter-typescript/LICENSE +21 -0
- package/grammars/tree-sitter-vba/LICENSE +21 -0
- package/grammars/tree-sitter-vba/README.md +738 -0
- package/grammars/tree-sitter-vbnet/LICENSE +21 -0
- package/grammars/tree-sitter-vbnet/README.md +322 -0
- package/grammars/tree-sitter-xml/LICENSE +19 -0
- package/grammars/tree-sitter-yaml/LICENSE +20 -0
- package/grammars/tree-sitter-yaml/README.md +21 -0
- package/package.json +184 -4
- package/wasm/dart.wasm +0 -0
- package/wasm/tree-sitter-bash.wasm +0 -0
- package/wasm/tree-sitter-c.wasm +0 -0
- package/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/wasm/tree-sitter-clean.wasm +0 -0
- package/wasm/tree-sitter-clojure.wasm +0 -0
- package/wasm/tree-sitter-core_schema.wasm +0 -0
- package/wasm/tree-sitter-cpp.wasm +0 -0
- package/wasm/tree-sitter-css.wasm +0 -0
- package/wasm/tree-sitter-dart.wasm +0 -0
- package/wasm/tree-sitter-elisp.wasm +0 -0
- package/wasm/tree-sitter-elixir.wasm +0 -0
- package/wasm/tree-sitter-elm.wasm +0 -0
- package/wasm/tree-sitter-embedded_template.wasm +0 -0
- package/wasm/tree-sitter-erlang.wasm +0 -0
- package/wasm/tree-sitter-fsharp.wasm +0 -0
- package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
- package/wasm/tree-sitter-go.wasm +0 -0
- package/wasm/tree-sitter-graphql.wasm +0 -0
- package/wasm/tree-sitter-groovy.wasm +0 -0
- package/wasm/tree-sitter-haskell.wasm +0 -0
- package/wasm/tree-sitter-hcl.wasm +0 -0
- package/wasm/tree-sitter-html.wasm +0 -0
- package/wasm/tree-sitter-java.wasm +0 -0
- package/wasm/tree-sitter-javascript.wasm +0 -0
- package/wasm/tree-sitter-json.wasm +0 -0
- package/wasm/tree-sitter-json_schema.wasm +0 -0
- package/wasm/tree-sitter-julia.wasm +0 -0
- package/wasm/tree-sitter-kotlin.wasm +0 -0
- package/wasm/tree-sitter-lua.wasm +0 -0
- package/wasm/tree-sitter-make.wasm +0 -0
- package/wasm/tree-sitter-markdown.wasm +0 -0
- package/wasm/tree-sitter-markdown_inline.wasm +0 -0
- package/wasm/tree-sitter-matlab.wasm +0 -0
- package/wasm/tree-sitter-nim.wasm +0 -0
- package/wasm/tree-sitter-objc.wasm +0 -0
- package/wasm/tree-sitter-ocaml.wasm +0 -0
- package/wasm/tree-sitter-perl.wasm +0 -0
- package/wasm/tree-sitter-php.wasm +0 -0
- package/wasm/tree-sitter-php_only.wasm +0 -0
- package/wasm/tree-sitter-powershell.wasm +0 -0
- package/wasm/tree-sitter-protobuf.wasm +0 -0
- package/wasm/tree-sitter-python.wasm +0 -0
- package/wasm/tree-sitter-ql.wasm +0 -0
- package/wasm/tree-sitter-r.wasm +0 -0
- package/wasm/tree-sitter-rescript.wasm +0 -0
- package/wasm/tree-sitter-ruby.wasm +0 -0
- package/wasm/tree-sitter-rust.wasm +0 -0
- package/wasm/tree-sitter-scala.wasm +0 -0
- package/wasm/tree-sitter-scss.wasm +0 -0
- package/wasm/tree-sitter-solidity.wasm +0 -0
- package/wasm/tree-sitter-sql.wasm +0 -0
- package/wasm/tree-sitter-svelte.wasm +0 -0
- package/wasm/tree-sitter-swift.wasm +0 -0
- package/wasm/tree-sitter-systemrdl.wasm +0 -0
- package/wasm/tree-sitter-terraform.wasm +0 -0
- package/wasm/tree-sitter-tlaplus.wasm +0 -0
- package/wasm/tree-sitter-toml.wasm +0 -0
- package/wasm/tree-sitter-tsx.wasm +0 -0
- package/wasm/tree-sitter-typescript.wasm +0 -0
- package/wasm/tree-sitter-vba.wasm +0 -0
- package/wasm/tree-sitter-vbnet.wasm +0 -0
- package/wasm/tree-sitter-vue.wasm +0 -0
- package/wasm/tree-sitter-xml.wasm +0 -0
- package/wasm/tree-sitter-yaml.wasm +0 -0
- package/wasm/tree-sitter-zig.wasm +0 -0
- package/wasm/tree-sitter.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkFileFreshness
|
|
3
|
+
} from "./chunk-QLK6ED4Q.js";
|
|
4
|
+
import "./chunk-MLKGABMK.js";
|
|
5
|
+
|
|
6
|
+
// src/lsp/freshness.ts
|
|
7
|
+
import { watch, existsSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
var DEBOUNCE_MS = 300;
|
|
10
|
+
function createFreshnessMonitor(deps) {
|
|
11
|
+
const { projectId, projectPath, raw } = deps;
|
|
12
|
+
const log = deps.log ?? (() => {
|
|
13
|
+
});
|
|
14
|
+
let watcher = null;
|
|
15
|
+
let debounceTimer = null;
|
|
16
|
+
let reindexInFlight = Promise.resolve();
|
|
17
|
+
let stopped = false;
|
|
18
|
+
const pending = /* @__PURE__ */ new Map();
|
|
19
|
+
const lastReindex = /* @__PURE__ */ new Map();
|
|
20
|
+
const inFlight = /* @__PURE__ */ new Set();
|
|
21
|
+
function fileIdFor(path) {
|
|
22
|
+
return deps.fileIdForPath(path);
|
|
23
|
+
}
|
|
24
|
+
function scheduleReindex() {
|
|
25
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
26
|
+
debounceTimer = setTimeout(() => {
|
|
27
|
+
debounceTimer = null;
|
|
28
|
+
if (pending.size === 0) return;
|
|
29
|
+
const changes = Array.from(pending.entries()).map(([p, type]) => ({ path: p, type }));
|
|
30
|
+
pending.clear();
|
|
31
|
+
for (const c of changes) inFlight.add(c.path);
|
|
32
|
+
log("freshness: reindex starting", { count: changes.length });
|
|
33
|
+
reindexInFlight = (async () => {
|
|
34
|
+
try {
|
|
35
|
+
await reindexInFlight;
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const res = await deps.reindex(changes);
|
|
40
|
+
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
41
|
+
for (const c of changes) {
|
|
42
|
+
inFlight.delete(c.path);
|
|
43
|
+
lastReindex.set(c.path, at);
|
|
44
|
+
}
|
|
45
|
+
log("freshness: reindex completed", { ...res });
|
|
46
|
+
} catch (error) {
|
|
47
|
+
log("freshness: reindex failed", { error: String(error) });
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
}, DEBOUNCE_MS);
|
|
51
|
+
}
|
|
52
|
+
function onWatchEvent(path) {
|
|
53
|
+
if (stopped) return;
|
|
54
|
+
let type;
|
|
55
|
+
try {
|
|
56
|
+
type = existsSync(path) ? "modified" : "deleted";
|
|
57
|
+
} catch {
|
|
58
|
+
type = "deleted";
|
|
59
|
+
}
|
|
60
|
+
pending.set(path, type);
|
|
61
|
+
scheduleReindex();
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
start() {
|
|
65
|
+
if (watcher || stopped) return;
|
|
66
|
+
try {
|
|
67
|
+
watcher = watch(projectPath, { persistent: false, recursive: true }, (_event, filename) => {
|
|
68
|
+
if (!filename) {
|
|
69
|
+
void this.fullScan();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
onWatchEvent(join(projectPath, filename));
|
|
73
|
+
});
|
|
74
|
+
watcher.on("error", (err) => {
|
|
75
|
+
log("freshness: watcher error, falling back to scan-on-read", { error: String(err) });
|
|
76
|
+
try {
|
|
77
|
+
watcher?.close();
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
watcher = null;
|
|
81
|
+
});
|
|
82
|
+
log("freshness: watching", { projectPath, debounceMs: DEBOUNCE_MS });
|
|
83
|
+
} catch (error) {
|
|
84
|
+
log("freshness: watch unavailable, falling back to scan-on-read", { error: String(error) });
|
|
85
|
+
watcher = null;
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
async stop() {
|
|
89
|
+
stopped = true;
|
|
90
|
+
if (debounceTimer) {
|
|
91
|
+
clearTimeout(debounceTimer);
|
|
92
|
+
debounceTimer = null;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
watcher?.close();
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
watcher = null;
|
|
99
|
+
await reindexInFlight.catch(() => {
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
async marker(fileId) {
|
|
103
|
+
let f = null;
|
|
104
|
+
try {
|
|
105
|
+
f = checkFileFreshness(raw, fileId);
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
const path = f?.path;
|
|
109
|
+
const pendingReindex = path ? inFlight.has(path) || pending.has(path) : false;
|
|
110
|
+
const status = f ? f.status : "unknown";
|
|
111
|
+
return {
|
|
112
|
+
// unknown counts as stale: we cannot claim freshness for a file we
|
|
113
|
+
// cannot check. Silence is guilt (contract §4.3).
|
|
114
|
+
stale: status !== "fresh" || pendingReindex,
|
|
115
|
+
status,
|
|
116
|
+
pendingReindex,
|
|
117
|
+
lastReindexAt: path ? lastReindex.get(path) : void 0
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
async fullScan() {
|
|
121
|
+
const rows = raw.prepare("SELECT id, path FROM brain_file").all();
|
|
122
|
+
let stale = 0;
|
|
123
|
+
let missing = 0;
|
|
124
|
+
const changes = [];
|
|
125
|
+
for (const row of rows) {
|
|
126
|
+
const f = checkFileFreshness(raw, row.id);
|
|
127
|
+
if (!f) continue;
|
|
128
|
+
if (f.status === "stale") {
|
|
129
|
+
stale++;
|
|
130
|
+
changes.push({ path: row.path, type: "modified" });
|
|
131
|
+
}
|
|
132
|
+
if (f.status === "missing") {
|
|
133
|
+
missing++;
|
|
134
|
+
changes.push({ path: row.path, type: "deleted" });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (changes.length > 0) {
|
|
138
|
+
for (const c of changes) inFlight.add(c.path);
|
|
139
|
+
const res = await deps.reindex(changes);
|
|
140
|
+
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
141
|
+
for (const c of changes) {
|
|
142
|
+
inFlight.delete(c.path);
|
|
143
|
+
lastReindex.set(c.path, at);
|
|
144
|
+
}
|
|
145
|
+
log("freshness: full scan reindex", { ...res });
|
|
146
|
+
}
|
|
147
|
+
return { checked: rows.length, stale, missing };
|
|
148
|
+
},
|
|
149
|
+
pendingFiles() {
|
|
150
|
+
return Array.from(/* @__PURE__ */ new Set([...pending.keys(), ...inFlight]));
|
|
151
|
+
},
|
|
152
|
+
async drain() {
|
|
153
|
+
const settle = () => new Promise((r) => setTimeout(r, 50));
|
|
154
|
+
await settle();
|
|
155
|
+
const deadline = Date.now() + DEBOUNCE_MS * 4 + 2e3;
|
|
156
|
+
while (Date.now() < deadline && (debounceTimer || pending.size > 0 || inFlight.size > 0)) {
|
|
157
|
+
if (debounceTimer) await new Promise((r) => setTimeout(r, Math.min(DEBOUNCE_MS, 100)));
|
|
158
|
+
await reindexInFlight.catch(() => {
|
|
159
|
+
});
|
|
160
|
+
if (pending.size === 0 && inFlight.size === 0 && !debounceTimer) {
|
|
161
|
+
await settle();
|
|
162
|
+
if (pending.size === 0 && inFlight.size === 0 && !debounceTimer) break;
|
|
163
|
+
}
|
|
164
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
165
|
+
}
|
|
166
|
+
await reindexInFlight.catch(() => {
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export {
|
|
172
|
+
DEBOUNCE_MS,
|
|
173
|
+
createFreshnessMonitor
|
|
174
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
graphTraversal,
|
|
3
|
+
likeContains,
|
|
4
|
+
resolveGraphRoot,
|
|
5
|
+
resolveGraphRootDetailed,
|
|
6
|
+
traverseGraph
|
|
7
|
+
} from "./chunk-47HKX4AJ.js";
|
|
8
|
+
import "./chunk-UUNHHX4M.js";
|
|
9
|
+
import "./chunk-KLK3PBTO.js";
|
|
10
|
+
import "./chunk-2BSKD7O3.js";
|
|
11
|
+
import "./chunk-SM7RFQRO.js";
|
|
12
|
+
import "./chunk-L5TDYKYK.js";
|
|
13
|
+
import "./chunk-ROMM6KMC.js";
|
|
14
|
+
import "./chunk-MLKGABMK.js";
|
|
15
|
+
export {
|
|
16
|
+
graphTraversal,
|
|
17
|
+
likeContains,
|
|
18
|
+
resolveGraphRoot,
|
|
19
|
+
resolveGraphRootDetailed,
|
|
20
|
+
traverseGraph
|
|
21
|
+
};
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IDENTITY_TRAVERSABLE_TYPES,
|
|
3
|
+
memberFileMatches,
|
|
4
|
+
memberResolutionRecord,
|
|
5
|
+
resolveMemberIdentity
|
|
6
|
+
} from "./chunk-VL52PL2T.js";
|
|
7
|
+
import {
|
|
8
|
+
USAGE_COUNT_UNIT_LABEL,
|
|
9
|
+
isDeclarationRelationship
|
|
10
|
+
} from "./chunk-GBI7V7KY.js";
|
|
11
|
+
import {
|
|
12
|
+
graphTraversal
|
|
13
|
+
} from "./chunk-47HKX4AJ.js";
|
|
14
|
+
import "./chunk-UUNHHX4M.js";
|
|
15
|
+
import "./chunk-KLK3PBTO.js";
|
|
16
|
+
import "./chunk-2BSKD7O3.js";
|
|
17
|
+
import "./chunk-SM7RFQRO.js";
|
|
18
|
+
import "./chunk-L5TDYKYK.js";
|
|
19
|
+
import "./chunk-ROMM6KMC.js";
|
|
20
|
+
import "./chunk-MLKGABMK.js";
|
|
21
|
+
|
|
22
|
+
// src/lsp/graph_usages.ts
|
|
23
|
+
var USAGES_DECLARED_EXCLUSIONS = {
|
|
24
|
+
/** A stored row whose BOTH ends are this symbol — an analyzer artifact, not a
|
|
25
|
+
* use of anything. Already excluded before this wave (the self-loop fix). */
|
|
26
|
+
selfReferentialRows: "an analyzer artifact: the row's source and target are the same symbol",
|
|
27
|
+
/** `contains`/`exports` — how a symbol is DECLARED, never who uses it.
|
|
28
|
+
* `Greeter contains greet` is not `Greeter` USING `greet`; it is `greet` being
|
|
29
|
+
* a member of `Greeter`. Serving the declaration containment as a caller
|
|
30
|
+
* listed a class among the users of its own member, which is the exact
|
|
31
|
+
* inversion the vocabulary exists to prevent (src/lsp/relations.ts:
|
|
32
|
+
* "a declaration is never a usage"). Measured: `Greeter` was rendered as a
|
|
33
|
+
* caller of `greet`.
|
|
34
|
+
*
|
|
35
|
+
* WHY HERE AND NOT IN THE ENGINE'S DEFAULT TYPE LIST: the traversal must walk
|
|
36
|
+
* `contains` — a graph rooted at a class cannot reach that class's own
|
|
37
|
+
* methods without it (src/intelligence/graph/graph-engine.ts:28-30, where
|
|
38
|
+
* dropping it was measured as structural damage). The exclusion is a property
|
|
39
|
+
* of the USAGES vocabulary, not of the walk, so it belongs at the usages
|
|
40
|
+
* grouping — the module the codebase already calls "the SINGLE owner of the
|
|
41
|
+
* grouping" — and `mode: "graph"` keeps serving every stored kind. */
|
|
42
|
+
declarationContainments: "declaration containments (contains/exports) declare a symbol; they are never usages of it",
|
|
43
|
+
/** NEW (T3 cross-surface defect): rows the traversal reached only THROUGH the
|
|
44
|
+
* owning declaration, a containment walk, or a chain this answer does not
|
|
45
|
+
* serve. The owner cascade is right for the graph panel (a class graph must
|
|
46
|
+
* reach its members), but in a CALLERS list it made every member inherit the
|
|
47
|
+
* whole class's referrers — measured: a method with ZERO callers answered
|
|
48
|
+
* six, one per class method's callers plus the class's own instantiators; and
|
|
49
|
+
* the class's caller list carried a member's own call re-attributed to the
|
|
50
|
+
* class. A "caller" that does not name this symbol is not a caller of it.
|
|
51
|
+
* Omitted, counted in `declaredExclusions.counts.*.ownerFamilyRows`, never
|
|
52
|
+
* silent. */
|
|
53
|
+
ownerFamilyRows: "rows reached only through the symbol's owning declaration, a containment walk or a chain that is not served \u2014 they do not name this symbol, so they are not usages of it (the owner-family cascade made a zero-caller method report six callers)"
|
|
54
|
+
};
|
|
55
|
+
function classifyFileLevel(raw) {
|
|
56
|
+
const imports = [];
|
|
57
|
+
const exports = [];
|
|
58
|
+
for (const row of raw) {
|
|
59
|
+
const entry = { rowId: row.rowId, relationshipType: row.relationshipType, moduleSpecifier: row.moduleSpecifier ?? "", confidence: row.confidence };
|
|
60
|
+
if (row.relationshipType === "imports" || row.relationshipType === "part_of") imports.push(entry);
|
|
61
|
+
else if (row.relationshipType === "exports") exports.push(entry);
|
|
62
|
+
else throw new Error(`bb/graph: file-level classifier received unexpected relationship_type ${row.relationshipType} (row ${row.rowId})`);
|
|
63
|
+
}
|
|
64
|
+
imports.sort((a, b) => a.moduleSpecifier.localeCompare(b.moduleSpecifier) || a.rowId.localeCompare(b.rowId));
|
|
65
|
+
exports.sort((a, b) => a.moduleSpecifier.localeCompare(b.moduleSpecifier) || a.rowId.localeCompare(b.rowId));
|
|
66
|
+
return { imports, exports };
|
|
67
|
+
}
|
|
68
|
+
function typeCounts(rows) {
|
|
69
|
+
const map = /* @__PURE__ */ new Map();
|
|
70
|
+
for (const row of rows) map.set(row.relationshipType, (map.get(row.relationshipType) ?? 0) + 1);
|
|
71
|
+
return [...map.entries()].map(([type, occurrences]) => ({ type, occurrences })).sort((a, b) => a.type.localeCompare(b.type) || b.occurrences - a.occurrences);
|
|
72
|
+
}
|
|
73
|
+
function sortedGroups(groups) {
|
|
74
|
+
return [...groups].sort(
|
|
75
|
+
(a, b) => a.file.localeCompare(b.file) || a.name.localeCompare(b.name) || a.symbolId.localeCompare(b.symbolId)
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
function groupSide(edges, nodes, pick, parentOf) {
|
|
79
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
80
|
+
for (const edge of edges) {
|
|
81
|
+
const nodeId = pick(edge);
|
|
82
|
+
const node = nodes[nodeId];
|
|
83
|
+
if (node === void 0) {
|
|
84
|
+
throw new Error(`bb/graph: usages grouping consistency failure \u2014 edge ${edge.from} -> ${edge.to} has no registered node ${nodeId}`);
|
|
85
|
+
}
|
|
86
|
+
const parentId = parentOf(edge);
|
|
87
|
+
if (nodes[parentId] === void 0) {
|
|
88
|
+
throw new Error(`bb/graph: usages grouping consistency failure \u2014 edge ${edge.from} -> ${edge.to} has no registered parent node ${parentId}`);
|
|
89
|
+
}
|
|
90
|
+
let group = byNode.get(nodeId);
|
|
91
|
+
if (group === void 0) {
|
|
92
|
+
group = {
|
|
93
|
+
symbolId: node.id,
|
|
94
|
+
name: node.name,
|
|
95
|
+
file: node.file,
|
|
96
|
+
language: node.language,
|
|
97
|
+
symbolType: node.symbolType,
|
|
98
|
+
line: node.line,
|
|
99
|
+
isExternal: node.isExternal,
|
|
100
|
+
relationshipTypes: [],
|
|
101
|
+
occurrences: 0,
|
|
102
|
+
rows: []
|
|
103
|
+
};
|
|
104
|
+
byNode.set(nodeId, group);
|
|
105
|
+
}
|
|
106
|
+
group.rows.push({
|
|
107
|
+
rowId: edge.rowId,
|
|
108
|
+
relationshipType: edge.relationshipType,
|
|
109
|
+
callSite: edge.callSite,
|
|
110
|
+
depth: edge.depth,
|
|
111
|
+
confidence: edge.confidence,
|
|
112
|
+
isCrossLanguage: edge.isCrossLanguage,
|
|
113
|
+
bridgeMechanism: edge.bridgeMechanism,
|
|
114
|
+
evidenceClass: edge.metadata?.evidenceClass,
|
|
115
|
+
enrichment: edge.metadata?.enrichment,
|
|
116
|
+
parentSymbolId: parentId,
|
|
117
|
+
parentName: nodes[parentId].name
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return byNode;
|
|
121
|
+
}
|
|
122
|
+
function finalize(byNode) {
|
|
123
|
+
const groups = [...byNode.values()];
|
|
124
|
+
for (const g of groups) {
|
|
125
|
+
g.rows.sort((a, b) => a.relationshipType.localeCompare(b.relationshipType) || a.rowId.localeCompare(b.rowId));
|
|
126
|
+
g.relationshipTypes = typeCounts(g.rows);
|
|
127
|
+
g.occurrences = g.rows.length;
|
|
128
|
+
}
|
|
129
|
+
return sortedGroups(groups);
|
|
130
|
+
}
|
|
131
|
+
function directUsageRows(edges, direction, rootId) {
|
|
132
|
+
const rendered = [];
|
|
133
|
+
const excluded = { selfReferentialRows: 0, declarationContainments: 0, ownerFamilyRows: 0 };
|
|
134
|
+
const servedGroupIds = /* @__PURE__ */ new Set();
|
|
135
|
+
const deferred = [];
|
|
136
|
+
const namesRoot = (edge) => direction === "caller" ? edge.to === rootId && edge.targetMatch !== "owner-cascade" : edge.from === rootId;
|
|
137
|
+
const groupOf = (edge) => direction === "caller" ? edge.from : edge.to;
|
|
138
|
+
for (const edge of edges) {
|
|
139
|
+
if (edge.from === edge.to) {
|
|
140
|
+
excluded.selfReferentialRows++;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (isDeclarationRelationship(edge.relationshipType)) {
|
|
144
|
+
excluded.declarationContainments++;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const rowDepth = edge.depth;
|
|
148
|
+
if (namesRoot(edge)) {
|
|
149
|
+
if (!rendered.some((r) => r.rowId === edge.rowId)) rendered.push(edge);
|
|
150
|
+
servedGroupIds.add(groupOf(edge));
|
|
151
|
+
} else if (rowDepth === 0) {
|
|
152
|
+
excluded.ownerFamilyRows++;
|
|
153
|
+
} else {
|
|
154
|
+
deferred.push(edge);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
for (const edge of deferred) {
|
|
158
|
+
const parentId = direction === "caller" ? edge.to : edge.from;
|
|
159
|
+
const extendsServedChain = servedGroupIds.has(parentId) && (direction === "caller" ? edge.targetMatch !== "owner-cascade" : true);
|
|
160
|
+
if (extendsServedChain) rendered.push(edge);
|
|
161
|
+
else excluded.ownerFamilyRows++;
|
|
162
|
+
}
|
|
163
|
+
return { rendered, excluded };
|
|
164
|
+
}
|
|
165
|
+
function groupUsagesEdges(result) {
|
|
166
|
+
const rootId = result.root.id;
|
|
167
|
+
const callerSide = directUsageRows(result.callers ?? [], "caller", rootId);
|
|
168
|
+
const calleeSide = directUsageRows(result.callees ?? [], "callee", rootId);
|
|
169
|
+
const callerMap = groupSide(callerSide.rendered, result.nodes ?? {}, (e) => e.from, (e) => e.to);
|
|
170
|
+
const calleeMap = groupSide(calleeSide.rendered, result.nodes ?? {}, (e) => e.to, (e) => e.from);
|
|
171
|
+
return {
|
|
172
|
+
callers: finalize(callerMap),
|
|
173
|
+
callees: finalize(calleeMap),
|
|
174
|
+
exclusions: { caller: callerSide.excluded, callee: calleeSide.excluded },
|
|
175
|
+
candidateRows: { caller: (result.callers ?? []).length, callee: (result.callees ?? []).length }
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function buildGroupedUsages(result, fileLevel) {
|
|
179
|
+
const { callers, callees, exclusions, candidateRows } = groupUsagesEdges(result);
|
|
180
|
+
const crossLanguageGroups = [...callers, ...callees].filter((g) => g.rows.some((r) => r.isCrossLanguage)).length;
|
|
181
|
+
const root = result.root;
|
|
182
|
+
const sections = { imports: fileLevel.imports, exports: fileLevel.exports, dependencies: fileLevel.dependencies ?? [] };
|
|
183
|
+
return {
|
|
184
|
+
root: { symbolId: root.id, name: root.name, file: root.file, language: root.language, line: root.line },
|
|
185
|
+
callers,
|
|
186
|
+
callees,
|
|
187
|
+
fileLevel: sections,
|
|
188
|
+
counts: {
|
|
189
|
+
callerGroups: callers.length,
|
|
190
|
+
calleeGroups: callees.length,
|
|
191
|
+
callerRows: callers.reduce((n, g) => n + g.rows.length, 0),
|
|
192
|
+
calleeRows: callees.reduce((n, g) => n + g.rows.length, 0),
|
|
193
|
+
fileLevelRows: sections.imports.length + sections.exports.length + sections.dependencies.length,
|
|
194
|
+
fileDependencyRows: sections.dependencies.length,
|
|
195
|
+
callerCandidateRows: candidateRows.caller,
|
|
196
|
+
calleeCandidateRows: candidateRows.callee
|
|
197
|
+
},
|
|
198
|
+
summary: {
|
|
199
|
+
truncated: result.summary.truncated,
|
|
200
|
+
truncationReason: result.summary.truncationReason,
|
|
201
|
+
crossLanguageGroups
|
|
202
|
+
},
|
|
203
|
+
declaredExclusions: { ...USAGES_DECLARED_EXCLUSIONS, counts: exclusions },
|
|
204
|
+
countUnit: USAGE_COUNT_UNIT_LABEL,
|
|
205
|
+
annotations: result.annotations
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/lsp/graph_request.ts
|
|
210
|
+
var GRAPH_REQUEST_METHOD = "bb/graph";
|
|
211
|
+
var GRAPH_SCHEMA_VERSION = 2;
|
|
212
|
+
var GRAPH_MODE_GRAPH = "graph";
|
|
213
|
+
var GRAPH_MODE_USAGES = "usages";
|
|
214
|
+
var HUB_USAGES_MAX_DEPTH = 5;
|
|
215
|
+
var GraphRequestError = class extends Error {
|
|
216
|
+
constructor(message) {
|
|
217
|
+
super(message);
|
|
218
|
+
this.name = "GraphRequestError";
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
function isIndexedWorkspace(db, projectId) {
|
|
222
|
+
try {
|
|
223
|
+
const row = db.prepare("SELECT 1 AS ok FROM brain_symbol WHERE project_id = ? LIMIT 1").get(projectId);
|
|
224
|
+
return row !== void 0 && row !== null;
|
|
225
|
+
} catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async function resolveTraversalRoot(deps, db, projectId, params) {
|
|
230
|
+
const file = typeof params.file === "string" && params.file.length > 0 ? params.file : void 0;
|
|
231
|
+
const opts = () => ({
|
|
232
|
+
direction: params.direction ?? (params.mode === GRAPH_MODE_USAGES ? "both" : void 0),
|
|
233
|
+
maxDepth: params.maxDepth,
|
|
234
|
+
relationshipTypes: params.relationshipTypes,
|
|
235
|
+
includeCrossLanguage: params.includeCrossLanguage
|
|
236
|
+
});
|
|
237
|
+
try {
|
|
238
|
+
const r = await deps.traverse(projectId, params.symbol, opts());
|
|
239
|
+
const rootType = r.root?.symbolType ?? "";
|
|
240
|
+
if (rootType && !IDENTITY_TRAVERSABLE_TYPES.includes(rootType)) {
|
|
241
|
+
const owner = (deps.resolveMember ?? resolveMemberIdentity)(db, projectId, params.symbol, file);
|
|
242
|
+
if (owner === null) {
|
|
243
|
+
throw new GraphRequestError(
|
|
244
|
+
`bb/graph: symbol '${params.symbol}' is not a traversable root (${rootType}) \u2014 no graph exists for it (declared error: the symbol was not found as a traversable root)`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
const rr = await deps.traverse(projectId, owner.name, opts());
|
|
248
|
+
rr.resolution = memberResolutionRecord(params.symbol, owner.name, file);
|
|
249
|
+
return rr;
|
|
250
|
+
}
|
|
251
|
+
if (file && typeof r.root?.file === "string" && r.root.file !== "" && !memberFileMatches(file, r.root.file)) {
|
|
252
|
+
throw new GraphRequestError(
|
|
253
|
+
`bb/graph: symbol '${params.symbol}' resolves to a member in '${r.root.file}' but the hover's identity is '${file}' \u2014 the hinted symbol was not found at that identity; refusing the silent relabel (declared error)`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
return r;
|
|
257
|
+
} catch (error) {
|
|
258
|
+
const owner = (deps.resolveMember ?? resolveMemberIdentity)(db, projectId, params.symbol, file);
|
|
259
|
+
if (owner === null) {
|
|
260
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
261
|
+
if (/^Symbol '.+' not found$/.test(detail)) {
|
|
262
|
+
throw new GraphRequestError(
|
|
263
|
+
`bb/graph: symbol '${params.symbol}' not found \u2014 no graph exists (declared error; run \`bb index\` or check the name)`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
const r = await deps.traverse(projectId, owner.name, opts());
|
|
269
|
+
r.resolution = memberResolutionRecord(params.symbol, owner.name, file);
|
|
270
|
+
return r;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async function handleGraphRequest(db, projectId, params, deps = { traverse: graphTraversal }) {
|
|
274
|
+
if (params === null || typeof params !== "object" || Array.isArray(params)) {
|
|
275
|
+
throw new GraphRequestError("bb/graph: params must be an object carrying schemaVersion and symbol");
|
|
276
|
+
}
|
|
277
|
+
if (params.schemaVersion !== GRAPH_SCHEMA_VERSION) {
|
|
278
|
+
throw new GraphRequestError(
|
|
279
|
+
`bb/graph: schema version mismatch \u2014 request carries ${JSON.stringify(params.schemaVersion) ?? "nothing"}, server implements ${GRAPH_SCHEMA_VERSION} (upgrade the client or pin bbLsp.graphSchemaVersion)`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
if (typeof params.symbol !== "string" || params.symbol.length === 0) {
|
|
283
|
+
throw new GraphRequestError("bb/graph: params.symbol (non-empty string) is required");
|
|
284
|
+
}
|
|
285
|
+
if (params.mode !== void 0 && params.mode !== GRAPH_MODE_GRAPH && params.mode !== GRAPH_MODE_USAGES) {
|
|
286
|
+
throw new GraphRequestError('bb/graph: params.mode must be "graph" or "usages"');
|
|
287
|
+
}
|
|
288
|
+
if (params.direction !== void 0 && (params.direction !== "callers" && params.direction !== "callees" && params.direction !== "both")) {
|
|
289
|
+
throw new GraphRequestError('bb/graph: params.direction must be "callers", "callees", or "both"');
|
|
290
|
+
}
|
|
291
|
+
const effectiveDirection = params.direction ?? (params.mode === GRAPH_MODE_USAGES ? "both" : void 0);
|
|
292
|
+
const requestedDepth = params.maxDepth === void 0 && params.mode === GRAPH_MODE_USAGES ? HUB_USAGES_MAX_DEPTH : params.maxDepth;
|
|
293
|
+
if (params.maxDepth !== void 0 && (typeof params.maxDepth !== "number" || !Number.isInteger(params.maxDepth) || params.maxDepth < 1 || params.maxDepth > 10)) {
|
|
294
|
+
throw new GraphRequestError("bb/graph: params.maxDepth must be an integer in [1, 10]");
|
|
295
|
+
}
|
|
296
|
+
if (params.relationshipTypes !== void 0) {
|
|
297
|
+
if (!Array.isArray(params.relationshipTypes) || params.relationshipTypes.some((t) => typeof t !== "string" || t.length === 0)) {
|
|
298
|
+
throw new GraphRequestError("bb/graph: params.relationshipTypes must be an array of non-empty strings");
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (params.includeCrossLanguage !== void 0 && typeof params.includeCrossLanguage !== "boolean") {
|
|
302
|
+
throw new GraphRequestError("bb/graph: params.includeCrossLanguage must be a boolean");
|
|
303
|
+
}
|
|
304
|
+
if (db === null || !isIndexedWorkspace(db, projectId)) {
|
|
305
|
+
throw new GraphRequestError("bb/graph: workspace is not indexed \u2014 run `bb index` first (declared error: an unindexed workspace has no graph to serve)");
|
|
306
|
+
}
|
|
307
|
+
const result = await resolveTraversalRoot(deps, db, projectId, params);
|
|
308
|
+
for (const edge of [...result.callers ?? [], ...result.callees ?? []]) {
|
|
309
|
+
if (typeof edge.rowId !== "string" || edge.rowId.length === 0) {
|
|
310
|
+
throw new GraphRequestError(`bb/graph: internal consistency failure \u2014 edge ${edge.from} -> ${edge.to} has no brain_relationship row id (refusing to serve untraceable data)`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
const root = result.root;
|
|
315
|
+
const rootQualified = root?.id ? db.prepare("SELECT qualified_name FROM brain_symbol WHERE id = ?").get(root.id)?.qualified_name ?? null : null;
|
|
316
|
+
const annRows = db.prepare(
|
|
317
|
+
"SELECT author_class, tool_identity, body, time_updated FROM brain_annotation WHERE project_id = ? AND (symbol_name = ? OR symbol_name = ?) AND (symbol_path IS NULL OR symbol_path = ? OR symbol_path = ?) ORDER BY time_updated DESC, id"
|
|
318
|
+
).all(projectId, root?.name ?? "", rootQualified, root?.file ?? "", root?.filePath ?? "");
|
|
319
|
+
result.annotations = annRows;
|
|
320
|
+
} catch {
|
|
321
|
+
;
|
|
322
|
+
result.annotations = [];
|
|
323
|
+
}
|
|
324
|
+
if (params.mode === GRAPH_MODE_USAGES) {
|
|
325
|
+
const rootNode = result.root;
|
|
326
|
+
const fileLevelRaw = db.prepare(
|
|
327
|
+
"SELECT id AS rowId, relationship_type AS relationshipType, target_external AS moduleSpecifier, confidence FROM brain_relationship WHERE project_id = ? AND source_symbol_id IS NULL AND target_symbol_id = ? AND relationship_type IN ('imports', 'exports', 'part_of')"
|
|
328
|
+
).all(projectId, rootNode.id);
|
|
329
|
+
const fileLevel = classifyFileLevel(fileLevelRaw);
|
|
330
|
+
const fileDepsRaw = db.prepare(
|
|
331
|
+
"SELECT id AS rowId, relationship_type AS relationshipType, target_external AS moduleSpecifier, confidence FROM brain_relationship WHERE project_id = ? AND relationship_type IN ('imports', 'part_of') AND source_symbol_id IS NULL AND target_symbol_id IS NULL AND source_external = ?"
|
|
332
|
+
).all(projectId, rootNode.file);
|
|
333
|
+
const dependencies = classifyFileLevel(fileDepsRaw).imports;
|
|
334
|
+
const grouped = buildGroupedUsages(result, { ...fileLevel, dependencies });
|
|
335
|
+
const res = result.resolution;
|
|
336
|
+
if (res !== void 0) grouped.resolution = res;
|
|
337
|
+
return grouped;
|
|
338
|
+
}
|
|
339
|
+
return result;
|
|
340
|
+
}
|
|
341
|
+
export {
|
|
342
|
+
GRAPH_MODE_GRAPH,
|
|
343
|
+
GRAPH_MODE_USAGES,
|
|
344
|
+
GRAPH_REQUEST_METHOD,
|
|
345
|
+
GRAPH_SCHEMA_VERSION,
|
|
346
|
+
GraphRequestError,
|
|
347
|
+
HUB_USAGES_MAX_DEPTH,
|
|
348
|
+
handleGraphRequest,
|
|
349
|
+
isIndexedWorkspace
|
|
350
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IMPACT_BUDGET,
|
|
3
|
+
computeImpact
|
|
4
|
+
} from "./chunk-BHB7BYYI.js";
|
|
5
|
+
import "./chunk-VL52PL2T.js";
|
|
6
|
+
import "./chunk-RCMTFSEF.js";
|
|
7
|
+
import "./chunk-47HKX4AJ.js";
|
|
8
|
+
import "./chunk-UUNHHX4M.js";
|
|
9
|
+
import "./chunk-KLK3PBTO.js";
|
|
10
|
+
import "./chunk-2BSKD7O3.js";
|
|
11
|
+
import "./chunk-SM7RFQRO.js";
|
|
12
|
+
import "./chunk-L5TDYKYK.js";
|
|
13
|
+
import "./chunk-ROMM6KMC.js";
|
|
14
|
+
import "./chunk-MLKGABMK.js";
|
|
15
|
+
|
|
16
|
+
// src/lsp/impact_request.ts
|
|
17
|
+
var IMPACT_REQUEST_METHOD = "bb/impact";
|
|
18
|
+
var IMPACT_SCHEMA_VERSION = 1;
|
|
19
|
+
var ImpactRequestError = class extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "ImpactRequestError";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var IMPACT_REQUEST_BUDGET = IMPACT_BUDGET;
|
|
26
|
+
async function handleImpactRequest(db, projectId, params, deps = { compute: computeImpact }) {
|
|
27
|
+
if (params === null || typeof params !== "object" || Array.isArray(params)) {
|
|
28
|
+
throw new ImpactRequestError("bb/impact: params must be an object carrying schemaVersion and symbol");
|
|
29
|
+
}
|
|
30
|
+
if (params.schemaVersion !== IMPACT_SCHEMA_VERSION) {
|
|
31
|
+
throw new ImpactRequestError(
|
|
32
|
+
`bb/impact: schema version mismatch \u2014 request carries ${JSON.stringify(params.schemaVersion) ?? "nothing"}, server implements ${IMPACT_SCHEMA_VERSION} (upgrade the client) or pin bbLsp.impactSchemaVersion)`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
if (typeof params.symbol !== "string" || params.symbol.length === 0) {
|
|
36
|
+
throw new ImpactRequestError("bb/impact: params.symbol (non-empty string) is required");
|
|
37
|
+
}
|
|
38
|
+
if (db === null) {
|
|
39
|
+
throw new ImpactRequestError(
|
|
40
|
+
"bb/impact: workspace is not indexed \u2014 run `bb index` first (declared error: an unindexed workspace has no impact to serve)"
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return await deps.compute(
|
|
45
|
+
db,
|
|
46
|
+
projectId,
|
|
47
|
+
params.symbol,
|
|
48
|
+
{},
|
|
49
|
+
typeof params.file === "string" && params.file.length > 0 ? params.file : void 0
|
|
50
|
+
);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (error instanceof Error && error.message.startsWith("bb/impact:")) throw error;
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
if (message.includes("not found") || message.includes("unknown symbol") || message.includes("cannot be resolved")) {
|
|
55
|
+
throw new ImpactRequestError(
|
|
56
|
+
`bb/impact: symbol "${params.symbol}" is not in the index \u2014 hover a symbol that was indexed (re-run \`bb index\` if it should be)`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
throw new ImpactRequestError(`bb/impact: ${message}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
IMPACT_REQUEST_BUDGET,
|
|
64
|
+
IMPACT_REQUEST_METHOD,
|
|
65
|
+
IMPACT_SCHEMA_VERSION,
|
|
66
|
+
ImpactRequestError,
|
|
67
|
+
handleImpactRequest
|
|
68
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkpointWal,
|
|
3
|
+
formatSpace,
|
|
4
|
+
reclaimSpace,
|
|
5
|
+
shouldVacuumAfterWipe,
|
|
6
|
+
spaceReport
|
|
7
|
+
} from "./chunk-DYM4FQEE.js";
|
|
8
|
+
import "./chunk-MLKGABMK.js";
|
|
9
|
+
export {
|
|
10
|
+
checkpointWal,
|
|
11
|
+
formatSpace,
|
|
12
|
+
reclaimSpace,
|
|
13
|
+
shouldVacuumAfterWipe,
|
|
14
|
+
spaceReport
|
|
15
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
INDEX_RUN_PHASES,
|
|
3
|
+
INDEX_STATUS_SCHEMA_VERSION,
|
|
4
|
+
RESUMABLE_PHASES,
|
|
5
|
+
TERMINAL_PHASES,
|
|
6
|
+
clearStatus,
|
|
7
|
+
composeStatus,
|
|
8
|
+
decideResume,
|
|
9
|
+
isRunPhase,
|
|
10
|
+
readIndexCheckpoint,
|
|
11
|
+
readLastRun,
|
|
12
|
+
readLiveStatus,
|
|
13
|
+
statusPath,
|
|
14
|
+
writeLiveStatus
|
|
15
|
+
} from "./chunk-VURYFIHW.js";
|
|
16
|
+
import "./chunk-KLK3PBTO.js";
|
|
17
|
+
import "./chunk-2BSKD7O3.js";
|
|
18
|
+
import "./chunk-ROMM6KMC.js";
|
|
19
|
+
import "./chunk-MLKGABMK.js";
|
|
20
|
+
export {
|
|
21
|
+
INDEX_RUN_PHASES,
|
|
22
|
+
INDEX_STATUS_SCHEMA_VERSION,
|
|
23
|
+
RESUMABLE_PHASES,
|
|
24
|
+
TERMINAL_PHASES,
|
|
25
|
+
clearStatus,
|
|
26
|
+
composeStatus,
|
|
27
|
+
decideResume,
|
|
28
|
+
isRunPhase,
|
|
29
|
+
readIndexCheckpoint,
|
|
30
|
+
readLastRun,
|
|
31
|
+
readLiveStatus,
|
|
32
|
+
statusPath,
|
|
33
|
+
writeLiveStatus
|
|
34
|
+
};
|